[SOLVED] What is wrong with my Rock Paper Scissors app?

Issue

I’ve been trying to turn my old JavaScript learning projects into intractable web applications now that I am learning the DOM. It has been a while since I wrote a basic JavaScript script like this, so I am likely missing something obvious here, but my program outputs the last line in my game algorithm regardless of the user choice (‘Rock beats scissors. You lose.’), and the computer score updates in increments of three. This is obviously not what I intended.

I believe it is fairly intuitive what the output should be, but I’ve included comments in my JavaScript file to highlight the desired output (game should follow the conventional rules of Rock Paper Scissors). Apologies if the interface looks jumbled, I designed it to spec for a 15.6" screen and haven’t worked out cross-user functionality yet.

//HTML elements saved as JS variables
let rock = document.getElementById("rock");
let paper = document.getElementById("paper");
let scissors = document.getElementById("scissors");
let gameResults = document.getElementById("gameResults");
let scoreboard = document.getElementById("scoreboard")

/*Generates a random number between 0 and 2 to be substituted for rock, paper, or scissors, respectively.*/
const getComputerChoice = () => {
    // Rock is 0; Paper is 1; Scissors is 2.
    let choice = Math.floor(Math.random() * 3);
    return choice;
};

/*Player and computer scores which update the "scoreboard" element id; score should update in increments of one.*/
let playerScore = 0;
let computerScore = 0;

/*Game algorithm which should return a random choice from the computer and update the "gameResults" element id, according to the standard rules of Rock Paper Scissors, when interacted with through the event listeners at the bottom of the program.*/
const game = () => {
    let playerChoice;
    let computerChoice = getComputerChoice();

    if (playerChoice === computerChoice) {
        gameResults.innerHTML = 'You tied!';
        playerScore++;
        computerScore++;
    }

    if (playerChoice === rock && computerChoice === 2) {
        gameResults.innerHTML = 'Rock beats scissors. You win!'
        playerScore++;
    } else {
        gameResults.innerHTML = 'Paper covers rock. You lose.'
        computerScore++;
    }

    if (playerChoice === paper && computerChoice === 0) {
        gameResults.innerHTML = 'Paper covers rock. You win!'
        playerScore++;
    } else {
        gameResults.innerHTML = 'Scissors cuts paper. You lose.'
        computerScore++;
    }

    if (playerChoice === scissors && computerChoice === 1) {
        gameResults.innerHTML = 'Scissors cuts paper. You win!'
        playerScore++;
    } else {
        gameResults.innerHTML = 'Rock beats scissors. You lose.'
        computerScore++;
    }

    scoreboard.innerHTML = `Player: ${playerScore} | Computer: ${computerScore}`
};

//Event listeners
rock.addEventListener("click", game);
paper.addEventListener("click", game);
scissors.addEventListener("click", game);
body {
    background-image: url("pexels-pixabay-326311.jpg");
}

p {
    color: white;
    text-align: center;
}

#gameHeader {
    font-family: 'Shizuru', cursive, serif, sans-serif;
    font-size: 75px;
    border: 3px solid white;
    padding-bottom: 20px;
    margin-left: 350px;
    margin-right: 350px;
}

#gameResults {
    font-family: 'Rowdies', cursive, serif, sans-serif;
    font-size: 50px;
}

#scoreboard {
    font-family: 'Rowdies', cursive, serif, sans-serif;
    font-size: 20px;
    background-color: black;
    margin-left: 600px;
    margin-right: 600px;
    border: 2px solid white;
    border-radius: 50px;
    padding: 5px;
}

.results {
    position: relative;
    top: 100px;
}

label {
    font-family: 'Roboto Mono', sans-serif, serif;
    font-size: 25px;
    color: white;
}

.labels {
    display: inline-flexbox;
    margin-top: 20px;
}

#rockLabel {
    border: 2px solid white;
    border-radius: 10px;
    padding: 5px;
    position: fixed;
    left: 520px;
    background-color: black;
}

