RPSSL resolution logic#
How do we determine which player has won?
In other words, how do we resolve different situations into win, lose, and tie?
Analyzing an easier game: Rock paper scissors#
If we have only rock πͺ¨ paper ποΈ and scissors βοΈ, then we have 9 combinations for player 1 and player 2 named as p1 and p2, respectively.
p1 |
p2 |
p1 β¦ |
|---|---|---|
πͺ¨ |
πͺ¨ |
tie |
πͺ¨ |
ποΈ |
loses |
πͺ¨ |
βοΈ |
wins |
ποΈ |
πͺ¨ |
wins |
ποΈ |
ποΈ |
tie |
ποΈ |
βοΈ |
loses |
βοΈ |
πͺ¨ |
loses |
βοΈ |
ποΈ |
wins |
βοΈ |
βοΈ |
tie |
How would you implement this in C?
Do you see any simplifications on the table that leads to less rows?
After simplification we end up with:
p1 |
p2 |
p1 β¦ |
|---|---|---|
πͺ¨ |
ποΈ |
loses |
πͺ¨ |
βοΈ |
wins |
ποΈ |
πͺ¨ |
wins |
ποΈ |
βοΈ |
loses |
βοΈ |
πͺ¨ |
loses |
βοΈ |
ποΈ |
wins |
else |
tie |
As a result, we have 3 * 3 - 3 = 6 if-else if lines with Boolean expressions and one else line.
Activity 29 (RPS resolution logic)
3 min. Draw a flowchart for the resolution table above.
Implement it using the template below:
3 min. using
if-else3 min. using
switch
Which solution do you prefer?
if-elseswitch
#include <stdio.h>
enum { ROCK, PAPER, SCISSORS, SHAPE_COUNT } p1, p2;
const char *SHAPE_STRINGS[] = {"πͺ¨", "οΈποΈ", "βοΈ"};
int main() {
for (size_t p1 = 0; p1 < SHAPE_COUNT; ++p1) {
for (size_t p2 = 0; p2 < SHAPE_COUNT; ++p2) {
printf("If p1: %s and p2: %s => ", SHAPE_STRINGS[p1],
SHAPE_STRINGS[p2]);
// YOUR CODE HERE
}
puts("");
}
}
The output should be:
If p1: πͺ¨ and p2: πͺ¨ => Tie.
If p1: πͺ¨ and p2: οΈποΈ => p1 looses.
If p1: πͺ¨ and p2: βοΈ => p1 wins.
If p1: οΈποΈ and p2: πͺ¨ => p1 wins.
If p1: οΈποΈ and p2: οΈποΈ => Tie.
If p1: οΈποΈ and p2: βοΈ => p1 looses.
If p1: βοΈ and p2: πͺ¨ => p1 looses.
If p1: βοΈ and p2: οΈποΈ => p1 wins.
If p1: βοΈ and p2: βοΈ => Tie.
Important
switch only works with integers. You cannot use it with arrays like:
switch (player_tuple) {
case {ROCK, SCISSORS}:
...
}
Moving on to πͺ¨βοΈποΈπ¦π#
In our problem we have five different items. This corresponds to 5 * 5 - 5 + 1 = 21 if-else if-else lines. This is too long. A better idea is to analytically describe the win-lose table:
Fig. 14 rock paper scissors lizard Spock resolution diagram
CC BY-SA 3.0. By DMacks (talk). Source: Wikimedia Commons#
Let us try to extract a pattern from the resolution diagram in Fig. 14. Assume that clock-wise rotation is a forwards direction.
In the diagram we see that Spock wins against scissors and stone, which are +1 and +3 forward in the circle. Spock loses against lizard and paper, which are +2 and +4 forward in the circle. In other words, if the second shape is +1 and +3 away, Spock wins, and if the second shape is +2 and +4 shapes away, then Spock loses.
Does the rule described above apply to all shapes? Why?
Describing the resolution using the distance between shapes#
If we generalize our rule for all items, we get:
If the second item is +1 or +3 away, then the first item wins. If the second item is +2 or +4 away, then the first item loses.
How can we determine if the second item is +1 or +3 away, i.e the distance? An idea is to attach numbers to all items, for example:
Spock
scissors
paper
rock
lizard
The numbers 0 to 4 become their ids. Now we can determine the distance by subtracting their ids.
Example: rock vs lizard. lizardβs id is 4, and rockβs id is 3, so we get 4-3=1, which means that rock wins against the lizard. The resolution diagram confirms this.
This approach can be summarized as a table, where id1 and id2 stand for the ids of the items.
p2-p1 |
p1 β¦ |
|---|---|
0 |
tie |
1 or 3 |
wins |
2 or 4 |
loses |
This was too fast. Do you see any problems with this table?
Expanding the resolution table#
What happens if p1βs id is greater than p2βs id? Then we get negative numbers. For example for p1 = 4 and p2 = 0, we get p2 - p1 = -4. 4 means lizard and 0 Spock; and lizard wins against Spock.
We can look at the negative numbers from another perspective. -4 means a counter-clockwise turn, which is the same as if we moved 1 clockwise. So we can extend the table as follows:
p2-p1 |
p1 β¦ |
|---|---|
0 |
tie |
-4 or -2 or 1 or 3 |
wins |
-3 or -1 or 2 or 4 |
loses |
Activity 30 (RPSSL resolution logic using difference between shapes)
Implement the resolution logic above either with
if-else ...orswitchstatement.
Two students with different approaches will demonstrate and we will compare.
Use the following template. Your output should be the same as the output below.
#include <stdio.h>
enum { SPOCK, SCISSORS, PAPER, ROCK, LIZARD, SHAPE_COUNT } player1, player2;
const char *SHAPE_STRINGS[] = {"π", "βοΈ", "οΈποΈ", "πͺ¨", "π¦"};
int main() {
for (size_t player1 = SPOCK; player1 < SHAPE_COUNT; ++player1) {
for (size_t player2 = SPOCK; player2 < SHAPE_COUNT; ++player2) {
printf("If player1: %s and player2: %s => ", SHAPE_STRINGS[player1],
SHAPE_STRINGS[player2]);
// YOUR CODE HERE
}
puts("");
}
}
If player1: π and player2: π => Tie.
If player1: π and player2: βοΈ => Player1 wins.
If player1: π and player2: οΈποΈ => Player1 looses.
If player1: π and player2: πͺ¨ => Player1 wins.
If player1: π and player2: π¦ => Player1 looses.
If player1: βοΈ and player2: π => Player1 looses.
If player1: βοΈ and player2: βοΈ => Tie.
If player1: βοΈ and player2: οΈποΈ => Player1 wins.
If player1: βοΈ and player2: πͺ¨ => Player1 looses.
If player1: βοΈ and player2: π¦ => Player1 wins.
If player1: οΈποΈ and player2: π => Player1 wins.
If player1: οΈποΈ and player2: βοΈ => Player1 looses.
If player1: οΈποΈ and player2: οΈποΈ => Tie.
If player1: οΈποΈ and player2: πͺ¨ => Player1 wins.
If player1: οΈποΈ and player2: π¦ => Player1 looses.
If player1: πͺ¨ and player2: π => Player1 looses.
If player1: πͺ¨ and player2: βοΈ => Player1 wins.
If player1: πͺ¨ and player2: οΈποΈ => Player1 looses.
If player1: πͺ¨ and player2: πͺ¨ => Tie.
If player1: πͺ¨ and player2: π¦ => Player1 wins.
If player1: π¦ and player2: π => Player1 wins.
If player1: π¦ and player2: βοΈ => Player1 looses.
If player1: π¦ and player2: οΈποΈ => Player1 wins.
If player1: π¦ and player2: πͺ¨ => Player1 looses.
If player1: π¦ and player2: π¦ => Tie.