From c2dc4c8b38977849ac3c933e1946c8c5ca09f628 Mon Sep 17 00:00:00 2001 From: LukasMurdock Date: Sat, 1 Jan 2022 20:09:24 -0500 Subject: [PATCH] update acey_ducey --- 01_Acey_Ducey/javascript/.prettierrc.json | 6 + 01_Acey_Ducey/javascript/aceyducey.html | 8 +- 01_Acey_Ducey/javascript/aceyducey.js | 284 +++++++++++++++------- 01_Acey_Ducey/javascript/io.js | 29 --- 01_Acey_Ducey/javascript/util.js | 67 +++++ 5 files changed, 277 insertions(+), 117 deletions(-) create mode 100644 01_Acey_Ducey/javascript/.prettierrc.json delete mode 100644 01_Acey_Ducey/javascript/io.js create mode 100644 01_Acey_Ducey/javascript/util.js diff --git a/01_Acey_Ducey/javascript/.prettierrc.json b/01_Acey_Ducey/javascript/.prettierrc.json new file mode 100644 index 00000000..f9148847 --- /dev/null +++ b/01_Acey_Ducey/javascript/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "trailingComma": "es5", + "tabWidth": 4, + "semi": true, + "singleQuote": true +} diff --git a/01_Acey_Ducey/javascript/aceyducey.html b/01_Acey_Ducey/javascript/aceyducey.html index e526c3df..61c362a7 100644 --- a/01_Acey_Ducey/javascript/aceyducey.html +++ b/01_Acey_Ducey/javascript/aceyducey.html @@ -1,7 +1,7 @@ - - + + ACEY DUCEY -

-
+

+
diff --git a/01_Acey_Ducey/javascript/aceyducey.js b/01_Acey_Ducey/javascript/aceyducey.js
index 6c31d77c..61525a3d 100644
--- a/01_Acey_Ducey/javascript/aceyducey.js
+++ b/01_Acey_Ducey/javascript/aceyducey.js
@@ -1,100 +1,216 @@
-import { readLine, print, spaces } from "./io.js";
+// UTILITY VARIABLES
 
-const minFaceCard = 11;
-const faceCards = {
-  11: "JACK",
-  12: "QUEEN",
-  13: "KING",
-  14: "ACE"
-};
+// By default:
+// — Browsers have a window object
+// — Node.js does not
+// Checking for an undefined window object is a loose check
+// to enable browser and Node.js support
+const isRunningInBrowser = typeof window !== 'undefined';
 
