烘干岩纸剪刀

我是一个新手ruby程序员,虽然这段代码有效,但我想知道如何改进它。 我对lambdas和procs等知识非常有限,但任何建议都会很棒。 有没有办法在每种情况下简化if else语句? 另外,是否有任何替代方法可以跳过case语句,而不是将几乎整个代码作为else if语句?

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

您可以构建包含选择的散列以及针对该选择丢失的选项:

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

然后检查机器选择是否与您一样:

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

赢/输条件变成这样:

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

只有2个条件,干净整洁。

 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 

以下是几种方法:

#1使用Array#循环

 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将@MurifoX的答案更进一步

 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"] 

这里:

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

并且由于默认值“tie”:

 h[["rock", "rock"]] #=> "tie" h[["paper", "paper"]] #=> "tie" h[["scissors", "scissors"]] #=> "tie" 

我认为proc或其他类似的设置可能有点过分。 只需使用内联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") 

我删除了你应该处理非输入的额外的其他内容。 在这种情况下更好地使用错误。

这里有几个技巧:

1-内联ifs。 那些应该很清楚。

2-结果变量设置为等于if表达式的返回值。 这是一个方便的技巧,你可以使用,因为在Ruby中,一切都是表达!

如果你对使用lambda感兴趣,它应该也能很好地工作:

 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