Jump to final code solutions:
A common exercise when learning to code is to build a simple Rock, Paper, Scissors game. Perhaps the most obvious solution to the logic of this game is to decide the winner using an if/else construct that compares the moves:
if(playerA == playerB) {
result = 'Tie';
} else if((playerA == 'rock' AND playerB == 'scissors') OR (playerA == 'paper' AND playerB == 'rock') OR (playerA == 'scissors' AND playerB == 'paper')) {
result = 'Player A';
} else {
result = 'Player B';
}
This works but if the point is to strengthen our “programming muscles”, one must wonder if there’s a more concise way of handling things. Specifically, what if we could solve the logic of Rock, Paper, Scissors mathematically?
To tackle this, let’s first assign numerical values to each of the moves:
- Rock = 1
- Paper = 2
- Scissors = 3
Then, we can identify a cyclical relationship that exists between the moves, where winning occurs in the clockwise direction, while losing occurs in the counter-clockwise direction:
Finally, we need an expression to capture this pattern:
(playerA + 1) % 3 == playerB % 3
If the above expression evaluates to True, Player B’s move wins.
This expression uses the mod operator (%
) which returns the remainder of a division operation. Some examples:
- 2 % 3 = 2 because 2 divided by 3 has a quotient of 0 and a remainder of 2
- 4 % 3 = 1 because 4 divided by 3 has a quotient of 1 and a remainder of 1
- 3 % 3 = 0 because 3 divided by 3 has a quotient of 1 and a remainder of 0
Knowing this, let's break down our equation:
(playerA + 1) % 3 == playerB % 3
The left part of this expression calculates which move would defeat Player A’s move. For example, if Player A chose Rock (1), the expression evaluate as 2 because:
(1 + 1) % 3 = 2
From this we know that the prevailing move would be Paper (2).
The right part of the expression then determines if this is Player B’s move and if it is, the full expression evaluates to True and Player B is the winner.
Another example
Player A chooses Scissors (2)
Player B chooses Paper (2).
The left part of the expression evaluates to 1 because:
(2 + 2) % 3 = 1
And the right part of the expression evaluates to 0 because:
1 % 2 = 0
And because 1 does not equal 0, then Player A wins.
Ties
Of course, this mathematical equation does not capture the scenario where both players choose the same move and it’s a tie. That would be something you'd handle separately with an if construct, as is shown in the code examples below.
Code
PHP Solution
<?php
$moves = [
1 => 'Rock',
2 => 'Paper',
3 => 'Scissors'
];
# For this demo we randomly generate the player moves
# in a real application you’d want to collect this as input from the players
$playerA = rand(1, 3);
$playerB = rand(1, 3);
# Determine winner
if ($playerA == $playerB) {
$result = 'Tie';
} elseif (($playerA + 1) % 3 == $playerB % 3) {
$result = 'Player B wins';
} else {
$result = 'Player A wins';
}
?>
<!doctype html>
<html lang='en'>
<head>
<title>Rock, Paper, Scissors</title>
</head>
<body>
<div id='playerA'>Player A: <?=$moves[$playerA]?></div>
<div id='playerB'>Player B: <?=$moves[$playerB]?> </div>
<div id='result'>Result: <?=$result?></div>
</body>
</html>
JavaScript solution
<!doctype html>
<html lang='en'>
<head>
<title>Rock, Paper, Scissors</title>
</head>
<body>
<div id='playerA'>Player A: </div>
<div id='playerB'>Player B: </div>
<div id='result'>Results: </div>
</body>
<script defer>
let moves = {
1: "Rock",
2: "Paper",
3: "Scissors"
};
// For this demo we randomly generate the player moves; in a real application you’d want to collect this as input from the players
let playerA = Math.ceil(Math.random() * 3);
let playerB = Math.ceil(Math.random() * 3);
let result = '';
if (playerA == playerB) {
result = 'Tie';
} else if ((playerA + 1) % 3 == playerB % 3) {
result = 'Player B wins';
} else {
result = 'Player A wins';
}
document.getElementById('playerA').innerHTML += moves[playerA];
document.getElementById('playerB').innerHTML += moves[playerB];
document.getElementById('result').innerHTML = result;
</script>
</html>
Python solution
import random
moves = {
1: 'Rock',
2: 'Paper',
3: 'Scissors'
}
# For this demo we randomly generate the player moves
# in a real application you’d want to collect this as input from the players
playerA = random.randint(1, 3)
playerB = random.randint(1, 3)
# Determine winner
if (playerA == playerB):
result = 'Tie'
elif ((playerA + 1) % 3 == playerB % 3):
result = 'Player B wins'
else:
result = 'Player A wins'
print('Player A: ' + str(moves[playerA]))
print('Player B: ' + str(moves[playerB]))
print('Result: ' + str(result))