#paperLabel {
    border: 2px solid white;
    border-radius: 10px;
    padding: 5px;
    position: fixed;
    left: 722px;
    background-color: black;
}

#scissorsLabel {
    border: 2px solid white;
    border-radius: 10px;
    padding: 5px;
    position: fixed;
    left: 915px;
    background-color: black;
}


#rock {
    background-image: url("Rock.jpeg");
    background-color: white;
    background-position: center;
    background-size: contain;
    padding: 50px;
    border: 3px solid black;
    border-radius: 50px;
}

#paper {
    background-image: url("Papers.jpg");
    background-color: white;
    background-position: center;
    background-size: contain;
    padding: 50px;
    border: 3px solid black;
    border-radius: 50px;
    margin-left: 100px;
    margin-right: 100px;
}

#scissors {
    background-image: url("Scissors.jpg");
    background-position: center;
    background-size: contain;
    padding: 50px;
    border: 3px solid black;
    border-radius: 50px;
}
<!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>Rock Paper Scissors</title>
    <link rel="stylesheet" href="Rock-Paper-Scissors.css">
    <script src="Rock-Paper-Scissors.js" async></script>
    
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Marko+One&family=Orbitron&family=Roboto+Mono:[email protected]&family=Rowdies:[email protected]&family=Saira+Condensed:[email protected]&family=Shizuru&family=Supermercado+One&display=swap" rel="stylesheet"> 

</head>

<body>

    <header>
        <p id="gameHeader">Rock Paper Scissors</p>
    </header>

    <div class="buttons">
        <center>
            <button id="rock"></button>
            <button id="paper"></button>
            <button id="scissors"></button>
        </center>
    </div>

    <div class="labels">
        <label for="rock" id="rockLabel">Rock</label>
        <label for="paper" id="paperLabel">Paper</label>
        <label for="scissors" id="scissorsLabel">Scissors</label>
    </div>

    <div class="results">
        <p id="gameResults">Try your luck!</p>
        <p id="scoreboard">Player: 0 | Computer: 0</p>
    </div>
    
</body>

</html>

Solution

Let’s reduce a lot of the replicated logic and use a single event listener on the button group, then leverage event delegation.

Most importantly, assign a value to player choice

//HTML elements saved as JS variables
let rock = document.getElementById("rock");
let paper = document.getElementById("paper");
let scissors = document.getElementById("scissors");
let gameResults = document.getElementById("gameResults");
let scoreboard = document.getElementById("scoreboard");

/*Set up a matirx of results */
let gameMatrix = {
  "rock": {
    "defeats": "scissors",
    "action": "smashes"
  },
  "paper": {
    "defeats": "rock",
    "action": "covers"
  },
  "scissors": {
    "defeats": "paper",
    "action": "cuts"
  }
};

/*Computer options*/
let computerChoices = ["rock", "paper", "scissors"];

/*Generates a random number between 0 and 2 to be substituted for rock, paper, or scissors, respectively.*/
const getComputerChoice = () => {
  // Rock is 0; Paper is 1; Scissors is 2.
  let choice = Math.floor(Math.random() * 3);
  //Get actual name to use as a key
  return computerChoices[choice];
}

/*Player and computer scores which update the "scoreboard" element id; score should update in increments of one.*/
let playerScore = 0;
let computerScore = 0;

