Posted by Marta on February 2, 2023 Viewed 9434 times
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.
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!
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:
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:
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:
totalScore
containing the total number of gamesAt 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; } }
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:
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; } }
All source code is available in Github. Go to Github
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! 🙂
Steady pace book with lots of worked examples. Starting with the basics, and moving to projects, data visualisation, and web applications
Unique lay-out and teaching programming style helping new concepts stick in your memory
Great guide for those who want to improve their skills when writing python code. Easy to understand. Many practical examples
Perfect Boook for anyone who has an alright knowledge of Java and wants to take it to the next level.
Excellent read for anyone who already know how to program and want to learn Best Practices
Perfect book for anyone transitioning into the mid/mid-senior developer level
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