Rock, Paper, Scissors is a hand game played by two people. Both people would say "rock, paper, scissors" and then simultaneously form one of three objects (rock, paper, or scissors) with an outstretched hand. The winner is determined by the hand formations. Scissors beats paper, paper beats rock, and rock beats scissors. If both players play the same hand formation, it is considered a tie. We will write a simple game in Java to simulates Rock, Paper, Scissors where one player is the user and the other player is the computer.
Steps
-
Create the main class and call it
RockPaperScissors
. This will be the class where we will write the game. You may choose to name it something else such asGame
orMain
. Write in method declarations for the constructor and the main method.public class RockPaperScissors { public RockPaperScissors () { } public static void main ( String [] args ) { } }
-
Create an enumeration for the hand gestures (rock, paper, or scissors). We could use strings to represent rock, paper, or scissors, but an enumeration allows us to predefine our constants which means that using the enumeration is a better design. We will call our enum type
Move
with the valuesROCK
,PAPER
, andSCISSORS
.private enum Move { ROCK , PAPER , SCISSORS }
Advertisement -
Create two private classes
User
andComputer
. These classes will represent our players in the game. You may choose to make these classes public. TheUser
class will be the class that prompts the user for either rock, paper, or scissors, so we will need to write agetMove()
method. TheComputer
class will also need to have agetMove()
method so that the computer can also make a move. We will put placeholders in these methods and implement them later. TheUser
class will require a constructor that sets up theScanner
object to take in the user input. We will put theScanner
as a private field for the user and then initiate it in the constructor. Since we are using theScanner
class, we need to write an import statement for it at the top of our code. TheComputer
class does not require a constructor, so we do not need to write one; when we initiate theComputer
object, we will just be calling the default constructor. Here is what ourRockPaperScissors
class looks like now: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 () { // TODO: Implement this method return null ; } } private class Computer { public Move getMove () { // TODO: Implement this method return null ; } } public RockPaperScissors () { } public static void main ( String [] args ) { } }
-
Write the
getMove()
method for theComputer
class. This method will return a randomMove
. We can get an array ofMove
enumerations by calling thevalues()
method:Move.values()
. To choose a randomMove
enumeration in this values array, we need to generate a random index that is an integer between 0 and the length of our values array. To do this, we can use thenextInt()
method of theRandom
class which we need to import fromjava.util
. After we have gotten the random index, we can return theMove
of that index from our values array.public Move getMove () { Move [] moves = Move . values (); Random random = new Random (); int index = random . nextInt ( moves . length ); return moves [ index ]; }
-
Write the
getMove()
method for theUser
class. This method will return aMove
corresponding to what the user has input. We will expect the user to write either "rock", "paper", or "scissors". First, we need to prompt the user for an input:System.out.print("Rock, paper, or scissors? ")
. Then use thenextLine()
method of theScanner
object to get the user input as a string. We need now need to check if the user has submitted a valid move, but we can be lenient if the user has misspelled a word. So we will only check if the first letter of the user input is either "R" (for rock), "P" (for paper), or "S" (for scissors), and we won't care about the case because we will first use thetoUpperCase()
method of theString
class to make the user input string all uppercase. If the user has not entered a remotely correct input, we will prompt the user again. Then, depending on what the user has put in, we will return a corresponding move.public Move getMove () { // Prompt the user System . out . print ( "Rock, paper, or scissors? " ); // Get the user input String userInput = inputScanner . nextLine (); userInput = userInput . toUpperCase (); char firstLetter = userInput . charAt ( 0 ); if ( firstLetter == 'R' || firstLetter == 'P' || firstLetter == 'S' ) { // User has entered a valid input switch ( firstLetter ) { case 'R' : return Move . ROCK ; case 'P' : return Move . PAPER ; case 'S' : return Move . SCISSORS ; } } // User has not entered a valid input. Prompt again. return getMove (); }
-
Write a
playAgain()
method for theUser
class. The user should be able to play the game over and over again. In order to determine whether the user wants to play again, we need to write aplayAgain()
method that returns a boolean telling the game whether the user has determined to play again or not. In this method, we are using theScanner
that we had previously initiated in the constructor to get a "Yes" or a "No" from the user. We will only check if the first letter is 'Y' to determine whether the user wants to play again. Any other input will mean that the user does not want to play again.public boolean playAgain () { System . out . print ( "Do you want to play again? " ); String userInput = inputScanner . nextLine (); userInput = userInput . toUpperCase (); return userInput . charAt ( 0 ) == 'Y' ; }
-
Connect the
User
andComputer
classes together in theRockPaperScissors
class. Now that we have finished writing theUser
andComputer
classes, we can focus on working on our actual game. Create private fields for theUser
andComputer
classes in theRockPaperScissors
class. We will need to access these fields to access thegetMove()
methods when we're playing the game. In the constructor for theRockPaperScissors
class, initiate these fields. We will also need to keep track of the score inuserScore
andcomputerScore
fields, which we need to initiate as 0 in the constructor. We need to keep track of the number of games as well, which will also be a field initiated as 0.private User user ; private Computer computer ; private int userScore ; private int computerScore ; private int numberOfGames ; public RockPaperScissors () { user = new User (); computer = new Computer (); userScore = 0 ; computerScore = 0 ; numberOfGames = 0 ; }
-
Extend the
Move
enum to include a method that tells us which move wins in each case. We need to write acompareMoves()
method that returns 0 if the moves are the same, 1 if the current move beats the other move, and -1 if the current move loses to the other move. This will be useful for determining the winner in the game. To implement this method, we will first return 0 if the moves are the same and therefore we have a tie. Then write a switch statement for returning 1 or -1.private enum Move { ROCK , PAPER , SCISSORS ; /** * Compares this move with another move to determining a tie, a win, or * a loss. * * @param otherMove * move to compare to * @return 1 if this move beats the other move, -1 if this move loses to * the other move, 0 if these moves 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 ); } // Should never reach here return 0 ; } }
-
Create a
startGame()
method in theRockPaperScissors
class. This method will be the playing of the game. Start out by putting a simpleSystem.out.println
in the method.public void startGame () { System . out . println ( "ROCK, PAPER, SCISSORS!" ); }
-
Get moves from the user and the computer. In the
startGame()
method, use thegetMove()
methods from theUser
class and theComputer
class to get the user and the computer's moves.Move userMove = user . getMove (); Move computerMove = computer . getMove (); System . out . println ( "\nYou played " + userMove + "." ); System . out . println ( "Computer played " + computerMove + ".\n" );
-
Compare the two moves and determine whether the user won or the computer won. Use the
compareMoves()
method from theMove
enum to to determine whether the user won or not. If the user won, increment the user score by 1. If the user lost, increment the computer score by 1. If there was a tie, do not increment any of the scores. Then increment the number of games played by one.int compareMoves = userMove . compareMoves ( computerMove ); switch ( compareMoves ) { case 0 : // Tie System . out . println ( "Tie!" ); break ; case 1 : // User wins System . out . println ( userMove + " beats " + computerMove + ". You won!" ); userScore ++; break ; case - 1 : // Computer wins System . out . println ( computerMove + " beats " + userMove + ". You lost." ); computerScore ++; break ; } numberOfGames ++;
-
Ask if the user wants to play again. If the user wants to play again, call
startGame()
again. Otherwise, callprintGameStats()
which will print out the statistics of the game. We will write this method in the next step.if ( user . playAgain ()) { System . out . println (); startGame (); } else { printGameStats (); }
-
Write the
printGameStats()
method. This method will display the statistics of the game: number of wins, number of losses, number of ties, number of games played, and percentage of games won by the user. The percentage of games won is calculated by the (# wins + (# ties/2))/(# games played). This method usesSystem.out.printf
to print out formatted text.private void printGameStats () { int wins = userScore ; int losses = computerScore ; int ties = numberOfGames - userScore - computerScore ; double percentageWon = ( wins + (( double ) ties ) / 2 ) / numberOfGames ; // Line System . out . print ( "+" ); printDashes ( 68 ); System . out . println ( "+" ); // Print titles System . out . printf ( "| %6s | %6s | %6s | %12s | %14s |\n" , "WINS" , "LOSSES" , "TIES" , "GAMES PLAYED" , "PERCENTAGE WON" ); // Line 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 values System . out . printf ( "| %6d | %6d | %6d | %12d | %13.2f%% |\n" , wins , losses , ties , numberOfGames , percentageWon * 100 ); // Line System . out . print ( "+" ); printDashes ( 68 ); System . out . println ( "+" ); }
-
Start the game in the main class. In the main class, initialize an instance of the
RockPaperScissors
class and call thestartGame()
method.public static void main ( String [] args ) { RockPaperScissors game = new RockPaperScissors (); game . startGame (); }
-
Test out your game. Now that we have gone through all the effort of writing the Rock, Paper, Scissors game, it's time to compile and test everything out!Advertisement
Expert Q&A
Ask a Question
200 characters left
Include your email address to get a message when this question is answered.
Submit
Advertisement
Sample Program
import
java.util.Random
;
import
java.util.Scanner
;
public
class
RockPaperScissors
{
private
User
user
;
private
Computer
computer
;
private
int
userScore
;
private
int
computerScore
;
private
int
numberOfGames
;
private
enum
Move
{
ROCK
,
PAPER
,
SCISSORS
;
/**
* Compares this move with another move to determining a tie, a win, or
* a loss.
*
* @param otherMove
* move to compare to
* @return 1 if this move beats the other move, -1 if this move loses to
* the other move, 0 if these moves 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
);
}
// Should never reach here
return
0
;
}
}
private
class
User
{
private
Scanner
inputScanner
;
public
User
()
{
inputScanner
=
new
Scanner
(
System
.
in
);
}
public
Move
getMove
()
{
// Prompt the user
System
.
out
.
print
(
"Rock, paper, or scissors? "
);
// Get the user input
String
userInput
=
inputScanner
.
nextLine
();
userInput
=
userInput
.
toUpperCase
();
char
firstLetter
=
userInput
.
charAt
(
0
);
if
(
firstLetter
==
'R'
||
firstLetter
==
'P'
||
firstLetter
==
'S'
)
{
// User has entered a valid input
switch
(
firstLetter
)
{
case
'R'
:
return
Move
.
ROCK
;
case
'P'
:
return
Move
.
PAPER
;
case
'S'
:
return
Move
.
SCISSORS
;
}
}
// User has not entered a valid input. Prompt again.
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
(
"ROCK, PAPER, SCISSORS!"
);
// Get moves
Move
userMove
=
user
.
getMove
();
Move
computerMove
=
computer
.
getMove
();
System
.
out
.
println
(
"\nYou played "
+
userMove
+
"."
);
System
.
out
.
println
(
"Computer played "
+
computerMove
+
".\n"
);
// Compare moves and determine winner
int
compareMoves
=
userMove
.
compareMoves
(
computerMove
);
switch
(
compareMoves
)
{
case
0
:
// Tie
System
.
out
.
println
(
"Tie!"
);
break
;
case
1
:
// User wins
System
.
out
.
println
(
userMove
+
" beats "
+
computerMove
+
". You won!"
);
userScore
++;
break
;
case
-
1
:
// Computer wins
System
.
out
.
println
(
computerMove
+
" beats "
+
userMove
+
". You lost."
);
computerScore
++;
break
;
}
numberOfGames
++;
// Ask the user to play again
if
(
user
.
playAgain
())
{
System
.
out
.
println
();
startGame
();
}
else
{
printGameStats
();
}
}
/**
* Prints out the statistics of the game. Calculates ties as 1/2 a win in
* percentage won.
*/
private
void
printGameStats
()
{
int
wins
=
userScore
;
int
losses
=
computerScore
;
int
ties
=
numberOfGames
-
userScore
-
computerScore
;
double
percentageWon
=
(
wins
+
((
double
)
ties
)
/
2
)
/
numberOfGames
;
// Line
System
.
out
.
print
(
"+"
);
printDashes
(
68
);
System
.
out
.
println
(
"+"
);
// Print titles
System
.
out
.
printf
(
"| %6s | %6s | %6s | %12s | %14s |\n"
,
"WINS"
,
"LOSSES"
,
"TIES"
,
"GAMES PLAYED"
,
"PERCENTAGE WON"
);
// Line
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 values
System
.
out
.
printf
(
"| %6d | %6d | %6d | %12d | %13.2f%% |\n"
,
wins
,
losses
,
ties
,
numberOfGames
,
percentageWon
*
100
);
// 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
();
}
}
About this article
Thanks to all authors for creating a page that has been read 138,095 times.
Advertisement