Coding a rock paper scissors game with JavaScript, HTML, and CSS

A concise tutorial on how to code a rock paper scissors game using JavaScript

Posted on June 22, 2021


This tutorial will help you learn how to code a rock paper scissors game using JavaScript as its main engine.

The end result of this tutorial is as follows:

The complete code is stored in the following GitHub repository. You can play the game on this GitHub Page.

Let’s start with creating the core game mechanism using JavaScript and HTML first.

Rock paper scissors game using JavaScript and HTML

To create the code mechanics of the rock, paper, and scissors game, you need to create three HTML <button> elements with each represents an option for the user.

You can create them as follows:

<body>
  <h1>Basic Rock Paper Scissors game with JavaScript</h1>
  <button class="options">Rock</button>
  <button class="options">Paper</button>
  <button class="options">Scissors</button>
</body>

Next, you need to grab the elements using JavaScript and add an event listener to each one of them. The querySelectorAll() method is used because the returned NodeList object implements the forEach() method.

Take a look at the code below:

<body>
  <h1>Basic Rock Paper Scissors game with JavaScript</h1>
  <button class="options">Rock</button>
  <button class="options">Paper</button>
  <button class="options">Scissors</button>
  <script>
    const options = document.querySelectorAll(".options");

    options.forEach((option) => {
      option.addEventListener("click", function () {
        // TO DO: process user click
      });
    });
  </script>
</body>

The callback function passed into addEventListener() method will be executed when the user clicks on one of the three buttons.

When a click event is triggered, you need to fetch the user’s selected option by reading the value of the textContent property. Let’s store the value in a variable called pInput which stands for Player Input:

const pInput = this.textContent;

The this keyword in the code above refers to the <button> element that was clicked by the user. If the user clicked on "Rock" button, then pInput variable value will be of "Rock" string.

Once you have the pInput, it’s time to get the computer selection. The computer needs to select one of the three available choices.

You can use the Math.random() method to generate a random number between 0-2 and use it to randomly select between rock, paper, or scissors for the computer.

Here’s how you do it:

<body>
  <h1>Basic Rock Paper Scissors game with JavaScript</h1>
  <button class="options">Rock</button>
  <button class="options">Paper</button>
  <button class="options">Scissors</button>
  <script>
    const options = document.querySelectorAll(".options");

    options.forEach((option) => {
      option.addEventListener("click", function () {
        const pInput = this.textContent;

        const cOptions = ["Rock", "Paper", "Scissors"];
        const cInput = cOptions[Math.floor(Math.random() * 3)];
      });
    });
  </script>
</body>

The cInput variable stands for Computer Input.

Now that you have both pInput and cInput ready, it’s time to create a function to compare them and find out who wins the current round.

Let’s call the function compareInputs() and start by creating an if statement that ends the round with a tie:

function compareInputs(pInput, cInput) {
  const currentMatch = `${pInput} vs ${cInput}`;

  // Tie check
  if (pInput === cInput) {
    alert(`${currentMatch} is a Tie`);
    return;
  }
}

When the inputs are not equal, you can start checking pInput value if it matches one of the three possible options. The code below starts with checking if the user selects "Rock" for the current round:

function compareInputs(pInput, cInput) {
  const currentMatch = `${pInput} vs ${cInput}`;

  // Tie check
  if (pInput === cInput) {
    alert(`${currentMatch} is a Tie`);
    return;
  }

  // Rock
  if (pInput === "Rock") {
    if (cInput === "Scissors") {
      alert(`${currentMatch} = You Win`);
    } else {
      alert(`${currentMatch} = Computer Wins`);
    }
  }
}

Since you’ve checked for the possibility of a tie first, you only need to create one if..else block for the outcome.

After that, you need to check for both "Paper" and "Scissors" as follows:

