Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scalable solution for Rock-Paper-Scissor

Tags:

java

algorithm

Just went through a variant of the game : Rock-Paper-Scissor-Lizard-Spock

I have written a Java code for traditional R-P-S problem, but when I tried extending my code for the newer version of the game (R-P-S-L-S)..I felt my code is terribly bad. Here is a snippet :

 if (player1.equals("ROCK") && 
         player2.equals("SCISSORS")) {
        winner = 1;
    }
    // Paper covers rock...
    else if (player1.equals("PAPER") &&
         player2.equals("ROCK")) {
        winner = 1;
    }
    // Scissors cut paper...
    else if (player1.equals("SCISSORS") &&
         player2.equals("PAPER")) {
        winner = 1;
    }
    else {
        winner = 2;
    }

I realized the code cant be extended easily for the newer version - as well as for more than 2 players. This is mainly because of multiple if/else or switch/cases. I need some help re-designing my code for achieving the 2 objectives :

  1. Further modification as per R-P-C-L-S problem.

  2. Support for more than 2 players.

I don't need code, just some guidelines should help.

Thanks !!

EDIT : Seems like I was wrong in thinking that this game can be played by more than 2 players. I am sorry for this mistake, please ignore the second requirement.

like image 708
dev Avatar asked Mar 04 '12 07:03

dev


People also ask

How is Rock Paper Scissors game theory?

Well, in theory, the game has 3 outcomes: a win, loss, or tie. Rock defeats scissors, scissors defeats paper, and paper defeats rock. Players who play Rock-Paper-Scissors have an equal probability of winning, assuming that both players choose options completely randomly. Unfortunately, this is not the case.


2 Answers

In, Rock-Paper-Scissor games, it is easy to decide if move a wins against move b using their index at a cycle. So you don't have to manually decide in your code the result of every combination as other answers here suggest.


For the Rock-Paper-Scissor-Spock-Lizard version:

Let's assign a number to each move (0, 1, 2, 3, 4).

Notice that every move beats two moves:

  1. The move previous to it in the cycle (or four cases ahead)
  2. The move two cases ahead in the cycle

So let d = (5 + a - b) % 5. Then:

  1. d = 1 or d = 3 => a wins
  2. d = 2 or d = 4 => b wins
  3. d = 0 => tie

For the Rock-Paper-Scissor version:

let d = (3 + a - b) % 3. Then:

  1. d = 1 => a wins
  2. d = 2 => b wins
  3. d = 0 => tie

Generalization For n >= 3 and n odd:

Let d = (n + a - b) % n. Then:

  1. If d = 0 => tie
  2. If d % 2 = 1 => a wins
  3. If d % 2 = 0 => b wins

enter image description here

like image 95
sch Avatar answered Nov 15 '22 11:11

sch


The nature of Rock-Paper-Scissors is such that you have to explicitly handle the case for every possible combination of states. So the number of cases you have to cover increases exponentially with the number of players, and polynomially (with the order of the polynomial being the number of players) with the number of options.

Having said that, Java's enums are good for this kind of thing.

Here's my stab at it:

import java.util.Arrays;
import java.util.List;

enum Result {
    WIN, LOSE, DRAW;
}

enum Option {

    ROCK(SCISSORS),
    PAPER(ROCK),
    SCISSORS(PAPER);

    private List<Option> beats;

    private Option(Option... beats) {
        this.beats = Arrays.asList(beats);
    }

    Result play(Option other) {
        if beats.contains(other) {
            return Result.WIN;
        } else if other.beats.contains(this) {
            return Result.LOSE;
        } else {
            return Result.DRAW;
        }
    }

}

Adding more cases (Lizard and Spock) is consequently relatively simple. Adding more players would be more complicated; among other things, you'd have to determine what the rules of three-player Rock-Paper-Scissors even are, because I have no idea.

like image 32
Taymon Avatar answered Nov 15 '22 11:11

Taymon