DRYing up Rock Paper Scissors

前端 未结 4 982
爱一瞬间的悲伤
爱一瞬间的悲伤 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:39

    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
    

提交回复
热议问题