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
}
Related
I am a newbie programmer, making a rock, paper, scissors game. I have the game "working", however, I am unable to isolate why some tie games actually credit either the player or computer as the winner and vice versa, some games that are not a tie, has an alert pop up signifying the game is tied. The code:
/*variable statements follow*/
const choices = ["rock", "paper", "scissors"];
const resultOutput = document.getElementById('result-output');
let roundsPlayed = 0;
/**
* This Array from statement within the function sets event listener to the button class control array
* which listens for the user and computer choices which are fed to the getresult function
*/
function arrayMethod() {
const resultDisplay = document.getElementById('result');
const possibleChoices = document.getElementsByClassName('control');
let computerChoice = document.getElementById('computer-choice').innerText;
Array.from(possibleChoices).forEach(possibleChoice => possibleChoice.addEventListener('click', (e) => {
userChoice = e.target.id;
resultDisplay.innerHTML = userChoice;
compChoice = generateComputerChoice();
gameImages(userChoice, computerChoice);
getResult();
}));
}
/**
* This adds an event listener for the reset button
*/
document.getElementById("resetScore").addEventListener("click", resetScore);
/**
* This function generates a random number for the computer and displays
* the output to the innerHTML
*/
function generateComputerChoice() {
let randomNumber = Math.floor(Math.random() * 3);
let computerChoiceDisplay = document.getElementById('computer-choice');
computerChoiceDisplay.innerHTML = choices[randomNumber];
}
/**
* Provides the logic to determin what to do in the event that either
* the user or computer wins, as well as what to do in the even of a draw.
*/
function getResult () {
computerChoice = document.getElementById('computer-choice').innerText;
userChoice = document.getElementById('result').innerText;
if (computerChoice === userChoice) {
result = "It's a draw!";
resultOutput.innerHTML = result;
completeRound();
}
else if (computerChoice === 'rock' && userChoice === 'paper') {
result = "You Win!";
resultOutput.innerHTML = result;
incrementUserScore();
}
else if (computerChoice === 'rock' && userChoice === 'scissors') {
result = "You lost!";
resultOutput.innerHTML = result;
incrementComputerScore();
}
else if (computerChoice === 'paper' && userChoice === 'scissors') {
result = "You Win!";
resultOutput.innerHTML = result;
incrementUserScore();
}
else if (computerChoice === 'paper' && userChoice === 'rock') {
result = "You lost!";
resultOutput.innerHTML = result;
incrementComputerScore();
}
else if (computerChoice === 'scissors' && userChoice === 'rock') {
result = "You win!";
resultOutput.innerHTML = result;
incrementUserScore();
}
else if (computerChoice === 'scissors' && userChoice === 'paper') {
result = "You lost!";
resultOutput.innerHTML = result;
incrementComputerScore();
}
resultOutput.innerHTML = result;
toggleBackgroundColor();
}
/**
* This function allows for the dynamic change of images based on user or
* computer choices.
*/
function gameImages(playerChoice, computerChoice) {
playerChoice = document.getElementById("result").innerHTML;
computerChoice = document.getElementById("computer-choice").innerHTML;
const playerImage = document.getElementById('player-image');
const computerImage = document.getElementById('computer-image');
playerImage.src = `assets/images/${playerChoice}.jpg`;
playerImage.alt = choices [userChoice];
computerImage.src = `assets/images/${computerChoice}.jpg`;
computerImage.alt = choices[computerChoice];
}
/**
* Gets the user score from the DOM and increments it by 1
*/
function incrementUserScore() {
let oldScore = parseInt(document.getElementById("userScore").innerText);
document.getElementById("userScore").innerText = ++oldScore;
completeRound();
}
/**
* Gets the computer score from the DOM and increments it by 1
*/
function incrementComputerScore() {
let oldScore = parseInt(document.getElementById("compScore").innerText);
document.getElementById("compScore").innerText = ++oldScore;
completeRound();
}
/**
* This function provides the logic used to reset the user and
* computer score back to zero, upon the user request.
*/
function resetScore() {
document.getElementById("userScore").innerText = 0;
document.getElementById("compScore").innerText = 0;
roundsPlayed = 0;
}
/**
* This function is to limit the amount of playable paper, rock, and scissors game to best out of 9
*/
function limitGameToBestOutOfNine () {
let score = parseInt(document.getElementById("userScore").innerText);
let mistakes = parseInt(document.getElementById("compScore").innerText);
if (score > mistakes) {
alert('Player has won the game!');
} else if (mistakes > score) {
alert('Computer has won the game!');
} else {
alert('It\'s a tie!');
}
}
/***
* This function limits the amount of games to below 10 and decides the winner
* who receives the most wins out of 9 games
*/
function completeRound() {
let userScore = parseInt(document.getElementById("userScore").innerText);
let computerScore = parseInt(document.getElementById("compScore").innerText);
roundsPlayed++
console.log(roundsPlayed);
if (roundsPlayed > 9) {
limitGameToBestOutOfNine();
resetScore();
}
}
/***
* This function toggles the background color of the .player .computer class
* based on the winner of the current game. The winner color is green and the loser color is red
*/
function toggleBackgroundColor() {
const player = document.getElementById('player');
const computer = document.getElementById('computer');
const winner = resultOutput.innerHTML.toLowerCase();
if (winner.includes('you win')) {
player.style.backgroundColor = "#00FF00";
computer.style.backgroundColor = "#FF0000";
}
else if (winner.includes('you lost')) {
player.style.backgroundColor = "#FF0000";
computer.style.backgroundColor = "#00FF00";
}
else {
player.style.backgroundColor = "#00FF00";
computer.style.backgroundColor = "#00FF00";
}
}
document.onload = arrayMethod();
Any advice would be greatly appreciated. Thank you!
I am unable to isolate why some tie games actually credit either the player or computer as the winner and vice versa, some games that are not a tie, has an alert pop up signifying the game is tied. I have tried to console log certain aspects of the game output, but am having a hard time finding why the game behaves like this periodically.
I am building a rock, paper, scissors project which is supposed to take 5 rounds. The user will get a prompt and input either "rock", "paper", or "scissors". When I write the code like this:
let playerSelection = prompt("Rock, paper ou scissors?").toLowerCase();
let game = function() {
for (let i = 0; i < 5; i++) {
compare(playerSelection, computerPlay);
if (compare === "You win!") {
playerScore++;
}
else if (compare === "You lose!") {
computerScore++;
}
else if (compare === "It's a tie!") {
}
}
}
The prompt is prompted and I get to input something, however it only happens once and the loop doesn't work. When I put the prompt inside the loop, like this:
let game = function() {
for (let i = 0; i < 5; i++) {
let playerSelection = prompt("Rock, paper ou scissors?").toLowerCase();
compare(playerSelection, computerPlay);
if (compare === "You win!") {
playerScore++;
}
else if (compare === "You lose!") {
computerScore++;
}
else if (compare === "It's a tie!") {
}
}
}
The prompt never shows up!
How can I solve this and make it prompt 5 times?
Well you are not calling the function.
use
game();
after function definition
I think there is some error in your compare function. checkout the snippet below its working fine.
const compare = function(playerSelection, computerPlay) {
// write your logic here
return "You win!";
}
let game = function() {
for (let i = 0; i < 5; i++) {
let playerSelection = prompt("Rock, paper ou scissors?").toLowerCase();
const outputs = ["rock", "paper", "scissor"];
compare(playerSelection, Math.floor(Math.random()*3));
if (compare === "You win!") {
playerScore++;
}
else if (compare === "You lose!") {
computerScore++;
}
else if (compare === "It's a tie!") {
}
}
}
game();
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()
I am practicing the rock-paper-scissors assignment.
When I call playRound function manually it returns normal (e.g tie true false tie tie).
But when I call playRound function with iteration through game function it returns (true true true true) or (false false false false false) or (tie tie tie tie tie), instead of something like (false tie false true tie). I used the if-else clause and now I used switch yet still the same output. please how will I solve the issue?
function getComputerPlay() {
let selectAny = ["paper", "rock", "scissors"];
let randomReturn = Math.floor(Math.random() * selectAny.length);
return selectAny[randomReturn];
}
function getUserSelect(choice) {
let userSelect = choice.toLowerCase();
if (userSelect === "rock" || userSelect === "paper" || userSelect === "scissors") return userSelect;
return "Not valid";
}
function playRound(playSelection, computerSelection) {
if (playSelection === computerSelection) return "Tie!.";
if (playSelection === "paper") {
if (computerSelection === "rock") {
return true;
}
else {
return false;
}
}
if (playSelection === "rock") {
if (computerSelection === "scissors") {
return true;
}
else {
return false;
}
}
if (playSelection === "scissors") {
if (computerSelection === "rock")
return false;
} else {
return true;
}
}
function game(playSelection, computerSelection) {
let win = 0;
let lost = 0;
let tie = 0;
for (let i = 0; i < 5; i++) {
let playRoundReturn = playRound(playSelection, computerSelection);
switch (playRoundReturn) {
case true:
win++;
break;
case false:
lost++;
break;
default:
tie++;
break;
}
}
console.log(win, lost, tie);
return "You won " + win + "times, lost " + lost + "times and draw " + tie + "time";
}
let playSelection = getUserSelect("rock");
let computerSelection = getComputerPlay();
let play = game(playSelection, computerSelection); //called playRound with iteration through game()
//let pl = playRound(playSelection, computerSelection); //called playRound manually
console.log(play);
This is because the playSelection is always 'rock', and the computerSelection only runs the random gen once, so will always be the same value for all 5 rounds.
Move the random generator into the for loop, e.g.
let playRoundReturn = playRound(playSelection, getComputerPlay());
I am doing a simple rock, paper, scissors program in the codeacademy javascript course. This first one is very simple and much of what is here is the way they guided me. I know the entire thing can be written better but that comes later. Program works partially but never seems to define the computerChoice variable. I think the issue is in lines 15-18 but not sure. I did try changing the strings to integers in lines 42, 49 & 58 but that did not solve the issue.
Can anyone look at my code and offer guidance.
//function to get the user's choice
const getUserChoice = userInput => {
userInput =
userInput.toLowerCase();
//if stmt to make sure input is valid
if (userInput === 'rock' || 'scissors' || 'paper') {
return userInput;
} else {
console.log('Invalid selection');
}//end else
}//end getUserChoice function
//function to get computer choice
const getComputerChoice = () => {
Math.floor(Math.random() * 3);
//switch case to verify & return result
switch (getComputerChoice) {
case 0:
return 'rock';
break;
case 1:
return 'paper';
break;
case 2:
return 'scissors';
break;
default:
console.log('Invalid');
break;
}//end switch
}//end getComputerChoice
//function to determine the winner
const determineWinner = (userChoice, computerChoice) => {
if (userChoice === computerChoice) {
return 'The game is a tie';
}
if (userChoice === 'rock') {
if (computerChoice === 'paper') { return 'You Won!'; }
} // end userchoice is rock
if (userChoice === 'paper') {
if (computerChoice === 'scissors') {
return 'The computer won!';
} else {
return 'You won!';
}
} // end userchoice is paper
if (userChoice === 'scissors') {
if (computerChoice === 'rock') {
return 'The computer won!';
} else {
return 'You won!';
}
} //end userchoice is scissors
}//end winner function
//function to play the game
const playGame = () => {
const userChoice = getUserChoice('rock');
const computerChoice = getComputerChoice();
console.log('You threw: ' + userChoice);
console.log('The computer threw: ' + computerChoice);
//call funtion to determine winner
console.log(determineWinner(userChoice, computerChoice));
}//end playGame
//function calls
playGame();
Problem
After a more thorough examination, there were a few errors. Demo 1 addresses each of these errors. Details are commented in the demo. There is a Plunker of Demo 1 as well.
At first, I had started on a working demo without the benefit of your updated post. Demo 2 is functioning as well and is helpful if you want to consider an alternative way to meet your objective.
Plunker
Demo 1
const getUserChoice = userInput => {
userInput = userInput.toLowerCase();
//if stmt to make sure input is valid
if (userInput === 'rock' || 'scissors' || 'paper') {
return userInput;
} else {
console.log('Invalid selection');
} //end else
}; //end getUserChoice function
//function to get computer choice
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
On each case there was a return before every break
A return statement always ends the block so break
was useless and in the process the switch useless.
Changed getComputerChoice into a declared function
Saved the results of switch in a variable
Returned the value as expected
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
function getComputerChoice() {
let compPick = Math.floor(Math.random() * 3);
console.log('compPick: ' + compPick);
var psr;
//switch case to verify & return result
switch (compPick) {
case 0:
psr = 'rock';
break;
case 1:
psr = 'paper';
break;
case 2:
psr = 'scissors';
break;
default:
console.log('Invalid');
break;
} //end switch
return psr;
}
//function to determine the winner
const determineWinner = (userChoice, computerChoice) => {
if (userChoice === computerChoice) {
return 'The game is a tie';
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Missing the else portion of conditional statement,
Whenever user threw a rock and computer threw a
scissor, the result was undefined.
Added the else portion, now all 7 condition are met. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if (userChoice === 'rock') {
if (computerChoice === 'paper') {
return 'You Lost!';
} else {
return "You Won!"
}
} // end userchoice is rock
if (userChoice === 'paper') {
if (computerChoice === 'scissors') {
return 'You Lost!';
} else {
return 'You won!';
}
} // end userchoice is paper
if (userChoice === 'scissors') {
if (computerChoice === 'rock') {
return 'You Lost!';
} else {
return 'You won!';
}
} //end userchoice is scissors
}; //end winner function
//function to play the game
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Added a <select> element so testing is properly done
Changed playGame() to a declared function and the
callback function for the change event listener
Note that playGame is passing a value. This value is from the <select>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
function playGame(psr) {
const userChoice = getUserChoice(psr);
const computerChoice = getComputerChoice();
console.log('You threw: ' + userChoice);
console.log('The computer threw: ' + computerChoice);
//call funtion to determine winner
console.log(determineWinner(userChoice, computerChoice));
} //end playGame
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reference the <select> tag
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
var sel = document.getElementById('psr');
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Register the change event on the <select> tag
When change event occurs on select#psr, playGame() is
called and it passes the value of select#psr thru
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
sel.addEventListener('change', function(e) {
playGame(this.value);
});
select,
option {
font: inherit
}
#psr {
margin: 30px 0 0 30px
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<select id='psr'>
<option>---</option>
<option value='paper'>Paper</option>
<option value='scissors'>Scissors</option>
<option value='rock'>Rock</option>
</select>
</body>
</html>
Demo 2
/* Using HTMLFormControlsCollection
\ Reference the form and...
*/
var game = document.forms.psrGame;
/* reference the form's form controls
*/
var ctrl = game.elements;
/* This is an Object Literal.
\ It's storing data for easy reuse
*/
var PSR = {
player: 0,
opponent: 0,
action: ['📃Paper', '✂️Scissors', '🗿Rock'],
outcome: ['Tied', 'Player Won', 'Player Lost'],
won: 0,
lost: 0,
tied: 0
};
/* Register the click event on fieldset#set
\ Callback function is choice()
*/
ctrl.set.addEventListener('click', choice);
// Callback function
function choice(e) {
/* if the clicked button (e.target) is NOT
|| the registered node (e.currentTarget)...
|| if the clicked node is a BUTTON...
*/
if (e.target !== e.currentTarget) {
if (e.target.tagName === 'BUTTON') {
// Get clicked button's id
var z = parseInt(e.target.id, 10);
PSR.player = z;
//console.log('z: ' + z);
// Get a randomly generated number 0-2
var x = rand(0, 2);
PSR.opponent = x;
//console.log('x: ' + x);
// Determine P.S.R. for player
var pick = PSR.action[z];
//console.log('Picked: ' + pick);
// Determine P.S.R. for opponent
var verse = PSR.action[x];
//console.log('Verses: ' + verse);
// Display P.S.R of player and opponent
ctrl.choice.value = pick;
ctrl.against.value = verse;
}
// Get the outcome and display it
var us = determine(PSR);
ctrl.view.value = us;
return us;
}
/* Prevent event bubbling thereby isolating the
|| the click events from the rest of the form
*/
e.stopPropagation();
}
/* Through a gauntlet of conditions
|| it is determined whether player
|| lost, won, or tied.
*/
function determine(PSR) {
var Z = PSR.player;
var X = PSR.opponent;
var msg;
if (Z === X) {
msg = PSR.outcome[0];
++PSR.tied;
} else if (Z === 0 && X === 2) {
msg = PSR.outcome[1];
++PSR.won;
} else if (Z === 1 && X === 0) {
msg = PSR.outcome[1];
++PSR.won;
} else if (Z === 2 && X === 1) {
msg = PSR.outcome[1];
++PSR.won;
} else {
msg = PSR.outcome[2];
++PSR.lost;
}
/* This is a Template Literal which will
|| display the player's wins, losses, and ties
*/
var totals = `Won: ${PSR.won} Lost: ${PSR.lost} Tied: ${PSR.tied} `;
ctrl.score.innerHTML = totals;
return msg;
}
// Utility to generate random integers
function rand(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
body {
font-size: 16px;
}
#set {
margin-bottom: 10px;
}
input,
button,
output,
label {
font: inherit;
display: inline-block
}
button {
width: 9ch
}
.as-console-wrapper {
max-width: 30%;
margin-left: 70%
}
#view {
font-weight: 900;
color: crimson
}
legend {
font-variant: small-caps;
font-size: 1.2em;
}
<form id='psrGame'>
<fieldset id='set'>
<legend>Paper, Scissors, Rock</legend>
<button id='0' type='button'>Paper</button>
<button id='1' type='button'>Scissors</button>
<button id='2' type='button'>Rock</button>
</fieldset>
<label><b>Player: </b>
<output id='choice'></output>
</label>
<hr>
<label><output id='view'></output></label>
<label style='float:right'><output id='score'></output></label>
<hr>
<label><b>Opponent:</b>
<output id='against'></output>
</label>
Line 18 should be
switch (Math.floor(Math.random() * 3)) {
Whatever value you pass to switch is what's compared against the values of the cases. The switch cases check a random integer from 0 to 2, so pass that generated random number to switch.