function compareInputs(pInput, cInput) {
  const currentMatch = `${pInput} vs ${cInput}`;

  // Tie check
  if (pInput === cInput) {
    alert(`${currentMatch} is a Tie`);
    return;
  }

  // Rock
  if (pInput === "Rock") {
    if (cInput === "Scissors") {
      alert(`${currentMatch} = You Win`);
    } else {
      alert(`${currentMatch} = Computer Wins`);
    }
  }
  // Paper
  else if (pInput === "Paper") {
    if (cInput === "Rock") {
      alert(`${currentMatch} = You Win`);
    } else {
      alert(`${currentMatch} = Computer Wins`);
    }
  }
  // Scissors
  else {
    if (cInput === "Paper") {
      alert(`${currentMatch} = You Win`);
    } else {
      alert(`${currentMatch} = Computer Wins`);
    }
  }
}

With the function completed, you just need to call it inside the addEventListener() method:

option.addEventListener("click", function () {
  const pInput = this.textContent;

  const cOptions = ["Rock", "Paper", "Scissors"];
  const cInput = cOptions[Math.floor(Math.random() * 3)];

  compareInputs(pInput, cInput);
});

And with that, you have completed the core mechanics of the rock paper scissors game.

The full code is as shown below:

<body>
  <h1>Basic Rock Paper Scissors game with JavaScript</h1>
  <button class="options">Rock</button>
  <button class="options">Paper</button>
  <button class="options">Scissors</button>
  <script>
    const options = document.querySelectorAll(".options");

    options.forEach((option) => {
      option.addEventListener("click", function () {
        const pInput = this.textContent;

        const cOptions = ["Rock", "Paper", "Scissors"];
        const cInput = cOptions[Math.floor(Math.random() * 3)];

        compareInputs(pInput, cInput);
      });
    });

    function compareInputs(pInput, cInput) {
      const currentMatch = `${pInput} vs ${cInput}`;

      // Tie check
      if (pInput === cInput) {
        alert(`${currentMatch} is a Tie`);
        return;
      }

      // Rock
      if (pInput === "Rock") {
        if (cInput === "Scissors") {
          alert(`${currentMatch} = You Win`);
        } else {
          alert(`${currentMatch} = Computer Wins`);
        }
      }
      // Paper
      else if (pInput === "Paper") {
        if (cInput === "Rock") {
          alert(`${currentMatch} = You Win`);
        } else {
          alert(`${currentMatch} = Computer Wins`);
        }
      }
      // Scissors
      else if (pInput === "Scissors") {
        if (cInput === "Paper") {
          alert(`${currentMatch} = You Win`);
        } else {
          alert(`${currentMatch} = Computer Wins`);
        }
      }
    }
  </script>
</body>

Now that you’ve learned the basic mechanics of the rock paper scissors game, it’s time to add more features to improve the gaming experience.

Improving the gaming experience for rock paper scissors game

With the core game mechanism set, you can start improving the game experience by keeping scores. For example, once the user or the computer gains five wins, the winner is called out and the score resets back to zero.

This can be done by creating two variables that keep the scores for both the user and the computer. The variable values will be updated when the user or the computer wins, and another function will check if either variable is equal to five.

Let’s start by updating the HTML with new elements to display the game objective and the scores:

<body>
  <h1>Basic Rock Paper Scissors game with JavaScript</h1>
  <h2>Win five rounds to be the victor</h2>
  <h3>
    Player <span id="p-score">0</span> - <span id="c-score">0</span> Computer
  </h3>
  <button class="options">Rock</button>
  <button class="options">Paper</button>
  <button class="options">Scissors</button>
</body>

The <span> elements above will be updated with the new variables named pScore and cScore. Let’s write the new variables inside the <script> tag:

const options = document.querySelectorAll(".options");
let pScore = 0;
let cScore = 0;

options.forEach((option) => {
  // ...
});

Next, increment the pScore value by one when the user wins, or the cScore value when the computer wins:

