Scalable solution for Rock-Paper-Scissor

后端 未结 7 1516
悲&欢浪女
悲&欢浪女 2020-12-05 01:28

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

相关标签:
7条回答
  • 2020-12-05 01:47

    The shortest way:

    var n = 5; // Rock, Paper, Scissors, Lizard-Spock
    
    function calculate(x, y, n) {
      return 1 - ((n + x - y) % n) % 2;
    }
    
    function getWinner(p1Gestrure, p2Guesture) {
      if(p1Gestrure === p2Guesture) {
         return - 1; // tie
      }
    
      return this.calculate(p1Gestrure, p2Guesture); // 0: win for p1. 1: win for p2.
    }
    

    I've created a cli game, please feel free to take a look there. https://github.com/julianusti/rpc-es6

    0 讨论(0)
  • 2020-12-05 01:58

    i think: 1 beats 2 or 5 loses to the rest. 2 beats 3 or 1 loses to the rest. 3 beats 4 or 2 loses to rest. 4 beats 5 or 3 loses to the rest. 5 beast 1 or 3 loses to the rest. For 3 players, compare the values of 2 players, then compare the winner vs player 3.

    0 讨论(0)
  • 2020-12-05 01:59

    I suggested a better design in an answer to another post. Have a single switch, and switch over a single encoding of every possible combination of moves, and for an encoding use a positional number system with a base that's a power of 2, so that each digit will map directly to a number of bits, and so that bitwise manipulations are intuitive.

    Three bits are sufficient for five choices, and although octal would be ideal, the syntax sucks, so use hex. Each hexadecimal digit then represents one of your five moves, with room to spare. A byte is large enough two encode the simultaneous moves of two players, an int for eight, a long for sixteen. It's straightforward. Follow the link for a code example.

    0 讨论(0)
  • 2020-12-05 02:08

    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.

    0 讨论(0)
  • 2020-12-05 02:09

    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

    0 讨论(0)
  • 2020-12-05 02:09

    This is a basic logic problem. It is small enough you can do a manual truth table ( or skip ahead to a k-map), minimize and get a solution.

    So basically, you need to evaluate first, if it is a draw. Then, you need to evaluate winning relative to other players. Doing this without needing to compare against each user can be a confusing task. Since this only has 5 variables, you can find a minimized solution with a K-map.

    You will need to evaluate each user, based on which item they chose with a specific algorithm to determine if they win. Note that with more than 2 players, there can be more than one winner if two people choose the same thing but both beat a 3rd player. Or you can consider that a tie, whatever. I'll assume the former. You should check also that all players didn't choose the same item.

    So I've done the first part of the algorithm for you when the user you are evaluating has chosen "rock".

    In code, this would look like:

    rock=0, paper=0, scissors=0, lizard=0, spock=0, win=0, tie=0
    if ( someone chose rock ) rock=1
    if ( someone chose paper ) paper=1
    if ( someone chose scissors ) scissors=1
    if ( someone chose lizard ) lizard=1
    if ( someone chose spock ) spock=1
    
    // Check if tie / draw, double check these, but I think I got them all
    tie=rock && !paper && spock && lizard || rock && paper && scissors ||  
        rock && paper && lizard || spock && paper && scissors || 
        spock && !rock && paper && lizard || !spock && scissors && lizard && paper
    
    if ( tie ) die()
    
    CheckIfUserWins() {
      if ( user chose rock ) {
        win=rock && !paper && !spock
      if ( user chose paper) {
        // ....  calculate using k-map and fill in
    
    }
    
    return win
    

    Notice that win=rock && !paper && !spock is exactly what would be expected based on the graphic of what beats what at the link you provided. So you can go to that graphic and pretty quickly fill in the rest of the equations.

    This solution is not dependent on any number of players other than to say "someone chose X". So it should scale to > 5 players, etc.

    0 讨论(0)
提交回复
热议问题