why is my classlist.remove not removing the class? - javascript

i'm currently working on a paper, rock, scissors game. i have pretty much everything working except getting a rematch button to show up at the end of a game. i've been able to successfully hide the button by grabbing it const rematchButton = document.querySelector('.hiddenButton'); and adding a classlist of hidden with rematchButton.classList.add('hidden');. in the css file, i have the class of hidden set to display: none;. i have a message that will show up once the player or computer has reached 5 wins and have added rematchButton.classList.remove('hidden'); which i would expect for the rematch button to then show up alongside the "game over" message but the button is still not showing up, only the "game over" message shows up. am i putting the classlist.remove in the wrong place?
this is the portion of my html file that contains the rematch button:
<div id="results">
<div class="rematchGroup">
<!-- <img src="photos/rematch.jpg"> -->
<br>
<button class="buttons hiddenButton">rematch?</button>
</div>
</div>
and this is the javascript file:
// DECLARES A VARIABLE TO HOLD AN ARRAY OF CHOICES
const choices = ['rock', 'paper', 'scissors'];
// DECLARES A VARIABLE FOR PLAYERSCORE AND COMPUTERSCORE AND SETS THEM TO 0
let playerScore = 0;
let computerScore = 0;
// DECLARES A VARIABLE FOR PLAYERSELECTION AND SETS IT TO AN EMPTY STRING
let playerSelection = '';
// DECLARES VARIABLES FOR ROCK, PAPER, & SCISSORS AND ASSIGNS IT TO THE RPS BUTTON ID'S
const rock = document.querySelector('#rock');
const paper = document.querySelector('#paper');
const scissors = document.querySelector('#scissors');
const rematchButton = document.querySelector('.hiddenButton');
rematchButton.classList.add('hidden');
// FUNCTION TO SELECT ONE OF THE CHOICES ARRAYS AT RANDOM
function computerPlay() {
return choices[~~(Math.random() * choices.length)];
}
// EVENTLISTENERS FOR BUTTON CLICKS TO CORRELATE WITH PLAYERSELECTION
rock.addEventListener('click', () => {
playerSelection = 'rock';
playGame();
});
paper.addEventListener('click', () => {
playerSelection = 'paper';
playGame();
});
scissors.addEventListener('click', () => {
playerSelection = 'scissors';
playGame();
});
// FUNCTION TO COMPARE PLAYERSELECTION WITH COMPUTERSELECTION
// INCREMENTS THE PLAYER & COMPUTER SCORE
// DISPLAYS MESSAGE SUMMARY OF WHO WON THE ROUND
function playRound(playerSelection, computerSelection) {
if (playerSelection === computerSelection) {
document.getElementById('results').innerHTML = 'you\'ve tied!'
} else if (computerSelection === 'paper' && playerSelection === 'rock') {
document.getElementById('results').innerHTML = 'you\'ve lost that round! you chose rock, the computer chose paper.';
computerScore += 1;
} else if (computerSelection === 'scissors' && playerSelection === 'paper') {
document.getElementById('results').innerHTML = 'you\'ve lost that round! you chose paper, the computer chose scissors.';
computerScore += 1;
} else if (computerSelection === 'rock' && playerSelection === 'scissors') {
document.getElementById('results').innerHTML = 'you\'ve lost that round! you chose scissors, the computer chose rock.';
computerScore += 1;
} else if (computerSelection === 'rock' && playerSelection === 'paper') {
document.getElementById('results').innerHTML = 'you\'ve won that round! you chose paper, the computer chose rock.';
playerScore += 1;
} else if (computerSelection === 'paper' && playerSelection === 'scissors') {
document.getElementById('results').innerHTML = 'you\'ve won that round! you chose scissors, the computer chose paper.';
playerScore += 1;
} else if (computerSelection === 'scissors' && playerSelection === 'rock') {
document.getElementById('results').innerHTML = 'you\'ve won that round! you chose rock, the computer chose scissors.';
playerScore += 1;
} else {
document.getElementById('results').innerHTML = 'that\'s not an acceptable answer!'
}
}
// FUNCTION THAT ASSIGNS COMPUTERPLAY(FUNCTION) TO COMPUTERSELECTION(VARIABLE)
// RUNS THE PLAYROUND FUNCTION
// DISPLAYS COMPUTER & PLAYER SCORE
// RUNS THE ENDGAME FUNCTION WHEN PLAYER OR COMPUTER REACHES 5 WINS
function playGame() {
computerSelection = computerPlay();
playRound(playerSelection, computerSelection);
// const results = document.getElementById('results');
// const resultsContent = document.createElement('div');
// resultsContent.textContent = roundResult;
// results.appendChild(resultsContent);
const score = document.getElementById('roundScore');
document.getElementById('roundScore').innerHTML = `player score: ${playerScore} | computer score: ${computerScore}`;
if (playerScore < 5 && computerScore < 5) {
return;
} else if (playerScore === 5 || computerScore === 5) {
endGame();
} else if (playerScore === 6 || computerScore === 6) {
location.reload();
}
}
// FUNCTION THAT DISPLAYS GAME OVER MESSAGE WHEN RAN
function endGame() {
if (playerScore > computerScore) {
document.getElementById('results').innerHTML = 'GAME OVER <BR> you win! you\'ve beat the computer to 5 wins.';
rematchButton.classList.remove('hidden');
} else if (computerScore > playerScore) {
document.getElementById('results').innerHTML = 'GAME OVER <BR> you lose! the computer has beat you to 5 wins';
rematchButton.classList.remove('hidden');
}
}

