Rock, paper, scissors is a game played between two people using their hands. Both players will have to pronounce the formula "Rock, paper, scissors", after which they will simultaneously choose and make with one hand one of the three objects available in the game (stone, paper or scissors). The winner will be determined based on the resulting combination of items. The scissors beat the paper, the stone beats the scissors, and the paper beats the stone. If both players have chosen the same object, the game turn is considered a draw. This tutorial shows you how to write a Java program that replicates the dynamics of this game. One player will be represented by the user, while the second will be controlled by the computer.
Steps
Step 1. Create the main program class and name it
RockPaperScissors
.
This will be the main class where we will insert the code of the whole program. You can choose a different name for this class, such as
Game
or
Main
. Write in it the declaration of the methods related to the constructor and the main method "main".
public class RockPaperScissors {public RockPaperScissors () {} public static void main (String args) {}}
Step 2. Create an enumeration describing the three objects in the game (rock, paper, scissors)
We could use three simple strings to represent rock, paper and scissors, but an enumeration allows us to define our constants; using an enumeration is therefore a better choice at the code design level. Our enumeration called
Move
will have the following values:
ROCK
(stone),
PAPER
(card) e
SCISSORS
(scissors).
private enum Move {ROCK, PAPER, SCISSORS}
Step 3. Create two classes of type “private”, one called
User
and the other
Computer
.
These classes represent the players facing each other in the real game. If you wish you can choose to declare these classes as "public". The class
User
is the one that will ask the user to choose the object of his move between stone, paper or scissors, so we will need to write the method
getMove ()
to execute our move. The class too
Computer
will need to have a method
getMove ()
because the computer will also have to make its move. The code of these two methods we will implement later, for the moment we will limit ourselves to their declaration. The class
User
requires a constructor that creates the object
Scanner
used to read user input. The field
Scanner
it will be declared private for the “User” class and will be initialized inside the class constructor. Since we are using Java's default class,
Scanner
we will need to import it into our program by inserting the relative "import" line at the beginning of our code. The class
Computer
it doesn't require the use of a constructor, so we won't have to write code for this element. When will we initialize the object
Computer
Java will use the default constructor. Below you will find the code of our class
RockPaperScissors
written so far:
import java.util. Scanner; public class RockPaperScissors {private enum Move {ROCK, PAPER, SCISSORS} private class User {private Scanner inputScanner; public User () {inputScanner = new Scanner (System.in); } public Move getMove () {// Code of the method to be implemented later return null; }} private class Computer {public Move getMove () {// Code of the method to be implemented later return null; }} public RockPaperScissors () {} public static void main (String args) {}}
Step 4. Create the method
getMove ()
related to the class
Computer
.
This method will return the value of a random move chosen within the enumeration
Move
. We can create an "array" of enumerations
Move
calling the method
values ()
so:
Move.values ()
. To choose an enumeration
Move
random among those present in our "array" we need to generate a random index, which will be represented by an integer between 0 and the number of all the elements contained in our "array". To do this we can use the method
nextInt ()
of the class
Random
that we can import from the package
java.util
. After getting the random index, we can return the enumeration value
Move
corresponding, present in our "array".
public Move getMove () {Move moves = Move.values (); Random random = new Random (); int index = random.nextInt (moves.length); return moves [index]; }
Step 5. Write the method code
getMove ()
for the class
User
.
This method will have to return the value corresponding to the move entered by the user. We expect the user to write one of the following values: "rock", "paper" or "scissors". The first step is to ask the user to enter a value. To do this we use the following code:
System.out.print ("Rock, paper or scissors?")
. After that we use the method
nextLine ()
of the object
Scanner
to read user input and store it in an object of type "string". Now we need to check if the user has entered a valid move, while remaining lenient in the event of a typo. So we will limit ourselves to verifying that the first letter typed corresponds to "S" (in the case of "stone"), "C" (in the case of "paper") or "F" (in the case of "scissors"). We don't care if the user typed an uppercase or lowercase letter, as we'll use the method
toUpperCase ()
of the class
String
to capitalize all the characters entered by the user. If the user has not entered a valid move, we will ask him again to make his move. After that, based on user input, we will return the value corresponding to the chosen move.
public Move getMove () {// We ask the user for input System.out.print ("Rock, paper or scissors?"); // We read the input entered by the user String userInput = inputScanner.nextLine (); userInput = userInput.toUpperCase (); char firstLetter = userInput.charAt (0); if (firstLetter == 'S' || firstLetter == 'C' || firstLetter == 'F') {// We validate the input entered by the user switch (firstLetter) {case 'S': return Move. ROCK; case 'C': return Move. PAPER; case 'F': return Move. SCISSORS; }} // The user has not entered a valid move, we ask again to enter a move return getMove (); }
Step 6. Write the method
playAgain ()
for the class
User
.
The user must be able to play indefinitely. In order to determine if the user wants to play again, we need to write the method
playAgain ()
which will have to return a boolean value that can tell us if the user wants to continue in the game or not. Within this method, we will use the object
Scanner
that we previously created in the constructor of the “User” class to obtain a “Yes” or a “No” from the user. Again we will only check if the first letter entered is a “Y”, to determine if the user wishes to play again. Any other characters, numbers or symbols entered will correspond to the player's willingness to stop the game.
public boolean playAgain () {System.out.print ("Do you want to play again?"); String userInput = inputScanner.nextLine (); userInput = userInput.toUpperCase (); return userInput.charAt (0) == 'Y'; }
Step 7. Link the classes together
User
And
Computer
within the class
RockPaperScissors
.
Now that we have finished writing the code for the classes
User
And
Computer
we can focus on the actual game code. Within the classroom
RockPaperScissors
declares two private objects, one of type
User
and one of kind
Computer
. While running the game, we will need to access the two methods
getMove ()
of the respective "User" and "Computer" classes. These two objects will be initialized within the constructor of the class
RockPaperScissors
. We will also need to keep track of the score. To do this we will use fields
userScore
And
computerScore
which we will initialize to 0 inside the class constructor. Finally, we will have the additional need to keep track of the number of matches whose field
numberOfGames
it will be initialized to 0 inside the class constructor.
private User user; private Computer computers; private int userScore; private int computerScore; private int numberOfGames; public RockPaperScissors () {user = new User (); computer = new Computer (); userScore = 0; computerScore = 0; numberOfGames = 0; }
Step 8. Extend the enumeration
Move
so that it includes the method of telling us which is the winning move of each game round.
To do this we have to write the method
compareMoves ()
which returns the value 0 if the moves are equal, 1 if the current move beats the previous one and -1 if the previous move beats the current one. This pattern is useful for us to determine who will be the winner of the game. In the implementation of this method, first of all, we will return the value 0 if the moves are equal and we are therefore in a parity situation. After that we will write the block of code related to the return of the values 1 and -1.
private enum Move {ROCK, PAPER, SCISSORS; / ** * We compare the current move with the previous move to determine if it is a tie, if * it wins or if it loses * * @ otherMove parameter * to perform the comparison * @return 1 if this move beats the other, -1 if this move is beaten by the other * 0 if it is a tie * / public int compareMoves (Move otherMove) {// Case of a tie if (this == otherMove) return 0; switch (this) {case ROCK: return (otherMove == SCISSORS? 1: -1); case PAPER: return (otherMove == ROCK? 1: -1); case SCISSORS: return (otherMove == PAPER? 1: -1); } // The program should never reach this point return 0; }}
Step 9. Inside the classroom
RockPaperScissors
create the method
startGame ()
.
This is the method that allows you to play our game. Start the method code by simply inserting the following line
System.out.println
public void startGame () {System.out.println ("Rock, Paper, Scissors!"); }
Step 10. Read the moves made by the user and the computer
Inside the method
startGame ()
calls the method
getMove ()
of classes
User
And
Computer
. This will make the user and the computer perform one move.
Move userMove = user.getMove (); Move computerMove = computer.getMove (); System.out.println ("\ nYou played" + userMove + "."); System.out.println ("The computer played" + computerMove + ". / N");
Step 11. Compare the two chosen moves to determine who won the round between the user and the computer
To do this, use the method
compareMoves ()
of the enumeration
Move
. If the user wins, he increases his score by 1. If the user lost, increase the computer's score by 1. If it is a tie, do not change the players' scores. At the end of the comparison, increase the number of games played by 1.
int compareMoves = userMove.compareMoves (computerMove); switch (compareMoves) {case 0: // Draw System.out.println ("Draw!"); break; case 1: // User System.out.println wins (userMove + "beats" + computerMove + ". You win!"); userScore ++; break; case -1: // Computer System.out.println wins (computerMove + "hits" + userMove + ". You lost."); computerScore ++; break; } numberOfGames ++;
Step 12. Ask the user if he would like to play again
If so, call the method again
startGame ()
. If not, it calls the method
printGameStats ()
to print match statistics on screen. We will create this method in the next step.
if (user.playAgain ()) {System.out.println (); startGame (); } else {printGameStats (); }
Step 13. Write the method code
printGameStats ()
.
This method must print the game statistics on the screen: number of wins, number of losses, number of draws, number of rounds played and percentage of rounds won by the user. Win rate is calculated like this (# of wins + (# number of draws / 2)) / (# of rounds played). This method uses code
System.out.printf
to display the formatted text on the screen.
private void printGameStats () {int wins = userScore; int losses = computerScore; int ties = numberOfGames - userScore - computerScore; double percentageWon = (wins + ((double) ties) / 2) / numberOfGames; // Print the lines System.out.print ("+"); printDashes (68); System.out.println ("+"); // Print the System.out.printf titles ("|% 6s |% 6s |% 6s |% 12s |% 14s | / n", "WINS", "LOSS", "DRAWS", "GAMES PLAYED", " PERCENTAGE OF VICTORIES "); // Print the lines System.out.print ("|"); printDashes (10); System.out.print ("+"); printDashes (10); System.out.print ("+"); printDashes (10); System.out.print ("+"); printDashes (16); System.out.print ("+"); printDashes (18); System.out.println ("|"); // Print the values of the statistics System.out.printf ("|% 6d |% 6d |% 6d |% 12d |% 13.2f %% | / n", wins, losses, ties, numberOfGames, percentageWon * 100); // Print the closing line System.out.print ("+"); printDashes (68); System.out.println ("+"); }
Step 14. Inside the “main” class, write the code to start the game
An instance of the class will be initialized within the “main” class
RockPaperScissors
and the method will be called
startGame ()
public static void main (String args) {RockPaperScissors game = new RockPaperScissors (); game.startGame (); }
Step 15. Test your program
Now we have finished writing all the code related to our program that replicates the game "Rock, paper, scissors". It's time to compile and verify that everything is working correctly.
Example Program
import java.util. Random; import java.util. Scanner; public class RockPaperScissors {private User user; private Computer computers; private int userScore; private int computerScore; private int numberOfGames; private enum Move {ROCK, PAPER, SCISSORS; / ** * We compare the current move with the previous move to determine if it is a tie, if * it wins or if it loses * * @ otherMove parameter * to perform the comparison * @return 1 if this move beats the other, -1 if this move is beaten by the other * 0 if it is a tie * / public int compareMoves (Move otherMove) {// Tie if (this == otherMove) return 0; switch (this) {case ROCK: return (otherMove == SCISSORS? 1: -1); case PAPER: return (otherMove == ROCK? 1: -1); case SCISSORS: return (otherMove == PAPER? 1: -1); } // The program should never reach this point return 0; }} private class User {private Scanner inputScanner; public User () {inputScanner = new Scanner (System.in); } public Move getMove () {// Ask the user to perform a move System.out.print ("Rock, paper or scissors?"); // Read user input String userInput = inputScanner.nextLine (); userInput = userInput.toUpperCase (); char firstLetter = userInput.charAt (0); if (firstLetter == 'S' || firstLetter == 'C' || firstLetter == 'F') {// User has entered a valid input switch (firstLetter) {case 'S': return Move. ROCK; case 'C': return Move. PAPER; case 'F': return Move. SCISSORS; }} // The user has not entered a valid move. Request the entry of a new move. return getMove (); } public boolean playAgain () {System.out.print ("Do you want to play again?"); String userInput = inputScanner.nextLine (); userInput = userInput.toUpperCase (); return userInput.charAt (0) == 'Y'; }} private class Computer {public Move getMove () {Move moves = Move.values (); Random random = new Random (); int index = random.nextInt (moves.length); return moves [index]; }} public RockPaperScissors () {user = new User (); computer = new Computer (); userScore = 0; computerScore = 0; numberOfGames = 0; } public void startGame () {System.out.println ("STONE, PAPER, SCISSORS!"); // Perform the moves Move userMove = user.getMove (); Move computerMove = computer.getMove (); System.out.println ("\ nYou played" + userMove + "."); System.out.println ("Computer played" + computerMove + ". / N"); // Compare the moves made to determine the winner int compareMoves = userMove.compareMoves (computerMove); switch (compareMoves) {case 0: // Draw System.out.println ("Draw!"); break; case 1: // User System.out.println wins (userMove + "tap" + computerMove + ". You win! "); UserScore ++; break; case -1: // Win Computer System.out.println (computerMove +" beat "+ userMove +". You lost. "); ComputerScore ++; break;} numberOfGames ++; // Ask user if he wants to play again if (user.playAgain ()) {System.out.println (); startGame ();} else {printGameStats ();}} / ** * Print game stats. Percentage of wins takes ties into account as * were 1/2 point. * / private void printGameStats () {int wins = userScore; int losses = computerScore; int ties = numberOfGames - userScore - computerScore; double percentageWon = (wins + ((double) ties) / 2) / numberOfGames; // Print a line System.out.print ("+"); printDashes (68); System.out.println ("+"); // Print System.out headers. printf ("|% 6s |% 6s |% 6s |% 12s |% 14s | / n", "WINS", "LOSS", "DRAWS", "GAMES PLAYED", "PERCENTAGE OF WINS"); // Print the separator lines System.out.print ("|"); printDashes (10); System.out.print ("+"); printDas hes (10); System.out.print ("+"); printDashes (10); System.out.print ("+"); printDashes (16); System.out.print ("+"); printDashes (18); System.out.println ("|"); // print the System.out.printf values ("|% 6d |% 6d |% 6d |% 12d |% 13.2f %% | / n", wins, losses, ties, numberOfGames, percentageWon * 100); // print the closing line System.out.print ("+"); printDashes (68); System.out.println ("+"); } private void printDashes (int numberOfDashes) {for (int i = 0; i <numberOfDashes; i ++) {System.out.print ("-"); }} public static void main (String args) {RockPaperScissors game = new RockPaperScissors (); game.startGame (); }}