I've been having this issue for several hours and I thought it's finally time to ask for some help. The issue is that my winning counts won't increment according to the winner declared on every of the 5 rounds.
I'm sorry if my code is messy or over complicated.
// The initial variable declarations including the user's pre-picked input/
let computerChoice;
let userChoice = 'paper';
// The function picks a random number that will change the computerChoice variable's value
function computerPlay() {
computerChoice = Math.floor(Math.random() * 3);
switch (computerChoice) {
case 0:
computerChoice = 'rock';
break;
case 1:
computerChoice = 'paper';
break;
case 2:
computerChoice = 'scissors';
break;
}
}
// The function will pick a round winner
function userPlay(userChoice) {
return userChoice.toLowerCase();
}
function playRound() {
computerPlay();
if ((computerChoice === 'rock' && userChoice === 'scissors') || (computerChoice === 'paper' && userChoice === 'rock') || (computerChoice === 'scissors' && userChoice === 'paper')) {
return `You lost! Computer chose ${computerChoice}.`
} else if (computerChoice === userChoice) {
return `It's a tie! Computer chose ${computerChoice}.`
} else {
return `You won! Computer chose ${computerChoice}.`
}
}
// The function will pick a winner of 5 rounds *not working*
function game() {
let userWinnerCount = 0;
let computerWinnerCount = 0;
let ties = 0;
for (let i = 0; i < 5; i++) {
console.log(playRound());
if (playRound() === `You won! Computer chose ${computerChoice}.`) {
userWinnerCount += 1
} else if (playRound() === `You lost! Computer chose ${computerChoice}.`) {
computerWinnerCount += 1
} else {
ties += 1
}
}
console.log(`${userWinnerCount} - times the user won / ${computerWinnerCount} - times the computer won / ${ties} - Ties`);
}
game()
Related
I'm working on Rock Paper Scissors and I'm lost at how to keep and display scores as well as determine a winner when they reach a score of 5. Right now, I'm adding +1 to the playerScore or compScore depending on the single round result, but I don't know how to display or keep track of it. Here is my code so far. Any tips are greatly appreciated!
//choices array
const choices = ["rock", "paper", "scissors"];
//set scores to 0
let playerScore = 0;
let compScore = 0;
//Get random choice from comp
function getComputerChoice() {
const randomNum = Math.floor(Math.random() * 3) //Generate random num with Math.random(), to ensure it's between 0 and 3, multiply by 3. Use Math.floor to round to down to nearest num
switch (randomNum) { //Create switch statement to take randomNum variable to perform different action based on the condition (case)
case 0:
return "rock";
case 1:
return "paper";
case 2:
return "scissors";
}
}
//single round gameplay
function playRound(playerSelection, computerSelection) {
if (playerSelection == "rock" && computerSelection == "scissors") {
//Add 1 to playerScore
playerScore+= 1
return "You win! Rock beats scissors";
} else if (playerSelection == "rock" && computerSelection == "paper") {
//Add 1 to compScore
compScore+= 1
return "You lose. Paper beats rock";
} else if (playerSelection == "scissors" && computerSelection == "paper") {
playerScore+= 1
return "You win! Scissors beat paper";
} else if (playerSelection == "scissors" && computerSelection == "rock") {
compScore+= 1
return "You lose. Rock beats scissors";
} else if (playerSelection == "paper" && computerSelection == "rock") {
playerScore+= 1
return "You win! Paper beats rock";
} else if (playerSelection == "paper" && computerSelection == "scissors") {
compScore+= 1
return "You lose. Scissors beat paper";
} else if (playerSelection === computerSelection) {
return "It's a tie";
} else {
return "Try again";
}
}
function userInput() {
let ask = false;
//while ask is still false, continue looping
while (ask == false){
const selction = prompt("Rock Paper or Scissors?")
// if the prompt return is empty
if (selction == null){
//keep looping
continue;
}
const selctionLower = selction.toLowerCase();
//ask if array of choices [rock, paper, scissors] is in the user input
if (choices.includes(selctionLower)){
//then ask is true
ask = true;
return selctionLower;
}
}
}
function game() {
//loop
for (let i = 0; i < 5; i++) {
const playerSelection = userInput();
const computerSelection = getComputerChoice();
//call playRound function
console.log(playRound(playerSelection, computerSelection));
}
}
game()
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>';
}
I'm new to coding and javascript. I'm working on an assignment where I have to create a Rock Paper Scissors game that has 2 modes, single player and best out of three. In the best out of three mode, you need to create a system to remember the score of the user and the bot. And it needs a loop to run as many rounds as possible until there is a player that wins at least two rounds. Once the game ends, you can ask the human player if he/she wants to play again using a confirm() function. I have the base game but I cant figure out how to have the game loop until one player wins 2 rounds. I also cant figure out how to add a play again option. If someone can please help I would greatly appreciate it.
const play = () => {
// set Computer Choice
var userChoice = prompt("Do you choose rock, paper or scissors?");
var computerChoice = Math.random();
if (computerChoice < 0.34) {
computerChoice = "rock";
} else if (computerChoice <= 0.67) {
computerChoice = "paper";
} else {
computerChoice = "scissors";
}
console.log("Player Choice: " + userChoice);
console.log("Computer Choice: " + computerChoice);
if (computerChoice === userChoice) {
return "The result is tie!";
}
if (computerChoice === "rock") {
if (userChoice === "scissors") {
return "Computer wins";
} else {
if (userChoice === "paper")
return "Player wins";
}
}
if (computerChoice === "paper") {
if (userChoice === "scissors") {
return "Computer wins";
} else {
if (userChoice === "rock")
return "Player wins";
}
}
if (computerChoice === "scissors") {
if (userChoice === "rock") {
return "Computer wins";
} else {
if (userChoice === "scissors")
return "Player wins";
}
}
};
const round = () => {
const res = play();
let playerScore = 0;
let computerScore = 0;
console.log(res)
cnt--
wins[cnt] = res.startsWith("Player") ? 1 : 0;
if (cnt === 0) {
const total = wins.reduce((a, b) => a + b)
console.log(`You beat the computer ${total} time${total===1?"":"s"}`)
return
}
setTimeout(round, 10) // else go again
}
let cnt = 1,
wins = [];
const mode = prompt("Please press 1 for single game mode or 2 for best out of 3 mode");
if (mode === '2') {
cnt = 3;
round()
}
You can pass a parameter to the round() function to tell it how many wins are needed. Then, put the main code in a loop:
const round = (winsNeeded) => {
let playerScore = 0;
let computerScore = 0;
while (playerScore < winsNeeded && computerScore < winsNeeded) {
const res = play();
console.log(res)
if (res[0] == 'P') playerScore++;
else if (res[0] == 'C') computerScore++;
console.log(`Score: you ${playerScore}, computer ${computerScore}`);
}
if (playerScore == winsNeeded) {
console.log("Player won that round.");
}
else {
console.log("Computer won that round.");
}
}
while (true) {
let cnt = 1;
const mode = prompt("Please press 1 for single game mode or 2 for best out of 3 mode");
if (mode === '2') cnt = 2;
round(cnt);
const choice = prompt("Play again?");
if (choice[0].toLowerCase() != 'y') break;
}
For every 2 round you can check for the current status of the game. Also made some changes on the play logic
const play = () => {
// set Computer Choice
var userChoice = prompt("Do you choose rock, paper or scissors?");
var computerChoice = Math.random();
if (computerChoice < 0.34) {
computerChoice = "rock";
} else if (computerChoice <= 0.67) {
computerChoice = "paper";
} else {
computerChoice = "scissors";
}
console.log("Player Choice: " + userChoice);
console.log("Computer Choice: " + computerChoice);
if (computerChoice === userChoice) {
return "The result is tie!";
}
//little change in logic here----
if (computerChoice === "rock") {
if (userChoice === "scissors") {
return "Computer wins";
} else {
if (userChoice === "paper")
return "Player wins";
}
}
if (computerChoice === "paper") {
if (userChoice === "rock") {
return "Computer wins";
} else {
if (userChoice === "scissors")
return "Player wins";
}
}
if (computerChoice === "scissors") {
if (userChoice === "paper") {
return "Computer wins";
} else {
if (userChoice === "rock")
return "Player wins";
}
}
};
const round = () => {
const res = play();
let playerScore = 0;
let computerScore = 0;
console.log(res)
cnt--
wins[cnt] = res.startsWith("Player") ? 1 :res.includes("tie") ?-1:0;
console.log(wins)
if (cnt === 0) {
const total = wins.filter((a) => a==1)
console.log(`You beat the computer ${total.length} time${total.length===1?"":"s"}`)
playAgain()
}else if(cnt == 1){ // Check for every round
var el2 = wins[2];
var el1 = wins[1];
if(el2 == el1 && el1!=-1){
const total = wins.filter((a) => a==1)
console.log(`You beat the computer ${total.length} time${total.length===1?"":"s"}`)
playAgain()
}
}
if(pa){
setTimeout(round, 10) // else go again
}else{
prompt("Thank you for playing")
}
}
let pa = true;
let cnt = 1,
wins = [];
const mode = prompt("Please press 1 for single game mode or 2 for best out of 3 mode");
if (mode === '2')
cnt = 3;
round()
function playAgain(){
if(confirm('Do you want to play again ?')){
pa = true
cnt = 1
wins = [];
const mode = prompt("Please press 1 for single game mode or 2 for best out of 3 mode");
if (mode === '2')
cnt = 3;
round()
}else{
pa=false
}
}
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()
I just created a five rounds rock-paper-scissors game using vanilla JavaScript. The program runs just fine so far except for the fact every time I start the game for the very first time it will take any user input as invalid no matter what and won't count that round.
This is my code:
// Global variables
let playerWins = 0;
let computerWins = 0;
let array = [];
let validInput = 0;
let newRound = "";
// This function generates a computer selection
const computerPlay = () => {
array = ["rock", "paper", "scissors"]
return array[Math.floor(Math.random() * array.length)];
}
// This function stores player selection
const playerSelection = (selection) => {
selection = prompt("Enter: 'Rock', 'Paper' or 'Scissors'").toLowerCase();
validInput = array.indexOf(selection);
console.log(validInput);
// This loop will validate user input is correct
while (validInput === -1) {
alert("Invalid input, try again");
selection = prompt("Enter 'Rock', 'Paper' or 'Scissors'").toLowerCase();
validInput = array.includes(selection);
}
return selection;
}
// This function plays a single round of Rock-Paper-Scissors
const playRound = (playerSelection, computerPlay) => {
// If both players select the same item
if (playerSelection === computerPlay) {
return alert("It's a tie!");
}
// If player selects "Rock"
if (playerSelection === "rock") {
if (computerPlay === "scissors") {
playerWins += 1;
return alert("Rock crushes scissors: YOU WIN!!!");
} else {
computerWins += 1;
return alert("Paper covers rock: YOU LOOSE!!!");
}
}
// If player selects "Paper"
if (playerSelection === "paper") {
if (computerPlay === "rock") {
playerWins += 1;
return alert("Paper covers rock: YOU WIN!!!");
} else {
computerWins += 1;
return alert("Scissors cuts paper: YOU LOOSE!!!");
}
}
// If player selects "Scissors"
if (playerSelection === "scissors") {
if (computerPlay === "rock") {
computerWins += 1;
return alert("Rock crushes scissors: YOU LOOSE!!!");
} else {
playerWins += 1;
return alert("Scissors cuts paper: YOU WIN!!!");
}
}
}
// This function keeps score and reports a winner or loser at the end
const trackWins = (pw, cw) => {
alert("COMPUTER WINS: " + cw + "\nPLAYER WINS: " + pw)
if (pw > cw) {
alert("YOU WIN THIS ROUND, CONGRAX!!!")
} else if (cw > pw) {
alert("YOU LOOSE THIS ROUND, SO BEST LUCK FOR THE NEXT TIME :_(")
} else {
alert("IT'S A TIE")
}
}
// This function creates a 5 round game
const game = () => {
for (let i = 0; i < 5; i++) {
playRound(playerSelection(), computerPlay());
}
trackWins(playerWins, computerWins);
}
do {
game();
newRound = prompt("Do yo want to play another round? Type 'y' to continue or any other key to exit").toLowerCase();
} while (newRound === "y");
alert("It was a good game, bye for now!")
I will appreciate any ideas to fix this problem or improve my script, thank you in advance!
Your posted code can be simplified to better reflect question - say, you have an array, and a variable that stores user input. How do you test if the input value is in the array?
var arr=['Rock','Paper','Scissors'];
var inp='Rock'; //user input
You could use a while loop, but there's a much faster way:
var options={'rock':0,'paper':1,'scissors':2}
var inp='Rock'; //user input
var ninp=inp.toLowerCase().trim(); //normalize input
var pick=(options[ninp]);
if (pick==null) // invalid selection
if (pick==0) //rock
if (pick==1) //paper
if (pick==2) //scissors
The code can be further cleaned up with a switch:
switch (pick){
case 0: ... break; //rock
case 1: ... break; //paper
case 2: ... break; //scissors
default: //invalid
}