Java programmer expert
Who doesn’t know the popular game Rock, Paper, Scissors we used to play as kids? But who would have thought back then that one day they would be able to program it in their favourite programming language, for example Java.

V článku sa dozvieš:
Few people know that Rock, Paper, Scissors is a hand game that is said to have originated in China, from where it spread to Japan. There it originated in its modern form as we know it, and in the early 20th century it spread very quickly around the world.
We certainly don’t need to imagine the rules of the game. But if there is anyone who doesn’t know it yet, we will briefly mention them.
It is most often played by two players (or more), each of whom subconsciously chooses either a rock, paper or scissors. On the count of one, two, three, both players simultaneously show what they have chosen – rock (closed fist), or scissors (using index and middle fingers), or paper (open hand). The result of the game, which is of course played over multiple rounds, is a draw, a win, or a loss.
The player who plays the stone beats the other player who chooses the scissors (the stone dulls the scissors), but loses to the player who played the paper (the paper covers the rock). The player with paper loses to the player who chose scissors (scissors cut the paper). If both players choose the same shape, the game is a tie and is usually repeated to break the tie.
Rock, paper, scissors is often used as a method of fair selection among children when it comes to which child will start something first.
Did you know that?
Various competitive tournaments were also organized for Stone, Paper, Scissors. For example, the winners of the tournaments took home between $5,000 and $20,000.
Today we will program this game together in Java. To make this game more interesting for players to play, we will also program an artificial intelligence (AI) that will not randomly decide whether to use a rock, paper, or scissors in each round, but will choose one of the default strategies in each round. Of course the player will have no idea what gesture the computer AI has just chosen.
You definitely don’t want to play Rock, Paper, Scissors with a robot. In 2012, researchers at the Ishikawa Watanabe Laboratory at the University of Tokyo created a robotic arm that can win any game against a human opponent. Using a high-speed camera, the robot recognizes within one millisecond what shape the human hand is making and then creates the corresponding winning shape.
The game will be played for a predefined number of rounds, which will be specified when the game instance is created. Since the game rounds are very fast and we want to test the behavior of the AI, we set the default value for the number of rounds to 20.
At the start of each round we will need to record the player’s selection, select the AI strategy for that round and use that to determine the AI computer’s selection. The AI will choose randomly from the default strategies, making it difficult for the player to determine what gesture the computer will play.
We then check who picked what and allocate points accordingly, +1 for a win, 0 for a draw or a loss. The first one to reach 20 points wins the game.
The game’s artificial intelligence will record the player’s winning gestures and decide which gesture to play based on the history. Basic strategies will include:
People are still debating which game strategy is the best today. Our articles try to teach readers something new, show them how to solve some problems, and we’re most excited when they start experimenting with the program and coming up with their own game strategies. You can also get inspired by this video, or by this article on Rempton games in English.
So let’s get down to programming the game in Java.
The Strategy design pattern is well suited for implementing an AI strategy.
This program will be a simple console game where the player chooses a rock, paper, or scissors and plays against the computer’s AI, which randomly chooses one of many strategies each round. The winner is determined based on the rules of the game.
Enum Move
Enum Move defines possible moves (rock, paper, scissors) and provides a method for comparing player and AI moves and a method for determining the best counter-move to a given move.
package games.rockpaperscissors;
public enum Move {
ROCK, PAPER, SCISSORS;
// Method to check who won
public static int compareMoves(Move player, Move ai) {
// Draw
if (player == ai) {
return 0;
}
switch (player) {
case ROCK:
// Rock beats Scissors, loses to Paper
return (ai == SCISSORS) ? 1 : -1;
case PAPER:
// Paper beats Rock, loses to Scissors
return (ai == ROCK) ? 1 : -1;
case SCISSORS:
// Scissors beats Paper, loses to Rock
return (ai == PAPER) ? 1 : -1;
}
return 0;
}
public static Move counterMove(Move move) {
switch (move) {
case ROCK:
return Move.PAPER;
case PAPER:
return Move.SCISSORS;
case SCISSORS:
return Move.ROCK;
}
throw new IllegalArgumentException();
}
}
Interface AIStrategy
Interface AIStrategy defines a nextMove() method that decides what move the AI will make based on history.
Specific Strategies
: AI has different strategies it can use. The strategy is chosen randomly before each round, which means that it is difficult for the player to predict what move the AI will choose.
package games.rockpaperscissors.ai.strategies;
import games.rockpaperscissors.Move;
import java.util.List;
public interface AIStrategy {
Move nextMove(List<Move> playerHistory, List<Move> aiHistory);
}
Class RandomStrategy
Random selection of a gesture.
package games.rockpaperscissors.ai.strategies;
import games.rockpaperscissors.Move;
import java.util.List;
import java.util.Random;
public class RandomStrategy implements AIStrategy {
private final Random random = new Random();
@Override
public Move nextMove(List<Move> playerHistory, List<Move> aiHistory) {
return Move.values()[random.nextInt(Move.values().length)];
}
}
Class RepeatLastMoveStrategy
Repeat the last gesture of the player.
package games.rockpaperscissors.ai.strategies;
import games.rockpaperscissors.Move;
import java.util.List;
public class RepeatLastMoveStrategy implements AIStrategy {
@Override
public Move nextMove(List<Move> playerHistory, List<Move> aiHistory) {
return aiHistory.isEmpty()
? new RandomStrategy().nextMove(playerHistory, aiHistory)
: aiHistory.get(aiHistory.size() - 1);
}
}
Class CounterLastPlayerMoveStrategy
Counter-move to a player’s gesture from the previous round.
package games.rockpaperscissors.ai.strategies;
import games.rockpaperscissors.Move;
import java.util.List;
public class CounterLastPlayerMoveStrategy implements AIStrategy {
@Override
public Move nextMove(List<Move> playerHistory, List<Move> aiHistory) {
if(!playerHistory.isEmpty()) {
Move lastPlayer = playerHistory.get(playerHistory.size() - 1);
return Move.counterMove(lastPlayer);
}
return new RandomStrategy().nextMove(playerHistory, aiHistory);
}
}
Class RepeatMostFrequentPlayerMoveStrategy
Repeats the gesture that the player used most often.
package games.rockpaperscissors.ai.strategies;
import games.rockpaperscissors.Move;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class RepeatMostFrequentPlayerMoveStrategy implements AIStrategy {
@Override
public Move nextMove(List<Move> playerHistory, List<Move> aiHistory) {
if(!playerHistory.isEmpty()) {
Map<Move, Integer> moveFrequency = new HashMap<>();
for(Move move : playerHistory) {
moveFrequency.put(move, moveFrequency.getOrDefault(move, 0) + 1);
}
return Collections.max(moveFrequency.entrySet(), Map.Entry.comparingByValue()).getKey();
}
return new RandomStrategy().nextMove(playerHistory, aiHistory);
}
}
Class CounterMostFrequentPlayerMoveStrategy
The counter-move to the gesture that the player used most often.
package games.rockpaperscissors.ai.strategies;
import games.rockpaperscissors.Move;
import java.util.List;
public class CounterMostFrequentPlayerMoveStrategy implements AIStrategy {
@Override
public Move nextMove(List<Move> playerHistory, List<Move> aiHistory) {
if(!playerHistory.isEmpty()) {
Move mostFrequentMove = new RepeatMostFrequentPlayerMoveStrategy().nextMove(playerHistory, aiHistory);
// Counter the most frequent player's move
return Move.counterMove(mostFrequentMove);
}
return new RandomStrategy().nextMove(playerHistory, aiHistory);
}
}
RockPaperScissors class
Class RockPaperScissorsGame implements the overall game logic and manages the game flow, score recording and strategy selection.
package games.rockpaperscissors;
import games.rockpaperscissors.ai.strategies.*;
import java.util.*;
public class RockPaperScissors {
private final int totalRounds;
private final List<Move> playerHistory = new ArrayList<>();
private final List<Move> aiHistory = new ArrayList<>();
private int playerScore = 0;
private int aiScore = 0;
private final List<AIStrategy> aiStrategies = Arrays.asList(
new RandomStrategy(),
new RepeatLastMoveStrategy(),
new CounterLastPlayerMoveStrategy(),
new RepeatMostFrequentPlayerMoveStrategy(),
new CounterMostFrequentPlayerMoveStrategy()
);
public RockPaperScissors(int totalRounds) {
this.totalRounds = totalRounds;
}
private Move getPlayerMove(int input) {
switch (input) {
case 1:
return Move.ROCK;
case 2:
return Move.PAPER;
case 3:
return Move.SCISSORS;
default:
Move playerMove = new RandomStrategy().nextMove(playerHistory, aiHistory);
System.out.println("Chybny vstup, vyberam za hraca: " + playerMove);
return playerMove;
}
}
public void play() {
Scanner scanner = new Scanner(System.in);
Random random = new Random();
while (playerScore < totalRounds && aiScore < totalRounds) {
System.out.println("Vyber si: (1) Kamen, (2) Papier, (3) Noznice");
Move playerMove = getPlayerMove(scanner.nextInt());
Move aiMove = aiStrategies.get(random.nextInt(aiStrategies.size()))
.nextMove(playerHistory, aiHistory);
System.out.println("HRAC vybral: " + playerMove);
System.out.println("AI vybrala: " + aiMove);
// Compare moves
int result = Move.compareMoves(playerMove, aiMove);
if (result > 0) {
System.out.println("Vyhral si toto kolo.");
playerScore++;
} else if (result < 0) {
System.out.println("AI vyhrala toto kolo.");
aiScore++;
}
// Record moves
playerHistory.add(playerMove);
aiHistory.add(aiMove);
System.out.println("Aktualne skore - Hrac: " + playerScore + " | AI: " + aiScore);
System.out.println();
}
if(playerScore >= totalRounds) {
System.out.println("Gratulujeme! Vyhral si tuto hru!");
}
else {
System.out.println("AI vyhrala tuto hru! Skus ju porazit.");
}
}
}
Main Class
import games.rockpaperscissors.RockPaperScissors;
public class Main {
public static void main(String[] args) {
RockPaperScissors game = new RockPaperScissors(20);
game.play();
}
}
The output of a 3-round game can look like this:

In this Java game, the artificial intelligence plays very well and it is not so easy to win in a multi-round game.
Here you can download the source code of RockPaperScissors in Java.
If you’re looking for a job and you’re a Java developer, check out our employee benefits and respond to our job offers!
Related articles