-function randomCard() {
-  return Math.floor(Math.random() * 13 + 2);
+// To easily validate input strings with utility functions
+const validLowerCaseYesStrings = ['yes', 'y'];
+const validLowerCaseNoStrings = ['no', 'n'];
+const validLowerCaseYesAndNoStrings = [
+    ...validLowerCaseYesStrings,
+    ...validLowerCaseNoStrings,
+];
+// UTILITY VARIABLES
+
+// Function to get a random number (card) 2-14 (ACE is 14)
+function getRandomCard() {
+    // In our game, the value of ACE is greater than face cards;
+    // instead of having the value of ACE be 1, we’ll have it be 14.
+    // So, we want to shift the range of random numbers from 1-13 to 2-14
+    let min = 2;
+    let max = 14;
+    // Return random integer between two values, inclusive
+    return Math.floor(Math.random() * (max - min + 1) + min);
 }
 
-function printCard(card) {
-  if (card < minFaceCard) {
-    print(card);
-  } else {
-    print(faceCards[card]);
-  }
-  print("\n");
+function getGameCards() {
+    let cardOne = getRandomCard();
+    let cardTwo = getRandomCard();
+    let cardThree = getRandomCard();
+    // We want:
+    // 1. cardOne and cardTwo to be different cards
+    // 2. cardOne to be lower than cardTwo
+    // So, while cardOne is greater than or equal two cardTwo
+    // we will continue to generate random cards.
+    while (cardOne >= cardTwo) {
+        cardOne = getRandomCard();
+        cardTwo = getRandomCard();
+    }
+    return [cardOne, cardTwo, cardThree];
 }
 
-print(spaces(26) + "ACEY DUCEY CARD GAME\n");
-print(spaces(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n\n\n");
-print("ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER\n");
-print("THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP\n");
-print("YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING\n");
-print("ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE\n");
-print("A VALUE BETWEEN THE FIRST TWO.\n");
-print("IF YOU DO NOT WANT TO BET, INPUT '0'\n");
+// Function to get card value
+function getCardValue(card) {
+    let faceOrAce = {
+        11: 'JACK',
+        12: 'QUEEN',
+        13: 'KING',
+        14: 'ACE',
+    };
+    // If card value matches a key in faceOrAce, use faceOrAce value;
+    // Else, return undefined and handle with the Nullish Coalescing Operator (??)
+    // and default to card value.
+    let cardValue = faceOrAce[card] ?? card;
+    return cardValue;
+}
 
-let currentMoney = 100;
-while (true) {
-  print(`YOU NOW HAVE ${currentMoney} DOLLARS.\n\n`);
+print(spaces(26) + 'ACEY DUCEY CARD GAME');
+print(spaces(15) + 'CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n\n');
+print('ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER');
+print('THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP');
+print('YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING');
+print('ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE');
+print('A VALUE BETWEEN THE FIRST TWO.');
+print("IF YOU DO NOT WANT TO BET, INPUT '0'");
 
-  let card1, card2, currentBet;
-  do {
-    print("HERE ARE YOUR NEXT TWO CARDS: \n");
-    [card1, card2] = [randomCard(), randomCard()];
+main();
 
-    // Ensure we always show cards in order of lowest to highest, and we never
-    // get two of the same card.
-    do {
-      card1 = randomCard();
-      card2 = randomCard();
-    } while (card1 >= card2);
-
-    printCard(card1);
-    printCard(card2);
-    print("\n");
+async function main() {
+    let bet;
+    let availableDollars = 100;
 
+    // Loop game forever
     while (true) {
-      print("\nWHAT IS YOUR BET? ");
-      currentBet = parseInt(await readLine(), 10);
+        let [cardOne, cardTwo, cardThree] = getGameCards();
 
-      if (currentBet > 0) {
-        if (currentBet > currentMoney) {
-          print("SORRY, MY FRIEND, BUT YOU BET TOO MUCH.\n");
-          print(`YOU HAVE ONLY ${currentMoney} DOLLARS TO BET.\n`);
-          continue;
+        print(`YOU NOW HAVE ${availableDollars} DOLLARS.\n`);
+
+        print('HERE ARE YOUR NEXT TWO CARDS: ');
+        print(getCardValue(cardOne));
+        print(getCardValue(cardTwo));
+        print('');
+
+        // Loop until receiving a valid bet
+        let validBet = false;
+        while (!validBet) {
+            print('\nWHAT IS YOUR BET? ');
+            bet = parseInt(await input(), 10);
+            let minimumRequiredBet = 0;
+            if (bet > minimumRequiredBet) {
+                if (bet > availableDollars) {
+                    print('SORRY, MY FRIEND, BUT YOU BET TOO MUCH.');
+                    print(`YOU HAVE ONLY ${availableDollars} DOLLARS TO BET.`);
+                } else {
+                    validBet = true;
+                }
+            } else {
+                // Does not meet minimum required bet
+                print('CHICKEN!!');
+                print('');
+            }
         }
-        break;
-      }
 
-      // Invalid bet value. Output an error message and reset to undefined to
-      // restart the loop with new cards.
-      currentBet = undefined;
-      print("CHICKEN!!\n");
-      print("\n");
-      break;
+        print('\n\nHERE IS THE CARD WE DREW: ');
+        print(getCardValue(cardThree));
+
+        // Determine if player won or lost
+        if (cardThree > cardOne && cardThree < cardTwo) {
+            print('YOU WIN!!!');
+            availableDollars = availableDollars + bet;
+        } else {
+            print('SORRY, YOU LOSE');
+
+            if (bet >= availableDollars) {
+                print('');
+                print('');
+                print('SORRY, FRIEND, BUT YOU BLEW YOUR WAD.');
+                print('');
+                print('');
+                print('TRY AGAIN (YES OR NO)');
+
+                let tryAgainInput = await input();
+
+                print('');
+                print('');
+
+                if (isValidYesNoString(tryAgainInput)) {
+                    availableDollars = 100;
+                } else {
+                    print('O.K., HOPE YOU HAD FUN!');
+                    break;
+                }
+            } else {
+                availableDollars = availableDollars - bet;
+            }
+        }
     }
-  } while (currentBet === undefined);
-
-  const actualCard = randomCard();
-  print("\n\nHERE IS THE CARD WE DREW:\n")
-  printCard(actualCard);
-  print("\n\n");
-
-  if (actualCard > card1 && actualCard < card2) {
-    print("YOU WIN!!!\n");
-    currentMoney += currentBet;
-  } else {
-    print("SORRY, YOU LOSE\n");
-    if (currentBet < currentMoney) {
-      currentMoney -= currentBet;
-    } else {
-      print("\n\nSORRY, FRIEND, BUT YOU BLEW YOUR WAD.\n\n\n");
-      print("TRY AGAIN (YES OR NO)");
-      const tryAgain = await readLine();
-      print("\n\n");
-      if (tryAgain.toLowerCase() === "yes") {
-        currentMoney = 100;
-      } else {
-        print("O.K., HOPE YOU HAD FUN!");
-        break;
-      }
-    }
-  }
 }
+
+// UTILITY FUNCTIONS
+function isValidYesNoString(string) {
+    return validLowerCaseYesAndNoStrings.includes(string.toLowerCase());
+}
+
+function isValidYesString(string) {
+    return validLowerCaseYesStrings.includes(string.toLowerCase());
+}
+
+function isValidNoString(string) {
+    return validLowerCaseNoStrings.includes(string.toLowerCase());
+}
+
+function print(string) {
+    if (isRunningInBrowser) {
+        // Adds trailing newline to match console.log behavior
+        document
+            .getElementById('output')
+            .appendChild(document.createTextNode(string + '\n'));
+    } else {
+        console.log(string);
+    }
+}
+
+function input() {
+    if (isRunningInBrowser) {
+        // Accept input from the browser DOM input
+        return new Promise((resolve) => {
+            const outputElement = document.querySelector('#output');
+            const inputElement = document.createElement('input');
+            outputElement.append(inputElement);
+            inputElement.focus();
+
+            inputElement.addEventListener('keydown', (event) => {
+                if (event.key === 'Enter') {
+                    const result = inputElement.value;
+                    inputElement.remove();
+                    print(result);
+                    print('');
+                    resolve(result);
+                }
+            });
+        });
+    } else {
+        // Accept input from the command line in Node.js
+        // See: https://nodejs.dev/learn/accept-input-from-the-command-line-in-nodejs
+        return new Promise(function (resolve) {
+            const readline = require('readline').createInterface({
+                input: process.stdin,
+                output: process.stdout,
+            });
+            readline.question('', function (input) {
+                resolve(input);
+                readline.close();
+            });
+        });
+    }
+}
+
+function printInline(string) {
+    if (isRunningInBrowser) {
+        document
+            .getElementById('output')
+            .appendChild(document.createTextNode(string));
+    } else {
+        process.stdout.write(string);
+    }
+}
+
+function spaces(numberOfSpaces) {
+    return ' '.repeat(numberOfSpaces);
+}
+
+// UTILITY FUNCTIONS
diff --git a/01_Acey_Ducey/javascript/io.js b/01_Acey_Ducey/javascript/io.js
deleted file mode 100644
index a9211e9c..00000000
--- a/01_Acey_Ducey/javascript/io.js
+++ /dev/null
@@ -1,29 +0,0 @@
-const outputEl = document.querySelector("#output");
-
-export function print(string) {
-  outputEl.append(string);
-}
-
-export function readLine() {
-  return new Promise(resolve => {
-    const inputEl = document.createElement("input");
-    outputEl.append(inputEl);
-    inputEl.focus();
-
-    inputEl.addEventListener("keydown", event => {
-      if (event.key === "Enter") {
-        const result = inputEl.value;
-        inputEl.remove();
-
-        print(result);
-        print("\n");
-
-        resolve(result);
-      }
-    });
-  });
-}
-
-export function spaces(numberOfSpaces) {
-  return " ".repeat(numberOfSpaces);
-}
diff --git a/01_Acey_Ducey/javascript/util.js b/01_Acey_Ducey/javascript/util.js
new file mode 100644
index 00000000..418eff40
--- /dev/null
+++ b/01_Acey_Ducey/javascript/util.js
@@ -0,0 +1,67 @@
+// By default:
+// — Browsers have a window object
+// — Node.js does not
+// Checking for an undefined window object is a loose check
+// to enable browser and Node.js support
+const isRunningInBrowser = typeof window !== 'undefined';
+
+const outputElement = document.querySelector('#output');
+
+function print(string) {
+    if (isRunningInBrowser) {
+        // Adds trailing newline to match console.log behavior
+        document
+            .getElementById('output')
+            .appendChild(document.createTextNode(string + '\n'));
+    } else {
+        console.log(string);
+    }
+}
+
+function input() {
+    if (isRunningInBrowser) {
+        // Accept input from the browser DOM input
+        return new Promise((resolve) => {
+            const inputEl = document.createElement('input');
+            outputElement.append(inputEl);
+            inputEl.focus();
+
+            inputEl.addEventListener('keydown', (event) => {
+                if (event.key === 'Enter') {
+                    const result = inputEl.value;
+                    inputEl.remove();
+                    print(result);
+                    print('');
+                    resolve(result);
+                }
+            });
+        });
+    } else {
+        // Accept input from the command line in Node.js
+        // See: https://nodejs.dev/learn/accept-input-from-the-command-line-in-nodejs
+        return new Promise(function (resolve) {
+            const readline = require('readline').createInterface({
+                input: process.stdin,
+                output: process.stdout,
+            });
+            readline.question('', function (input) {
+                resolve(input);
+                readline.close();
+            });
+        });
+    }
+}
+
+function printInline(string) {
+    if (isRunningInBrowser) {
+        document
+            .getElementById('output')
+            .appendChild(document.createTextNode(string));
+    } else {
+        process.stdout.write(string);
+    }
+}
+
+function spaces(numberOfSpaces) {
+    return ' '.repeat(numberOfSpaces);
+}