How To write a Rock Paper Scissors Game in Java – Step by Step

Posted by Marta on February 2, 2023 Viewed 9434 times

Card image cap

In this article, I want to help you to design a Rock Paper Scissors Game in Java step by step. And first step is overcoming your self-doubt and concentrate. You will put together everything you know about programming to build a rock paper scissors game that makes you feel proud of yourself. Let’s see how you will achieve this step by step.

Once Upon A Time…

It all starts with desire and passion. The desire to build cool pieces of software from scratch. And your love for programming and drive to practice to become the best programmer you can be.

And one day, like to Issac Newton, the idea falls on your head: “I am going to build a rock paper scissors game.”. As soon as you have the idea, the overwhelming self-doubt voices came around: “You are not a real programmer.”. “You are not that clever.”. “Building a game is too difficult.”

At this point, you silence all the voices and realize that maybe you don’t know every step yet, but following the software development process, you can start small and figure things out as you go. After this realization, you decide to crack on with the game. Let’s dive into the game!

Define How your Rock Paper Scissors Game works

Let’s start by defining how the game should work. You will be creating a rock paper scissors text-based java game like the one you can see below:

The first step is writing down the steps of what the game should. By doing so, it can help us identify the classes and actions that we will need our game. The steps are:

  • The Game welcomes the user.
  • The game requests the user to enter his choice(rock, paper or scissors)
  • The user types the selected option.
  • The game picks randomly among rock, paper or scissors.
  • Calculates the results.
  • The game updates the total score( how many games you play in total and won games)
  • Display the score.
  • Ask the user if he wants to continue.

Writing down how the game will work is a great start. It helps you identify some of the main entities of the problem, so later you can turn them into class. In this case, we will create the following classes:

  • RockPaperScissorsGame: the entry point of the application
  • Game Controller: this class will represent the game itself, containing the scores, the player choices, and operations related to the game mechanism like calculate who won, etc.
  • GameOption: This class represents different options the player can select: rock, paper, or scissors.
  • Player: It helps indicate you won, the user, the machine, or the tie.
  • Score: It contains the total number of games player, and the number of games played by the user.

Create a Skeleton Implementation

Now that we have an overall view of how the rock paper scissors java game will work and the main classes in our program, we can start creating them and give shape to our game. At this option, I will advise you not to add implementation. The skeleton should contain the classes and the empty operations of these classes. These operations define how the classes interact with each other. For now the implementation is not necessary.

Let’s start with the entry point of the game.

RockPaperScissorsGame class

This class needs a main method since it is the entry point of our java program. Since we are going to interact with the game, we will create an instance of the class to access its operations.

public class RockPaperScissorsGame {

    public static void main(String[] args){

        GameController gameController = new RockPaperScissorsGameController();

    }
}

GameController class

This class represents the game itself. Instead of creating the class directly, we will create an interface. The key reason is loose decoupling.

Loose Decoupling is an essential concept in programming. It means that a class that interacts with another class should know minimal information about the other class. How can you do that? Placing an interface between them.

The interface is sort of a contract containing all the operations. This way class A and class B will communicate through the contract. Therefore the classes are loosely coupled. As a consequence, if tomorrow I replace class B with class C, as long as C implements the same contract as B, class A should still work without further modifications.

Going back to our game, we will create an interface that defines what the game should do. It should welcome the user, request the user to enter its option(rock, paper, or scissors).

Also, it should save the user option or choice. Pick a random choice to play, calculate the result of the game; in other words, you won. Last, it needs an operation that returns the scores to keep track of how many games we played and how many we won. See the resulting interface below:

public interface GameController {

    String welcomeMessage();

    String pleaseEnterOptionMessage();

    void selectUserChoice(GameOption userOption);

    GameOption randomMachineChoice();

    Player calculateResult();

    Score getResults();

}

GameOption class

This class represents the different choices the game offers: rock, paper, and scissors. It is a good idea to include an empty option as well to avoid the null pointer risk.

The winBy field is representing the option id that wins a given option. For instance, rock is option 1, and it is won by paper with id 2. That is why the winBy value for ROCK is 2: ROCK(1,2)

public enum GameOption {
    ROCK(1,2), PAPER(2,3), SCISSOR(3,1),EMPTY(-1,-1);
    
    private int id;
    private int winBy;

    GameOption(int id, int winBy){

        this.id = id;
        this.winBy = winBy;
    }

    public static GameOption valueOf(int userEnteredOption){
        for(GameOption option: GameOption.values()){
            if(userEnteredOption ==option.id){
                return option;
            }
        }
        return EMPTY;
    }

    public boolean isWinBy(GameOption option){
        return this.winBy == option.id;
    }
}

Player

This class helps to indicate you won: the user, the machine, or the tie.

public enum Player {
    USER, MACHINE,TIE;
}

Score

The Score class will contain the total number of games played and the number of games played by the user.

public class Score {
    private int gamesWonByUser;
    private int totalNumberGames;

    public void incrementGamesWonByUser(){
        gamesWonByUser++;
    }

    public void incrementTotalNumberGames(){ totalNumberGames++; }

    public int totalNumberOfGames(){
        return totalNumberGames;
    }

    public int getGamesWonByUser(){
        return gamesWonByUser;
    }
}

RockPaperScissorsGameController

And finally, we can create one of the core classes which is the RockPaperScissorsGameController class. This class will implement the interface we created earlier. All essential game functionality will go here. Also, this class will keep track of three pieces of information:

  • what option the user has selected
  • what option the machine has selected
  • And totalScore containing the total number of games

At this point, we will just create the class and the methods and leave the method empty.

public class RockPaperScissorsGameController implements GameController {

