DRYing up Rock Paper Scissors

前端 未结 4 950
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-25 04:18

I\'m a novice ruby programmer and although this code works, I\'m wondering how I can improve it. I have very limited knowledge on lambdas and procs and the like, but any advice

相关标签:
4条回答
  • 2021-01-25 04:37

    You can build a hash that contains the pick and which option lose against that pick:

    hash = {'scissors' => 'paper', 'rock' => 'scissors', 'paper' => 'rock'}
    

    Then you check if the machine pick is the same like you did:

    roll_ops = ["rock", "paper", "scissors"]
    pick = roll_ops.sample
    if roll == pick
    

    And the win/lose condition becomes something like this:

    if hash[roll] == pick
      "win"
    else
      "lose"
    end
    

    Nice and clean with just 2 conditions.

    0 讨论(0)
  • I think a proc or other similar setup is probably overkill. Just use inline-ifs:

    def rps(roll)
      raise "Choose rock, paper, or scissors" if roll.nil?
      roll_ops = ["rock", "paper", "scissors"]
      pick = roll_ops.sample
      result = if roll == pick
        "tie"
      else
        case roll
        when "scissors"
          pick == "paper" ? 'win' : 'lose'
        when "rock"
          pick == "scissors" ? 'win' : 'lose'
        when "paper" then
          pick == "rock" ? 'win' : 'lose'
        end
      end
      puts "#{pick}, #{result}"
    end
    
    rps("scissors")
    

    I removed your extra else that was supposed to handle non-input. Better to use errors in such a case.

    There are a couple tricks here:

    1- The inline-ifs. Those should be pretty clear.

    2- The result variable is set equal to the return value of the if expression. This is a handy trick that you can use because in Ruby, everything is an expression!

    If you are interested in using a lambda for this, it should work pretty well too:

    def rps(roll)
      raise "Choose rock, paper, or scissors" if roll.nil?
      roll_ops = ["rock", "paper", "scissors"]
      pick = roll_ops.sample
      did_win = lambda do |choice|
        return choice == pick ? 'win' : 'lose'
      end
      result = if roll == pick
        "tie"
      else
        case roll
        when "scissors"
          did_win.call('paper')
        when "rock"
          did_win.call('scissors')
        when "paper" then
          did_win.call('rock')
        end
      end
      puts "#{pick}, #{result}"
    end
    
    0 讨论(0)
  • 2021-01-25 04:52
    ROLL_OPS = %w[rock paper scissors]
    RESULTS = %w[tie lose win]
    def rps(roll)
      unless i = ROLL_OPS.index(roll)
        return puts "Please input rock paper or scissors".freeze
      end
      pick = ROLL_OPS.sample
      puts "#{pick}, #{RESULTS[(i - ROLL_OPS.index(pick)) % 3]}"
    end
    
    0 讨论(0)
  • 2021-01-25 04:53

    Here are a couple of ways:

    #1 Use Array#cycle

    OPS = %w[rock paper scissors]
    
    def rps(roll)
      pick = OPS.sample
      enum = OPS.cycle
      (prev = enum.next) until enum.peek == roll
      return [pick, "lose"] if prev == pick
      enum.next
      return [pick, "win"] if enum.peek == pick
      [pick, "tie"]
    end
    
    rps "scissors" #=> ["scissors", "tie"] 
    rps "scissors" #=> ["scissors", "tie"] 
    rps "scissors" #=> ["rock", "win"] 
    rps "scissors" #=> ["paper", "lose"] 
    

    #2 Take @MurifoX's answer one step farther

    def rps(roll)
      roll_ops = %w|rock paper scissors|
      h = (roll_ops + [roll_ops.first]).each_cons(2).
        with_object(Hash.new("tie")) { |(a,b),h| h[[a,b]]="lose"; h[[b,a]]="win" }
      pick = roll_ops.sample
      [pick, h[[roll,pick]]]
    end
    
    rps "scissors" #=> ["rock", "lose"] 
    rps "scissors" #=> ["scissors", "tie"] 
    rps "scissors" #=> ["paper", "win"] 
    

    Here:

    h #=> {["rock", "paper"]=>"lose", ["paper", "rock"]=>"win",
      #    ["paper", "scissors"]=>"lose", ["scissors", "paper"]=>"win",
      #    ["scissors", "rock"]=>"lose", ["rock", "scissors"]=>"win"} 
    

    and because of the default value "tie":

    h[["rock", "rock"]]         #=> "tie"
    h[["paper", "paper"]]       #=> "tie"
    h[["scissors", "scissors"]] #=> "tie"
    
    0 讨论(0)
提交回复
热议问题