if (pInput === "Rock") {
  if (cInput === "Scissors") {
    alert(`${currentMatch} = You Win`);
    pScore++;
  } else {
    alert(`${currentMatch} = Computer Wins`);
    cScore++;
  }
}
//Check for Paper
else if (pInput === "Paper") {
  if (cInput === "Rock") {
    alert(`${currentMatch} = You Win`);
    pScore++;
  } else {
    alert(`${currentMatch} = Computer Wins`);
    cScore++;
  }
}
//Check for Scissors
else {
  if (cInput === "Paper") {
    alert(`${currentMatch} = You Win`);
    pScore++;
  } else {
    alert(`${currentMatch} = Computer Wins`);
    cScore++;
  }
}

Once the scores are updated, call a new function to update the scores displayed in the browser. Let’s call the function updateScore() method:

options.forEach((option) => {
  option.addEventListener("click", function () {
    const pInput = this.textContent;

    const computerOptions = ["Rock", "Paper", "Scissors"];
    const cInput = computerOptions[Math.floor(Math.random() * 3)];

    compareInputs(pInput, cInput);
    updateScore();
  });
});

The code inside the updateScore() method will update the <span> elements you’ve added before:

function updateScore() {
  document.getElementById("pScore").textContent = pScore;
  document.getElementById("cScore").textContent = cScore;
}

Finally, you need another function to check if one of the players already gained five wins. Let’s create another function named checkWinner() to do just that:

function checkWinner() {
  if (pScore === 5 || cScore === 5) {
    const winner =
      pScore === 5
        ? "You win the game! Congratulations!"
        : "Computer wins the game! Try again next time!";
    alert(winner);
    return true;
  }
  return false;
}

Call the checkWinner() function right above the call to updateScore() function. When it returns true, set the scores back to zero and call updateScore() again to refresh the rendered scores:

compareInputs(pInput, cInput);
updateScore();
if (checkWinner()) {
  pScore = cScore = 0;
  updateScore();
}

Now your rock paper scissors game will keep the scores and declare the winner when 5 wins have been gained.

Here’s the complete code again:

<body>
  <h1>Basic Rock Paper Scissors game with JavaScript</h1>
  <h2>Win five rounds to be the victor</h2>
  <h3>
    Player <span id="p-score">0</span> - <span id="c-score">0</span> Computer
  </h3>
  <button class="options">Rock</button>
  <button class="options">Paper</button>
  <button class="options">Scissors</button>
  <script>
    const options = document.querySelectorAll(".options");
    let pScore = 0;
    let cScore = 0;

    options.forEach((option) => {
      option.addEventListener("click", function () {
        const pInput = this.textContent;

        const cOptions = ["Rock", "Paper", "Scissors"];
        const cInput = cOptions[Math.floor(Math.random() * 3)];

        compareInputs(pInput, cInput);
        updateScore();
        if (checkWinner()) {
          pScore = cScore = 0;
          updateScore();
        }
      });
    });

    function compareInputs(pInput, cInput) {
      const currentMatch = `${pInput} vs ${cInput}`;
      if (pInput === cInput) {
        alert(`${currentMatch} is a Tie`);
        return;
      }

      if (pInput === "Rock") {
        if (cInput === "Scissors") {
          alert(`${currentMatch} = You Win`);
          pScore++;
        } else {
          alert(`${currentMatch} = Computer Wins`);
          cScore++;
        }
      }
      //Check for Paper
      else if (pInput === "Paper") {
        if (cInput === "Rock") {
          alert(`${currentMatch} = You Win`);
          pScore++;
        } else {
          alert(`${currentMatch} = Computer Wins`);
          cScore++;
        }
      }
      //Check for Scissors
      else {
        if (cInput === "Paper") {
          alert(`${currentMatch} = You Win`);
          pScore++;
        } else {
          alert(`${currentMatch} = Computer Wins`);
          cScore++;
        }
      }
    }

    function updateScore() {
      document.getElementById("p-score").textContent = pScore;
      document.getElementById("c-score").textContent = cScore;
    }

    function checkWinner() {
      if (pScore === 5 || cScore === 5) {
        const winner =
          pScore === 5
            ? "You win the game! Congratulations!"
            : "Computer wins the game! Try again next time!";
        alert(winner);
        return true;
      }
      return false;
    }
  </script>