The culprit is this line:
document.getElementById('results').innerHTML = 'GAME OVER <BR> you win! you\'ve beat the computer to 5 wins.';
(and its equivalent when you lose).
This replaces the entire content of the results div with your game over message - anything else that's there already is removed from the DOM.
But, what's already there includes your rematch button - so removing a class from it has no noticeable effect, it's no longer in the document!
The easiest fix based on how your code is currently set up is probably as follows: add a new div inside your results one, specifically to hold the message:
<div id="results">
<div id="results-message"></div>
<div class="rematchGroup">
<!-- <img src="photos/rematch.jpg"> -->
<br>
<button class="buttons hiddenButton">rematch?</button>
</div>
</div>
And then for the above line that sets the contents of the results div to the game over message, just set the contents of this inner div instead:
document.getElementById('results-message').innerHTML = 'GAME OVER <BR> you win! you\'ve beat the computer to 5 wins.';
(and similarly for the other one).
That will only overwrite any existing message, but leave the other DOM elements, including the rematch button, as they are.

Related

I'm making a rock-paper-scissors game with multiples rounds, but I'm having problems storing the number of player's victory. What am I doing wrong?

`
I'm making a rock-paper-scissors game with multiples rounds, but I'm having problems storing the number of player's victory. What am I doing wrong?
// THIS FUNCTION DECIDES IF THE COMPUTER CHOOSES ROCK, PAPER OR SCISSOS
function getComputerChoice () {
let rand = Math.floor(Math.random() * 10);
if (rand <= 3) {
return "Rock"
} else if (rand <= 6) {
return "Paper"
} else {
return "Scissors"
}}
// TESTING PLAYROUND FUNCTION
function playRound(playerSelection, computerSelection) {
const loseMessage = "You lose! Paper beats Rock";
const winMessage = "You win! Rock beats Scissors";
const drawMessage = "Draw. You and the computer chose Rock"
if (computerSelection === "Paper" && playerSelection === "Rock") {
alert (loseMessage);
return loseMessage
} else if (computerSelection === "Rock" && playerSelection === "Rock") {
alert(drawMessage);
return drawMessage
} else if (computerSelection === "Scissors" && playerSelection === "Rock") {
alert(winMessage);
return winMessage
} else {
alert("Something went wrong")
}
}
let playerScore = 0;
function updatePlayerScore1() {
let playRoundResults = playRound();
if (playRoundResults === "You win! Rock beats Scissors") {
playerScore += 1;
}
else {
playerScore += 0
}
return playerScore;
}
playRound(prompt("Rock, Paper or Scissors?", "Rock"), getComputerChoice());
alert (updatePlayerScore1());
`
I was expecting the updatePlayerScore1 function would store the number of player victories and alert it.
I don't think you run your updatePlayerScore(). It should run outside your alert. Instead put the player score inside the alert(playerScore)
When u declared function playRound(playerSelection, computerSelection)
here that you were going to pass two arguments but in the
function updatePlayerScore1() {
let playRoundResults = playRound();
***
}
u use didn't pass either one.
You can change your code to this and try
function updatePlayerScore1() {
let playRoundResults = playRound('Rock', getComputerChoice());
***
}
I think u should use var instead of let
Using let will not update your score, it still changes in the updatePlayerScore1 function but not in the global scope
And you should run playRound function inside your updatePlayerScore1 function, like this
function updatePlayerScore1() {
let playRoundResults = playRound(prompt("Rock, Paper or Scissors?", "Rock"), getComputerChoice());
if (playRoundResults === "You win! Rock beats Scissors") {
playerScore += 1;
}
else {
playerScore += 0
}
return playerScore;
}
let playRoundResults = playRound();
This line is producing the error, the function playRound() requires two arguments, but you are not providing any.
Resolve this line you will get the answer. If you are not able to find solution ,compare your code with below.
function updatePlayerScore1(message) {
let playRoundResults = message;
if (playRoundResults === "You win! Rock beats Scissors") {
playerScore += 1;
}
else {
playerScore += 0 ;
}
return playerScore;
}
let message = playRound(prompt("Rock, Paper or Scissors?", "Rock"), getComputerChoice());
alert (updatePlayerScore1());
There multiple combinations of draws, wins and losses. (For example, you can Win by picking Stone against scissors, but also by picking paper against rock). You'd have to consider all those possibilities in order for your code to work. (9 in total to be exact). I would suggest you create the message the player gets dynamically, especially nice to know how to do this if you go on to create games with even more possible outcomes.
The first function I wrote does exactly that ... it takes 2 picks as arguments. And bases on those it figures out if it is a draw, win or loss. And then inserts the picks in the appropriate message (way less work, especially if you add possible outcomes)
For your updatePlayerScore you only care if it was a win or not. So you split() the result message so that you only are left with either "you win" "you loose" or "draw". Then you can just check if it says "win" if it does add 1 to your score, if not just do nothing.
function results (yourPick, pcPick) {
let winningCombinations = {rock: "scissors", paper: "rock", scissors: "paper"}
if (yourPick === pcPick) return `Draw! bot of you picked ${yourPick}`
if (pcPick === winningCombinations[yourPick]) return `You win! ${yourPick} beats ${pcPick}`
return `You lose! ${yourPick} loses to ${pcPick}`
}
let playerScore = 0
function updatePlayerScore (result) {
let basicResult = result.split("!")[0]
if (basicResult === "You win") playerScore++
}

