I am currently building a program that allows the user to play rock-paper-scissors against the computer through the console log. The goal is for the game to terminate after five rounds.
I was able to set up one round of the game, but I am struggling to loop it. The for loop is in line 14 of the code.
I have tried placing getComputerChoice()
and getHumanChoice()
both inside and outside the for loop and outside of playGame()
. I was expecting the game to ask for user input, display console message with a winner and increment the round winner's score, then repeat four more times before terminating and displaying a console message with the overall winner.
Instead, after accepting user input, no message displays in the console. There is also no error or warning to indicate issues with the code.
function playGame() {
var humanScore = 0;
var computerScore = 0;
for (let i = 0; i < 5; i++) {
function getComputerChoice() {
let result = Math.ceil(Math.random() * 3);
if (result === 1) {
return "rock";
} else if (result === 2) {
return "paper";
} else {
return "scissors"
}
}
const computerChoice = getComputerChoice();
function getHumanChoice() {
let humanResult = prompt("Let's play Rock, Paper, Scissors! Enter your choice:");
if (humanResult.toLowerCase() === "rock") {
return "rock";
} else if (humanResult.toLowerCase() === "paper") {
return "paper";
} else if (humanResult.toLowerCase() === "scissors") {
return "scissors";
} else {
return "to not follow the rules";
}
};
const humanChoice = getHumanChoice();
function playRound(humanChoice, computerChoice) {
if (humanChoice === "rock" && computerChoice === "paper") {
computerScore++;
console.log(`Paper beats rock! AI wins! AI:${computerScore} Human:${humanScore}`);
} else if (humanChoice === "rock" && computerChoice === "scissors") {
humanScore++;
console.log(`Rock beats scissors! You win! AI:${computerScore} Human:${humanScore}`);
} else if (humanChoice == "rock" && computerChoice === "rock") {
console.log("Y'all both picked rock! Let's try again!");
} else if (humanChoice === "paper" && computerChoice === "scissors") {
computerScore++;
console.log(`Scissors beats paper! AI wins! AI:${computerScore} Human:${humanScore}`);
} else if (humanChoice === "paper" && computerChoice === "rock") {
humanScore++;
console.log(`Paper beats rock! You win! AI:${computerScore} Human:${humanScore}`);
} else if (humanChoice === "paper" && computerChoice === "paper") {
console.log("Y'all both picked paper! Let's try again!");
} else if (humanChoice === "scissors" && computerChoice === "scissors") {
console.log("Y'all both picked scissors! Let's try again!");
} else if (humanChoice === "scissors" && computerChoice === "rock") {
computerScore++;
console.log(`Rock beats scissors! AI wins! AI:${computerScore} Human:${humanScore}`);
} else if (humanChoice === "scissors" && computerChoice === "paper") {
humanScore++;
console.log(`Scissors beats paper! You win! AI:${computerScore} Human:${humanScore}`);
} else {
console.log("Try again! That's not a choice.");
}
}
}
};
playGame();
I am currently building a program that allows the user to play rock-paper-scissors against the computer through the console log. The goal is for the game to terminate after five rounds.
I was able to set up one round of the game, but I am struggling to loop it. The for loop is in line 14 of the code.
I have tried placing getComputerChoice()
and getHumanChoice()
both inside and outside the for loop and outside of playGame()
. I was expecting the game to ask for user input, display console message with a winner and increment the round winner's score, then repeat four more times before terminating and displaying a console message with the overall winner.
Instead, after accepting user input, no message displays in the console. There is also no error or warning to indicate issues with the code.
function playGame() {
var humanScore = 0;
var computerScore = 0;
for (let i = 0; i < 5; i++) {
function getComputerChoice() {
let result = Math.ceil(Math.random() * 3);
if (result === 1) {
return "rock";
} else if (result === 2) {
return "paper";
} else {
return "scissors"
}
}
const computerChoice = getComputerChoice();
function getHumanChoice() {
let humanResult = prompt("Let's play Rock, Paper, Scissors! Enter your choice:");
if (humanResult.toLowerCase() === "rock") {
return "rock";
} else if (humanResult.toLowerCase() === "paper") {
return "paper";
} else if (humanResult.toLowerCase() === "scissors") {
return "scissors";
} else {
return "to not follow the rules";
}
};
const humanChoice = getHumanChoice();
function playRound(humanChoice, computerChoice) {
if (humanChoice === "rock" && computerChoice === "paper") {
computerScore++;
console.log(`Paper beats rock! AI wins! AI:${computerScore} Human:${humanScore}`);
} else if (humanChoice === "rock" && computerChoice === "scissors") {
humanScore++;
console.log(`Rock beats scissors! You win! AI:${computerScore} Human:${humanScore}`);
} else if (humanChoice == "rock" && computerChoice === "rock") {
console.log("Y'all both picked rock! Let's try again!");
} else if (humanChoice === "paper" && computerChoice === "scissors") {
computerScore++;
console.log(`Scissors beats paper! AI wins! AI:${computerScore} Human:${humanScore}`);
} else if (humanChoice === "paper" && computerChoice === "rock") {
humanScore++;
console.log(`Paper beats rock! You win! AI:${computerScore} Human:${humanScore}`);
} else if (humanChoice === "paper" && computerChoice === "paper") {
console.log("Y'all both picked paper! Let's try again!");
} else if (humanChoice === "scissors" && computerChoice === "scissors") {
console.log("Y'all both picked scissors! Let's try again!");
} else if (humanChoice === "scissors" && computerChoice === "rock") {
computerScore++;
console.log(`Rock beats scissors! AI wins! AI:${computerScore} Human:${humanScore}`);
} else if (humanChoice === "scissors" && computerChoice === "paper") {
humanScore++;
console.log(`Scissors beats paper! You win! AI:${computerScore} Human:${humanScore}`);
} else {
console.log("Try again! That's not a choice.");
}
}
}
};
playGame();
Share
Improve this question
edited Mar 12 at 15:43
mplungjan
179k28 gold badges182 silver badges240 bronze badges
asked Mar 12 at 15:36
Jessi B.Jessi B.
11 silver badge
6
|
Show 1 more comment
2 Answers
Reset to default 1Your issues are explained in the comments, not calling functions etc
Here is a working version, best out of 5 - it leaves the game when one of you wins, but also stops after 5 tries. I moved the functions outside and call them in the loop
function getHumanChoice() {
let humanResult = prompt("Let's play Rock, Paper, Scissors! Enter your choice:");
if (humanResult.toLowerCase() === "rock") {
return "rock";
} else if (humanResult.toLowerCase() === "paper") {
return "paper";
} else if (humanResult.toLowerCase() === "scissors") {
return "scissors";
} else {
return "to not follow the rules";
}
};
function getComputerChoice() {
let result = Math.ceil(Math.random() * 3);
if (result === 1) {
return "rock";
} else if (result === 2) {
return "paper";
} else {
return "scissors"
}
}
let humanScore = 0;
let computerScore = 0;
function playRound(humanChoice, computerChoice) {
if (humanChoice === "rock" && computerChoice === "paper") {
computerScore++;
console.log(`Paper beats rock! AI wins! AI:${computerScore} Human:${humanScore}`);
} else if (humanChoice === "rock" && computerChoice === "scissors") {
humanScore++;
console.log(`Rock beats scissors! You win! AI:${computerScore} Human:${humanScore}`);
} else if (humanChoice == "rock" && computerChoice === "rock") {
console.log("Y'all both picked rock! Let's try again!");
} else if (humanChoice === "paper" && computerChoice === "scissors") {
computerScore++;
console.log(`Scissors beats paper! AI wins! AI:${computerScore} Human:${humanScore}`);
} else if (humanChoice === "paper" && computerChoice === "rock") {
humanScore++;
console.log(`Paper beats rock! You win! AI:${computerScore} Human:${humanScore}`);
} else if (humanChoice === "paper" && computerChoice === "paper") {
console.log("Y'all both picked paper! Let's try again!");
} else if (humanChoice === "scissors" && computerChoice === "scissors") {
console.log("Y'all both picked scissors! Let's try again!");
} else if (humanChoice === "scissors" && computerChoice === "rock") {
computerScore++;
console.log(`Rock beats scissors! AI wins! AI:${computerScore} Human:${humanScore}`);
} else if (humanChoice === "scissors" && computerChoice === "paper") {
humanScore++;
console.log(`Scissors beats paper! You win! AI:${computerScore} Human:${humanScore}`);
} else {
console.log("Try again! That's not a choice.");
}
}
function playGame() {
for (let i = 0; i < 5; i++) {
const humanChoice = getHumanChoice();
const computerChoice = getComputerChoice();
playRound(humanChoice, computerChoice);
const diff = computerScore-humanScore;
if (Math.abs(diff) >= 3) {
console.log(`${diff>0 ? 'You win!': 'Computer wins'} AI:${computerScore} Human:${humanScore}`)
return;
}
}
};
playGame();
Or DRYer (and added Lizard and Spock, because I am worth it) It will play until best of 5 regardless of how long that takes by ignoring rounds that result in a tie.
const title = ["Rock", "Paper", "Scissors"]; // or ["Rock", "Paper", "Scissors", "Lizard", "Spock"]
const CHOICES = title.map(item => item.toLowerCase());
const maxTries = 5; // Sanity limit, but not for ties
const SCORES = { human: 0, computer: 0 };
const getWinningChoices = (choiceIndex) => {
const n = CHOICES.length;
if (n === 3) { // RPS
return [CHOICES[(choiceIndex + 2) % 3]];
} else if (n === 5) { // RPSLS
const WINNING_OFFSETS = {
0: [2, 3], 1: [0, 4], 2: [1, 3], 3: [4, 1], 4: [2, 0]
};
return WINNING_OFFSETS[choiceIndex].map(index => CHOICES[index]);
}
throw new Error("Unsupported number of choices");
};
const getHumanChoice = () => {
const input = prompt(`Let's play ${title.join(', ')}! Enter your choice:`).toLowerCase();
return CHOICES.includes(input) ? input : 'invalid';
};
const getComputerChoice = () => CHOICES[Math.floor(Math.random() * CHOICES.length)];
const getResultMessage = (human, computer) => {
if (human === computer) return `Both picked ${title[CHOICES.indexOf(human)]}! Try again!`;
if (human === 'invalid') return "Try again! Invalid choice.";
const humanIndex = CHOICES.indexOf(human);
const computerIndex = CHOICES.indexOf(computer);
const humanWins = getWinningChoices(humanIndex).includes(computer);
humanWins ? SCORES.human++ : SCORESputer++;
const winner = humanWins ? 'You win' : 'AI wins';
const humanTitle = title[humanIndex];
const computerTitle = title[computerIndex];
const beatsMessage = humanWins
? `${humanTitle} beats ${computerTitle}`
: `${computerTitle} beats ${humanTitle}`;
const scores = `AI:${SCORESputer} Human:${SCORES.human}`;
return `${beatsMessage}! ${winner}! ${scores}`;
};
const playRound = (human, computer) => console.log(getResultMessage(human, computer));
const playGame = () => {
const winsNeeded = Math.ceil(maxTries / 2); // e.g., 3 wins for best of 5
let decisiveRounds = 0;
while (SCORES.human < winsNeeded && SCORESputer < winsNeeded) {
const human = getHumanChoice();
const computer = getComputerChoice();
const result = getResultMessage(human, computer);
console.log(result);
if (human !== computer && human !== 'invalid') { // Only increment if not a tie or invalid
decisiveRounds++;
}
if (decisiveRounds >= maxTries) break; // Safety net to prevent infinite loops
}
const finalMessage = SCORES.human > SCORESputer
? "You win the game!"
: "Computer wins the game!";
console.log(`${finalMessage} Final score - AI:${SCORESputer} Human:${SCORES.human}`);
};
playGame();
Firstly, the main problem is that you never call playRound()
, so all the playGame
function does is prompt for input 5 times and then stop. This is a fairly obvious omission. Once you fix that, it seems to work as intended.
Secondly your code is badly laid-out, making it hard to see the wood for the trees. Aside from specialised cases there's rarely a good reason for functions to be declared inside other functions, and certainly not to be interspersed amongst your main logic - which then makes that logic a lot harder to follow when reading and debugging the code. So the first step I took was to move all the function declarations to be independent, and out of the way of the logic in the playGame function.
Thirdly, although this isn't a functional problem in that your current code would work with the modification mentioned in point 1, there's a huge amount of unnecessary repetition of nearly-identical code, which could actually be made shorter, more readable and more maintainable by better use of variables and objects. So I've made a version of the code using that approach, to show how it could be done with far less code. The first snippet in mplungjan's answer is far closer to your original, with only the most essential fixes.
function getComputerChoice() {
let result = Math.floor(Math.random() * 3);
return choices[result];
}
function getHumanChoice() {
let humanResult = prompt(
"Let's play Rock, Paper, Scissors! Enter your choice:",
)
if (choices.includes(humanResult.toLowerCase())) {
return humanResult.toLowerCase();
} else {
return false;
}
}
function playRound(chosenValues) {
var hChoice = choices.indexOf(chosenValues["human"]);
var cChoice = choices.indexOf(chosenValues["computer"]);
var winner = "";
var loser = "";
if (hChoice == cChoice) {
console.log(`Y'all both picked ${chosenValues["human"]}! Let's try again!`);
return;
}
if (hChoice == 0 && cChoice == 2) {
winner = "human";
loser = "computer";
} else if (cChoice == 0 && hChoice == 2) {
winner = "computer";
loser = "human";
} else if (hChoice > cChoice) {
winner = "human";
loser = "computer";
} else if (cChoice > hChoice) {
winner = "computer";
loser = "human";
}
scores[winner]++;
console.log(`${chosenValues[winner]} beats ${chosenValues[loser]}! Computer: ${scores["computer"]} Human: ${scores["human"]}`);
}
function playGame() {
for (let i = 0; i < 5; i++) {
const computerChoice = getComputerChoice();
const humanChoice = getHumanChoice();
if (humanChoice !== false) {
var chosenValues = {
"human": humanChoice,
"computer": computerChoice
};
playRound(chosenValues);
} else {
console.log("Invalid or cancelled human choice, no round played");
}
}
}
var scores = {
"human": 0,
"computer": 0
}
var choices = ["rock", "paper", "scissors"];
playGame();
playRound()
(actually, this code doesn't even callplayGame()
) – mykaf Commented Mar 12 at 15:41function getHumanChoice() { let humanResult = prompt("Let's play Rock, Paper, Scissors! Enter your choice:",""); return ['rock','paper','scissors'].includes(humanResult.toLowerCase()) || "to not follow the rules";}
– mplungjan Commented Mar 12 at 15:46playRound()
still isn't called - so it prompts 5 times then quits. – fdomn-m Commented Mar 12 at 15:47playRound(humanChoice, computerChoice);
(or remove the function declaration and just have that code run after prompting for humanChoice) – fdomn-m Commented Mar 12 at 15:49