</body>

With that, your rock paper scissors game mechanic is completed.

Up until now, you haven’t touched the user interface of your game, so let’s add some style and make the interface prettier in the next section.

Styling the rock paper scissors game

You can make the game interface better by using CSS to add colors and borders. But the most important improvement would be to replace the <button> elements with images of rock, paper, and scissors.

First, you need to download the images for the actions here.

Note: the images are created by Cristiano Zoucas from Noun Project free of charge

Once you have the buttons, update your HTML <body> tag as shown below:

<body>
  <div class="container">
    <h1>The Rock Paper Scissors Game</h1>
    <h2>Win five rounds to be the victor</h2>
    <h2>
      Player <span id="p-score">0</span> - <span id="c-score">0</span> Computer
    </h2>
    <div class="display-moves">
      <div class="move">
        <img id="p-move" src="./assets/Rock.svg">
      </div>
      <div class="separator">VS</div>
      <div class="move">
        <img id="c-move" src="./assets/Rock.svg">
      </div>
    </div>
    <h2>Click on the image below to select your move:<h2>
    <div class="action">
      <input class="options" type="image" src="./assets/Rock.svg" value="Rock" />
      <input class="options" type="image" src="./assets/Paper.svg" value="Paper" />
      <input class="options" type="image" src="./assets/Scissors.svg" value="Scissors" />
    </div>
  </div>
</body>

The <button> elements are replaced with the <input> elements using the type image. Additional <div> elements are added to the HTML page to help with CSS styling.

The CSS code for the page will be as follows:

body {
  text-align: center;
}
.container {
  margin: 0 auto;
  background-color: aquamarine;
  border-radius: 20px;
  padding: 25px 50px;
  width: 80vw;
}
.action {
  max-width: 800px;
  padding: 40px 0;
  margin: 0 auto;
  background-color: cadetblue;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-evenly;
  border-radius: 20px;
}
.options {
  flex: 1 1 30%;
  border-radius: 50%;
  border-width: 4px;
  border-style: solid;
  border-color: rgba(0, 0, 0, 0.7);
  padding: 10px;
  animation-name: anim-fade;
  animation-duration: 1s;
  animation-fill-mode: forwards;
  width: 100%;
  max-width: 120px;
}
.display-moves {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-evenly;
}
.move {
  border-radius: 50%;
  border-width: 4px;
  border-style: solid;
  border-color: rgba(0, 0, 0, 0.7);
}
.separator {
  font-size: 5em;
}

The CSS above will add background color to the HTML page and create a circle border around the images. The last improvement you need to do is to update the JavaScript code.

First, revise the pInput variable value to fetch from value property instead of textContent:

const pInput = this.value;

After that, create a function to update the player and the computer actions (the smaller images)

Let’s name it the updateMoves() function:

function updateMoves(pInput, cInput) {
  document.getElementById("p-move").src = `./assets/${pInput}.svg`;
  document.getElementById("c-move").src = `./assets/${cInput}.svg`;
}

Finally, call the updateMoves() right before calling the compareInputs() function:

option.addEventListener("click", function () {
  const pInput = this.value;

  const cOptions = ["Rock", "Paper", "Scissors"];
  const cInput = cOptions[Math.floor(Math.random() * 3)];

  updateMoves(pInput, cInput);
  compareInputs(pInput, cInput);
  updateScore();
  if (checkWinner()) {
    pScore = cScore = 0;
    updateScore();
  }
});

Now your rock paper scissors game looks a lot better than before. Here’s a GitHub repository storing the finished game.

Conclusion

You’ve learned how to code a rock paper scissors game using JavaScript, HTML, and CSS.

Optionally, you can still improve the application further by adding an option for users to select how many rounds they want to play the game.

But don’t worry about it and congratulations on making it this far! 😉

Related articles:

Grab the free JavaScript book today 👍

Learn the building blocks of JavaScript programming language like data types, functions, objects, arrays and classes.

Use the knowledge from the book to build a small but solid program.

Learn more