Function is not called when button is clicked but works fine in console

I am trying to call a function with a specific parameter when button is clicked but it just won't work. Functions playRock and playRound work when tested in console but not with event listener. Please let me know what the problem is, I spent 8h trying to make it work.
It may have something to do with my lack of understanding how callback functions work. I could really use an example on how to call function playRound('rock') when button is pressed.
All examples I found online would have functions without parameters in them or a confusing callback functions.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="rockbtn">Rock</button>
<button id="papertn">Paper</button>
<button id="scissorsbtn">Scissors</button>
<script>
// Call PlayRock upon clicking button #rockbtn
const rockbtn = document.querySelector('#rockbtn');
rockbtn.addEventListener('click', playRock);
// Call function playRound with propery 'rock'
function playRock() {
result = playRound('rock');
return result
}
// Randomly selects computer's choice out of rock, paper or scissors
function computerPlay() {
const choices = ['rock', 'paper', 'scissors'];
let choice = choices[Math.floor(Math.random()*choices.length)];
return choice
}
// Plays round of rock, paper, scissors between computer and player
function playRound(playerSelection) {
playerSelection = playerSelection.toLowerCase();
computerSelection = computerPlay();
let result;
if (playerSelection !== 'rock' & playerSelection !== 'paper' & playerSelection !== 'scissors'){
result = 'There is no such choice. Please choose either rock, paper or scissors.';
} else if (playerSelection === computerSelection) {
result = 'It is a draw!';
} else if (playerSelection === 'rock' & computerSelection === 'paper') {
result = 'You lost! Paper beats rock.';
} else if (playerSelection === 'rock' & computerSelection === 'scissors') {
result = 'You won! Rock beats scissors.';
} else if (playerSelection === 'paper' & computerSelection === 'scissors') {
result = 'You lost! Scissors beat paper.';
} else if (playerSelection === 'paper' & computerSelection === 'rock') {
result = 'You won! Paper beats rock.';
} else if (playerSelection === 'scissors' & computerSelection === 'paper') {
result = 'You won! Scissors beat paper.';
} else if (playerSelection === 'scissors' & computerSelection === 'rock') {
result = 'You lost! Rock beats scissors.';
}
return result
}
/* function game() {
let playerScore = 0;
let computerScore = 0;
let finalResult;
for (let i = 0; i < 5; i++) {
let outcome = playRound();
if (roundResult = outcome.includes('won')) {
playerScore += 1;
console.log('You won this round!');
} else if (roundResult = outcome.includes('lost')) {
computerScore += 1;
console.log('You won this round!');
} else {
console.log('This round ended in a draw!');
}
}
if (playerScore > computerScore) {
finalResult = `Congratulations! You won ${playerScore} to ${computerScore}!`;
} else {
finalResult = `You lost ${playerScore} to ${computerScore}`;
}
return finalResult;
}
*/
</script>
</body>
</html>
// Call PlayRock upon clicking button #rockbtn
const rockbtn = document.querySelector('#rockbtn');
rockbtn.addEventListener('click', playRock);
// Call function playRound with propery 'rock'
function playRock() {
result = playRound('rock');
return result
}
// Randomly selects computer's choice out of rock, paper or scissors
function computerPlay() {
const choices = ['rock', 'paper', 'scissors'];
let choice = choices[Math.floor(Math.random() * choices.length)];
return choice
}
// Plays round of rock, paper, scissors between computer and player
function playRound(playerSelection) {
playerSelection = playerSelection.toLowerCase();
computerSelection = computerPlay();
let result;
if (playerSelection !== 'rock' & playerSelection !== 'paper' & playerSelection !== 'scissors') {
result = 'There is no such choice. Please choose either rock, paper or scissors.';
} else if (playerSelection === computerSelection) {
result = 'It is a draw!';
} else if (playerSelection === 'rock' & computerSelection === 'paper') {
result = 'You lost! Paper beats rock.';
} else if (playerSelection === 'rock' & computerSelection === 'scissors') {
result = 'You won! Rock beats scissors.';
} else if (playerSelection === 'paper' & computerSelection === 'scissors') {
result = 'You lost! Scissors beat paper.';
} else if (playerSelection === 'paper' & computerSelection === 'rock') {
result = 'You won! Paper beats rock.';
} else if (playerSelection === 'scissors' & computerSelection === 'paper') {
result = 'You won! Scissors beat paper.';
} else if (playerSelection === 'scissors' & computerSelection === 'rock') {
result = 'You lost! Rock beats scissors.';
}
return result
}
/* function game() {
let playerScore = 0;
let computerScore = 0;
let finalResult;
for (let i = 0; i < 5; i++) {
let outcome = playRound();
if (roundResult = outcome.includes('won')) {
playerScore += 1;
console.log('You won this round!');
} else if (roundResult = outcome.includes('lost')) {
computerScore += 1;
console.log('You won this round!');
} else {
console.log('This round ended in a draw!');
}
}
if (playerScore > computerScore) {
finalResult = `Congratulations! You won ${playerScore} to ${computerScore}!`;
} else {
finalResult = `You lost ${playerScore} to ${computerScore}`;
}
return finalResult;
}
*/
<button id="rockbtn">Rock</button>
<button id="papertn">Paper</button>
<button id="scissorsbtn">Scissors</button>
In functions, when you return something, that is just passing that data to the caller of that function. It doesn't show it to the user.
In the below example, the user will not have any clue that aa was returned as it isn't being shown or alerted in anyway.
function test(){
return test2("aa");
}
function test2(str){
return str;
}
For learning, at the end of function playRound(playerSelection) {
just add alert(result);
That will just popup a message to the user telling them the result. There are many other ways to do this, this is just the easiest for learning.
you can also use console.log(result); to show the results in the console.
In the below code, I add a class to all of the buttons, and use a data attribute to hold the button's action (ie rock, paper, scissors).
Then in the javascript I loop through the buttons and add an event handler to each that grabs that data attribute and passes it to playRound.
For testing, I didn't use your for playRound function, mine is for demo purposes only.
let btns = document.querySelectorAll(".btn");
function playRound(action){
console.log(action)
}
btns.forEach(function(el){
el.addEventListener("click",function(e){
playRound(e.target.getAttribute("data-action"));
});
});
<button class="btn" data-action="rock">Rock</button>
<button class="btn" data-action="paper">Paper</button>
<button class="btn" data-action="scissors">Scissors</button>

Rock, Paper, Scissors: Scores remain at 0 on the first round

As you can tell by my messy code, I am still a beginner at JavaScript so I'm really sorry If this will hurt your eyes.
I am working on this Rock, Paper, Scissors project from The Odin Project where we would add a simple UI to it by applying DOM Methods. To be honest, I really don't know if I'm doing this right. I feel like the if statements shouldn't be inside the event listener but this is the only way I have found to make the tallying of scores work. By putting the code here I made it playable, but not quite right:
let playerScore = 0;
let computerScore = 0;
let scores = document.createElement('p');
let body = document.querySelector('body');
const results = document.createElement('div');
body.appendChild(results);
const buttons = document.querySelectorAll('button');
buttons.forEach((button) => {
button.addEventListener('click', () => {
let playerSelection = button.className;
let computerSelection = computerPlay();
let roundResult = playRound(playerSelection, computerSelection);
console.log(roundResult);
score();
gameEnd();
if (roundResult === 'playerWin') {
playerScore++;
} else if (roundResult === 'computerWin') {
computerScore++;
}
})
})
//computer pick
function computerPlay() {
const pick = ['rock', 'paper', 'scissors'];
return pick[Math.floor(Math.random() * pick.length)];
}
// Round Play
function playRound(playerSelection, computerSelection) {
//message that specifies the winner
let tie = `It's a tie you both picked ${playerSelection}`;
let playerWin = `You win this round! ${playerSelection} beats ${computerSelection}`;
let computerWin = `You lose this round! ${computerSelection} beats
${playerSelection}`;
if(playerSelection === computerSelection) {
results.innerHTML = tie;
return 'tie';
} else if (playerSelection === 'rock' && computerSelection === 'scisors') {
results.innerHTML = playerWin;
return 'playerWin';
} else if (playerSelection === 'paper' && computerSelection === 'rock') {
results.innerHTML = playerWin;
return 'playerWin';
} else if (playerSelection === 'scissors' && computerSelection === 'paper') {
results.innerHTML = playerWin;
return 'playerWin';
} else {
results.innerHTML = computerWin;
return 'computerWin';
}
}
function score() {
//new element where score would be seen
scores.innerHTML = `player: ${playerScore} | computer: ${computerScore}`;
body.appendChild(scores);
}
function gameEnd() {
if(playerScore === 5 || computerScore === 5) {
document.querySelector('.rock').disabled = true;
document.querySelector('.paper').disabled = true;
document.querySelector('.scissors').disabled = true;
if (playerScore > computerScore) {
alert('You win the game');
} else if (computerScore > playerScore) {
alert('Aww you lose');
}
}
}
<button class="rock">Rock</button>
<button class="paper">Paper</button>
<button class="scissors">Scissors</button>
Here's the problem, scores remain both at 0 after the first round. It would show who the winner is but it won't tally its score until I have picked for the next round. Where exactly did I go wrong with this one? (feels like in everything I'm genuinely sorry if my explanation sounds as confusing as my code.)
Anyways this is what the initial code looks like, before applying the DOM Methods.
I was initially trying to use this code but I cant even tally the scores with this one because I can't seem to get the return value of of the function playRound().
function computerPlay() {
const pick = ['rock', 'paper', 'scissors'];
return pick[Math.floor(Math.random() * pick.length)];
}
function playRound(playerSelection, computerSelection) {
if (playerSelection === computerSelection) {
alert(`It's a tie! you both picked ${playerSelection}`);
return "tie";
} else if (playerSelection !== "rock" && playerSelection !== "paper" &&
playerSelection !== "scissors"){
alert(`You sure about using ${playerSelection} on a game of "Rock, Paper,
Scissors"?`)
} else if (playerSelection === "rock" && computerSelection === "scissors") {
alert(`You win this round! ${playerSelection} beats ${computerSelection}`);
return "playerWin";
} else if (playerSelection === "paper" && computerSelection === "rock") {
alert(`You win this round! ${playerSelection} beats ${computerSelection}`);
return "playerWin";
} else if (playerSelection === "scissors" && computerSelection === "paper") {
alert(`You win this! ${playerSelection} beats ${computerSelection}`);
return "playerWin";
} else {
alert(`You lose this round! ${computerSelection} beats ${playerSelection}`);
return "botWin";
}
}
const computerSelection = computerPlay();
// to loop the game until 5 rounds
function game() {
let playerScore = 0;
let botScore = 0;
let gameWinner = '';
for (let i = 0; i < 5; i++) {
let playerSelection = prompt(`Round ${i+1}: Choose among "Rock, Paper, Scissors"
as your weapon`).toLowerCase();
let roundResult = playRound(playerSelection, computerPlay());
if (roundResult === "playerWin" ) {
playerScore++;
} else if (roundResult === "botWin" ) {
botScore++;
}
}
if (playerScore > botScore) {
gameWinner = 'You win!';
} else if (botScore > playerScore) {
gameWinner = 'You lose, Computer wins!';
} else {
gameWinner = 'Draw';
}
alert(`Player: ${playerScore} | Bot: ${botScore}`);
if (gameWinner === 'Draw') {
alert("There is no match winner, draw!");
} else {
alert(`${gameWinner}`);
}
}
game();
between these codes which is more likely to be fixed? or would it be better to completely throw this code and just start anew?
The problem is in this part of the code:
score();
gameEnd();
if (roundResult === 'playerWin') {
playerScore++;
} else if (roundResult === 'computerWin') {
computerScore++;
}
score() will update the score in the HTML page, but at that moment the scores have not been updated yet. That only happens later in that if ... else if block.
So the solution is to first update the score, and then to call score():
score();
gameEnd();
if (roundResult === 'playerWin') {
playerScore++;
} else if (roundResult === 'computerWin') {
computerScore++;
}
There is another issue related to this: at the end of the game (when a player reaches 5 points), gameEnd() will call alert. But alert does not allow the page to actually display the latest changes. Instead it blocks any update to it. I would display the game-over message in an HTML element instead of in an alert, just like you already do for the scores. Alternatively, you could delay the execution of alert with a timer, but I would just avoid using alert.
Here is what you can do in the function gameEnd where you currently use alert:
if (playerScore > computerScore) {
results.innerHTML += '<p><b>You win the game</b>';
} else if (computerScore > playerScore) {
results.innerHTML += '<p><b>Aww you lose</b>';
}

For loop works well on Firefox but not on Chrome

I'm trying to understand why my code works well on Firefox and not on Chrome.
Basically what happens is that on Firefox the loop works and it prints the outputs on the page at every iteration and at the end.
On Chrome it only prints some of the outputs at the end of the loop.
I read that it might have to do with the way I'm asking the code to print the output on the page, which is .textContent, but I also tried to use .innerHtml and the problem persists.
The code is a bit long and I'm sure there is a shorter cleaner way to write, but it is my first project and this is the best I could do at this stage.
Thank you for your help :)
Here is what the html looks like:
const forma = document.querySelector('form');
const out0 = document.getElementById('user-choice');
const out1 = document.getElementById('computer-choice');
const out2 = document.getElementById('game-result');
const out3 = document.getElementById('user-score');
const out4 = document.getElementById('computer-score');
const out5 = document.getElementById('final-result');
// get a ramdom choice between Rock-paper-scissor from Computer
let choices = ['rock', 'paper', 'scissors'];
let randomValue = function computerPlay() {
let randomChoice = choices[Math.floor(Math.random() * choices.length)];
out1.textContent = randomChoice;
return randomChoice;
};
function game() {
let userScore = 0;
let computerScore = 0;
// iterate the function playRound 5 times with a for loop
for (let i = 0; i < 5; i++) {
// prompt an initial message "Rock, paper, scissor" to ask the user to input one of the 3
let sign = prompt("Rock, paper or scissors?");
// use a function to compare the random choice from computer with what the user has input in the prompt and return a result
function playRound(playerSelection, computerSelection) {
if (playerSelection == "rock" && computerSelection == choices[0]) {
i = i -1;
return "It's a tie! Play again!";
} else if (playerSelection == "rock" && computerSelection == choices[1]) {
computerScore = computerScore + 1;
out4.textContent = computerScore;
// this is when the computer wins
if(computerScore == 3) {
i = 5; // so that it practically breaks out of the loop
out5.textContent = "Unfortunately you lost the game :("
} else return "You lose this round! Paper beats rock.";
} else if (playerSelection == "rock" && computerSelection == choices[2]) {
userScore = userScore + 1;
out3.textContent = userScore;
if(userScore == 3) {
i = 5;
out5.textContent = "Congratulations, you won the game!"
} else return "You win this round! Rock beats scissors.";
} else if (playerSelection == "paper" && computerSelection == choices[0]) {
userScore = userScore + 1;
out3.textContent = userScore;
if(userScore == 3) {
i = 5;
out5.textContent = "Congratulations, you won the game!"
} else return "You win this round! Paper beats rock.";
} else if (playerSelection == "paper" && computerSelection == choices[1]) {
i = i -1;
return "It's a tie! Play again!";
} else if (playerSelection == "paper" && computerSelection == choices[2]) {
computerScore = computerScore + 1;
out4.textContent = computerScore;
if (computerScore == 3) {
i = 5;
out5.textContent = "Unfortunately you lost the game :("
} else return "You lose this round! Scissors beat paper.";
} else if (playerSelection == "scissors" && computerSelection == choices[0]) {
computerScore = computerScore + 1;
out4.textContent = computerScore;
if (computerScore == 3) {
i = 5;
out5.textContent = "Unfortunately you lost the game :("
} else return "You lose this round! Rock beats scissors.";
} else if (playerSelection == "scissors" && computerSelection == choices[1]) {
userScore = userScore + 1;
out3.textContent = userScore;
if(userScore == 3) {
i = 5;
out5.textContent = "Congratulations, you won the game!"
} else return "You win this round! Scissors beat paper.";
} else if (playerSelection == "scissors" && computerSelection == choices[2]) {
i = i -1;
return "It's a tie! Play again!";
// this currently doesn't work as it tries to convert the playerSelection toLowerCase, as requested in the let playerSelection = sign.toLowerCase(), but it cannot because the sign is null and so it returns an error that sign is null
} else if(playerSelection === '' || playerSelection === null) {
i = 0;
} else {
i = i -1;
return "I think you forgot how to play this game!";
}
}
// store the playerSelection argument value (equal to user input made lower case) in a variable
let playerSelection = sign.toLowerCase();
// store the computerSelection argument value (equal to radom choice determined by function randomValue) in a variable
let computerSelection = randomValue();
// print the user input made to lower case in the paragraph tag
out0.textContent = sign;
// print the return statement from the function in the out2 tag
out2.textContent= playRound(playerSelection, computerSelection);
}
}
// run the function
game();
And this is my Html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<form>
<strong>Your choice:</strong>
<output type="text" id="user-choice"></output>
</form>
</div>
<div>
<form>
<strong>Computer choice:</strong>
<output type="text" id="computer-choice"></output>
</form>
</div>
<div>
<form>
<strong>Result of this round:</strong>
<output type="text" id="game-result"></output>
</form>
</div>
<div>
<form>
<strong>User score:</strong>
<output type="number" id="user-score"></output>
</form>
</div>
<div>
<form>
<strong>Computer score:</strong>
<output type="number" id="computer-score"></output>
</form>
</div>
<div>
<form>
<strong>Game result:</strong>
<output type="text" id="final-result"></output>
</form>
</div>
<script src="script.js"></script>
</body>
</html>
You can use window.requestAnimationFrame to force the browser to render something. You will need to promisify it however, because requestAnimationFrame has a callback, and does not directly return a promise.
After doing that, your code should look like this:
const forma = document.querySelector('form');
const out0 = document.getElementById('user-choice');
const out1 = document.getElementById('computer-choice');
const out2 = document.getElementById('game-result');
const out3 = document.getElementById('user-score');
const out4 = document.getElementById('computer-score');
const out5 = document.getElementById('final-result');
// get a ramdom choice between Rock-paper-scissor from Computer
let choices = ['rock', 'paper', 'scissors'];
let userScore = 0;
let computerScore = 0;
let randomValue = function computerPlay() {
let randomChoice = choices[Math.floor(Math.random() * choices.length)];
out1.textContent = randomChoice;
return randomChoice;
};
async function game() {
// iterate the function playRound 5 times with a for loop
for (let i = 0; i < 5; i++) {
// prompt an initial message "Rock, paper, scissor" to ask the user to input one of the 3
let sign = prompt("Rock, paper or scissors?");
// use a function to compare the random choice from computer with what the user has input in the prompt and return a result
function playRound(playerSelection, computerSelection) {
if (playerSelection == "rock" && computerSelection == choices[0]) {
i = i - 1;
return "It's a tie! Play again!";
} else if (playerSelection == "rock" && computerSelection == choices[1]) {
computerScore = computerScore + 1;
out4.textContent = computerScore;
// this is when the computer wins
if (computerScore == 3) {
i = 5; // so that it practically breaks out of the loop
out5.textContent = "Unfortunately you lost the game :("
} else return "You lose this round! Paper beats rock.";
} else if (playerSelection == "rock" && computerSelection == choices[2]) {
userScore = userScore + 1;
out3.textContent = userScore;
if (userScore == 3) {
i = 5;
out5.textContent = "Congratulations, you won the game!"
} else return "You win this round! Rock beats scissors.";
} else if (playerSelection == "paper" && computerSelection == choices[0]) {
userScore = userScore + 1;
out3.textContent = userScore;
if (userScore == 3) {
i = 5;
out5.textContent = "Congratulations, you won the game!"
} else return "You win this round! Paper beats rock.";
} else if (playerSelection == "paper" && computerSelection == choices[1]) {
i = i - 1;
return "It's a tie! Play again!";
} else if (playerSelection == "paper" && computerSelection == choices[2]) {
computerScore = computerScore + 1;
out4.textContent = computerScore;
if (computerScore == 3) {
i = 5;
out5.textContent = "Unfortunately you lost the game :("
} else return "You lose this round! Scissors beat paper.";
} else if (playerSelection == "scissors" && computerSelection == choices[0]) {
computerScore = computerScore + 1;
out4.textContent = computerScore;
if (computerScore == 3) {
i = 5;
out5.textContent = "Unfortunately you lost the game :("
} else return "You lose this round! Rock beats scissors.";
} else if (playerSelection == "scissors" && computerSelection == choices[1]) {
userScore = userScore + 1;
out3.textContent = userScore;
if (userScore == 3) {
i = 5;
out5.textContent = "Congratulations, you won the game!"
} else return "You win this round! Scissors beat paper.";
} else if (playerSelection == "scissors" && computerSelection == choices[2]) {
i = i - 1;
return "It's a tie! Play again!";
// this currently doesn't work as it tries to convert the playerSelection toLowerCase, as requested in the let playerSelection = sign.toLowerCase(), but it cannot because the sign is null and so it returns an error that sign is null
} else if (playerSelection === '' || playerSelection === null) {
i = 0;
} else {
i = i - 1;
return "I think you forgot how to play this game!";
}
}
// store the playerSelection argument value (equal to user input made lower case) in a variable
let playerSelection = sign.toLowerCase();
// store the computerSelection argument value (equal to radom choice determined by function randomValue) in a variable
let computerSelection = randomValue();
// print the user input made to lower case in the paragraph tag
out0.textContent = sign;
// print the return statement from the function in the out2 tag
out2.textContent = playRound(playerSelection, computerSelection);
await promisifiedRequestAnimationFrame();
}
}
function promisifiedRequestAnimationFrame() {
return new Promise((resolve, reject) => {
window.requestAnimationFrame(() => {resolve()});
})
}
// run the function
game();
So what exactly changed?
We added a function, that returns a promise that resolves when the requestAnimationFrame is finished executing.
We made game() asynchronous. This allows us to use "await"
But why does it work?
Well, alerts, prompts and confirms are supposed to halt the code until a user does something. Firefox does not allow direct spamming of them, so there is a small time frame between your prompts on FF, but Chrome doesn't really care about that. You want a lot of prompts? Fine! By using window.requestAnimationFrame combined with await we will force chrome to wait until a frame has been drawn.

Rock, Paper, Scissors game: entering the correct value returns the wrong console.log message

Sometimes when I enter "rock" in the prompt and hit OK, the console will say "Please type Rock, Paper, or Scissors" even in case I had actually done that. I believe this is due to the else clause, I'm just not sure what I did wrong.
Also, other times when I enter "rock" in the prompt and hit OK, nothing happens in the console (no score is added). Below is the screenshot
const playerSelection = ''
const computerSelection = computerPlay()
let computerScore = 0;
let playerScore = 0;
console.log(playRound(playerSelection, computerSelection))
function computerPlay(){
let values = ['rock', 'paper', 'scissors'],
valueToUse = values [Math.floor(Math.random()* values.length)];
return valueToUse;
};
function playRound(playerSelection, computerSelection) {
while(true){
playerSelection = prompt ('Pick your poison');
if (playerSelection.toLowerCase() === 'rock' && computerPlay() === 'paper'){
computerScore += 1
console.log('Sorry! Paper beats Rock')
}
else if (playerSelection.toLowerCase() === 'rock'.toLowerCase() && computerPlay() === 'scissors'){
playerScore += 1
console.log('Good job! Rock beats Scissors');
}
else
{
console.log('Please type Rock, Paper, or Scissors')
}
console.log (`User Selection: ${playerSelection.toUpperCase()} | Player Score: ${playerScore}
Computer Selection: ${computerSelection.toUpperCase()} | Computer Score: ${computerScore}`);
}
}
You only call computerSelection once, at the beginning of pageload:
const computerSelection = computerPlay()
It then proceeds to only get used in the log:
Computer Selection: ${computerSelection.toUpperCase()} |
But your tests call computerPlay again, creating new strings for the computer every time:
if (playerSelection.toLowerCase() === 'rock' && computerPlay() === 'paper'){
// function invocation ^^^^^^^^^^^^^^
computerScore += 1
console.log('Sorry! Paper beats Rock')
}
else if (playerSelection.toLowerCase() === 'rock'.toLowerCase() && computerPlay() === 'scissors'){
// function invocation ^^^^^^^^^^^^^^
In addition to that, you aren't exhaustively testing each possibility for rock-paper-scissors (like when the player picks something other than 'rock').
To start with, call computerPlay only once, then use the computerSelection variable:
if (playerSelection.toLowerCase() === 'rock' && computerSelection === 'paper') {
computerScore += 1
console.log('Sorry! Paper beats Rock')
} else if (playerSelection.toLowerCase() === 'rock' && computerSelection === 'scissors') {
Also note that there isn't much point calling toLowerCase on something that's already a lower-cased string literal - just use the plain string.
You can update the code as following
Remove all unnecessary global variable declarations.
Remove unnecessary arguments of playRound function.
Add more logic for other player selection cases.
Nest condition for computer selection cases.
playRound();
function computerPlay(){
let values = ['rock', 'paper', 'scissors'],
valueToUse = values [Math.floor(Math.random()* values.length)];
return valueToUse;
};
function playRound() {
let playerSelection;
let computerSelection;
let playerScore = 0;
let computerScore = 0;
while(true){
playerSelection = prompt('Pick your poison').toLowerCase();
computerSelection = computerPlay();
if (playerSelection === 'rock') {
if (computerSelection === 'paper') {
computerScore += 1;
} else if (computerSelection === 'scissors') {
playerScore += 1;
}
} else if (playerSelection === 'paper') {
if (computerSelection === 'scissors') {
computerScore += 1;
} else if (computerSelection === 'rock') {
playerScore += 1;
}
} else if (playerSelection === 'scissors') {
if (computerSelection === 'rock') {
computerScore += 1;
} else if (computerSelection === 'paper') {
playerScore += 1;
}
} else {
console.log('Please type Rock, Paper, or Scissors');
continue;
}
console.log (`User Selection: ${playerSelection.toUpperCase()} | Player Score: ${playerScore}
Computer Selection: ${computerSelection.toUpperCase()} | Computer Score: ${computerScore}`);
}
}
Here is a minimalist version of the game as a complete rewrite:
function game(){
var usr, u, c, g, score=[0,0],last="";
const words=["rock","paper","scissors"];
while(usr=prompt(last+"\nScore (you:computer): "+score.join(":")+"\nYour choice:")) {
while((u=words.indexOf(usr.toLowerCase()))<0) usr=prompt("invalid choice, please enter again,\none of: "+words.join(", "));
c=Math.floor(Math.random()*3);
g=(3+u-c)%3; // who wins?
if(g) score[g-1]++;
last="you: "+words[u]+", computer: "+words[c]+" --> "
+["draw","you win!!!","you lost - sorry."][g];
}
}
game()

Categories