我是一名新手ruby程序员,虽然这段代码有效,但我想知道如何改进它。我对lambda和procs等知识非常有限,但任何建议都会很棒。在每种情况下,有没有办法简化if else
语句?另外,是否有任何替代方法可以跳过case
语句而不是将几乎整个代码作为一个大的if else语句?
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")
答案 0 :(得分:4)
您可以构建一个包含选择的哈希,以及针对该选择丢失的选项:
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个条件,很干净。
答案 1 :(得分: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
答案 2 :(得分:2)
以下是两种方法:
#1使用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将@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"
答案 3 :(得分:1)
我认为proc或其他类似的设置可能有点过分。只需使用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")
我删除了你应该处理非输入的额外的其他内容。在这种情况下最好使用错误。
这里有一些技巧:
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