/*Game algorithm which should return a random choice from the computer and update the "gameResults" element id, according to the standard rules of Rock Paper Scissors, when interacted with through the event listeners at the bottom of the program.*/
/*Use event delegation from button group*/
const game = (event) => {
  //Check it's a button
  if (event.target.matches("button")) {
    //get player choince from id
    let playerChoice = event.target.id;
    let computerChoice = getComputerChoice();
    let result;
    console.log(`C: ${computerChoice}, P: ${playerChoice}`);

    //Check for a tie
    if (playerChoice === computerChoice) {
      result = 'You tied!';
      playerScore++;
      computerScore++;
      //From the matrix, check if player defets computer choice
    } else if (gameMatrix[playerChoice].defeats === computerChoice) {
      playerScore++;
      //Set the result using the action from the matrix
      result = `You win, ${playerChoice} ${gameMatrix[playerChoice].action} ${computerChoice}`;
    } else {
      computerScore++;
      //Set the result usig the action  from the matrix but using the computer choice instead
      result = `You lose, ${computerChoice} ${gameMatrix[computerChoice].action} ${playerChoice}`;
    }

    console.log(result);
    gameResults.innerHTML = result;
    scoreboard.innerHTML = `Player: ${playerScore} | Computer: ${computerScore}`
  }
};

//Event listeners- sust to the group holding the button
document.querySelector(".buttons").addEventListener("click", game);
body {
  background-image: url("pexels-pixabay-326311.jpg");
}

p {
  color: white;
  text-align: center;
}

#gameHeader {
  font-family: 'Shizuru', cursive, serif, sans-serif;
  font-size: 75px;
  border: 3px solid white;
  padding-bottom: 20px;
  margin-left: 350px;
  margin-right: 350px;
}

#gameResults {
  font-family: 'Rowdies', cursive, serif, sans-serif;
  font-size: 50px;
  background-color: #EEE;
}

#scoreboard {
  font-family: 'Rowdies', cursive, serif, sans-serif;
  font-size: 20px;
  background-color: black;
  margin-left: 600px;
  margin-right: 600px;
  border: 2px solid white;
  border-radius: 50px;
  padding: 5px;
}

.results {
  position: relative;
  top: 100px;
}

label {
  font-family: 'Roboto Mono', sans-serif, serif;
  font-size: 25px;
  color: white;
}

.labels {
  display: inline-flexbox;
  margin-top: 20px;
}

/*Set a standard class for the labels*/
.labels label{
border: 2px solid white;
  border-radius: 10px;
  padding: 5px;
  position: fixed;
  left: 520px;
  background-color: black;
}

/*Now just set what is needed*/
#rockLabel {
  left: 520px;
}

#paperLabel {
  left: 722px;
}

#scissorsLabel {
  left: 915px;
}

/*Set a standard class for the buttons*/
.buttons button{
  background-color: white;
  background-position: center;
  background-size: contain;
  padding: 50px;
  border: 3px solid black;
  border-radius: 50px;

}


/*Now just set what is needed*/
#rock {
  background-image: url("Rock.jpeg");
}

#paper {
  background-image: url("Papers.jpg");
  margin-left: 100px;
  margin-right: 100px;
}

#scissors {
  background-image: url("Scissors.jpg");
}
<!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>Rock Paper Scissors</title>
  <link rel="stylesheet" href="Rock-Paper-Scissors.css">
  <script src="Rock-Paper-Scissors.js" async></script>

  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Marko+One&family=Orbitron&family=Roboto+Mono:[email protected]&family=Rowdies:[email protected]&family=Saira+Condensed:[email protected]&family=Shizuru&family=Supermercado+One&display=swap" rel="stylesheet">

</head>

<body>

  <header>
    <p id="gameHeader">Rock Paper Scissors</p>
  </header>

  <div class="buttons">
    <center>
      <button id="rock"></button>
      <button id="paper"></button>
      <button id="scissors"></button>
    </center>
  </div>

  <div class="labels">
    <label for="rock" id="rockLabel">Rock</label>
    <label for="paper" id="paperLabel">Paper</label>
    <label for="scissors" id="scissorsLabel">Scissors</label>
  </div>

  <div class="results">
    <p id="gameResults">Try your luck!</p>
    <p id="scoreboard">Player: 0 | Computer: 0</p>
  </div>

</body>

</html>

Answered By – Jon P

Answer Checked By – Dawn Plyler (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published.