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);
+}