    private GameOption userChoice = GameOption.EMPTY;
    private GameOption machineChoice = GameOption.EMPTY;
    private Score totalScore = new Score();

    @Override
    public String welcomeMessage() { return null; }

    @Override
    public String pleaseEnterOptionMessage(){
        return  null;
    }

    @Override
    public void selectUserChoice(GameOption userOption) { }

    @Override
    public GameOption randomMachineChoice() {
       return null;
    }

    @Override
    public Player calculateResult() {
        return null;
    }

    @Override
    public Score getResults() {
        return null;
    }
}

Complete the Implementation

Now we have created our application’s skeleton, and we have a better overall idea of how the game will work. So it is an excellent time to start filling the gaps and get the game working.

Let’s go back to our game’s entry point. The entry point which is the main method. Every statement executed by the game will be inside the main method.

Since you need to receive inputs from the user, we will need a Scanner class. Additionally, the game will run until the user indicates he wants to exit, so we will need a do-while loop to keep repeating.

Inside the loop, the game will:

  • Request the user selection and save it.
  • Pick a random option
  • Calculate the result
  • And finally, display the game results and ask the user if he wants to continue.

See all above in action in java below:

RockPaperScissorsGame

import java.util.Scanner;

public class RockPaperScissorsGame {

    public static void main(String[] args){

        GameController gameController = new RockPaperScissorsGameController();

        Scanner scanner = new Scanner(System.in);
        String userWantsToExit;

        System.out.print(gameController.welcomeMessage());

        do {
            System.out.println(gameController.pleaseEnterOptionMessage());

            int userOptionRaw = scanner.nextInt();

            GameOption userOption = GameOption.valueOf(userOptionRaw);

            gameController.selectUserChoice(userOption);

            GameOption machineChoice = gameController.randomMachineChoice();

            Player winner = gameController.calculateResult();

            Score score = gameController.getResults();

            System.out.printf("You played: %s and the machine played: %s \n", userOption.name(), machineChoice.name());
            if (Player.USER.equals(winner)) {
                System.out.println("You won!!");
            }
            if(Player.TIE.equals(winner)){
                System.out.println("Tie!!");
            }
            System.out.printf("You won %d games out of %d \n", score.getGamesWonByUser(), score.totalNumberOfGames());

            System.out.println("Continue playing(Y=Yes, N=No)?");
            userWantsToExit = scanner.next();

        }while(userWantsToExit.toUpperCase().equals("Y"));


    }
}

RockPaperScissorsGameController

And the last piece to complete our game is writing the code for the game controller, which is the game’s core piece.

The first two operations are simple. They only return the messages that should be displayed in the console to communicate with the user.

The selectUserChoice operation receives the user selected option and saves it.

Next is the randomMachineChoice method, which first generates a random number from 1 to 3 and then converts this number into a GameOption object.

The calculateResult method is another method. This method is responsible for comparing the user and the machine selections, working out who won and updating the scores. And last, the getResults, which returns the results so they can be displayed in the console.

import java.util.Random;

public class RockPaperScissorsGameController implements GameController {

    private GameOption userChoice = GameOption.EMPTY;
    private GameOption machineChoice = GameOption.EMPTY;
    private Score totalScore = new Score();


    @Override
    public String welcomeMessage() {

        return "           Welcome to          \n"+
               "   Rock Paper Scissors Game    \n"+
               "                               \n";
    }

    @Override
    public String pleaseEnterOptionMessage(){
        return  "         Please enter:         \n"+
                "            1. ROCK            \n"+
                "            2. PAPER           \n"+
                "            3. SCISSOR         \n"+
                "                               \n";
    }

    @Override
    public void selectUserChoice(GameOption userOption) {
        this.userChoice = userOption;
    }

    @Override
    public GameOption randomMachineChoice() {
        int randomNumberBetween1to3 = new Random().nextInt(3)+1;
        GameOption machineOption = GameOption.valueOf(randomNumberBetween1to3);
        this.machineChoice = machineOption;
        return machineOption;
    }

    @Override
    public Player calculateResult() {

        totalScore.incrementTotalNumberGames();

        if(machineChoice.equals(userChoice)){
            return Player.TIE;
        }
        if(machineChoice.isWinBy(userChoice)){
            totalScore.incrementGamesWonByUser();
            return Player.USER;
        }
        return Player.MACHINE;
    }

    @Override
    public Score getResults() {
        return totalScore;
    }

}

Source Code

All source code is available in Github. Go to Github

Conclusion

To summarise, we have seen how you can create the rock paper scissors game in java applying a software development process approach.

First, defining the requirements, in other words, how the game should work. Then creating a skeleton implementation to spread the functionality across different classes. And last, fill up the classes with the code to fulfill the initial requirements and make your code works!

I hope you enjoy this article, and thank you so much for reading and supporting this blog! Happy Coding! 🙂

More Interesting Articles

Project-Based Programming Introduction

Steady pace book with lots of worked examples. Starting with the basics, and moving to projects, data visualisation, and web applications

100% Recommended book for Java Beginners

Unique lay-out and teaching programming style helping new concepts stick in your memory

90 Specific Ways to Write Better Python

Great guide for those who want to improve their skills when writing python code. Easy to understand. Many practical examples

Grow Your Java skills as a developer

Perfect Boook for anyone who has an alright knowledge of Java and wants to take it to the next level.

Write Code as a Professional Developer

Excellent read for anyone who already know how to program and want to learn Best Practices

Every Developer should read this

Perfect book for anyone transitioning into the mid/mid-senior developer level

Great preparation for interviews

Great book and probably the best way to practice for interview. Some really good information on how to perform an interview. Code Example in Java