Ruby 如何简化代码?
我是Ruby的新手,我想出了这个小游戏。感觉太长了,但我不确定。有没有办法简化内部的if语句?我应该使用while还是可以使用其他技术 如果这个问题不好,请原谅我。在发布代码之前,我尽了最大努力修复代码Ruby 如何简化代码?,ruby,Ruby,我是Ruby的新手,我想出了这个小游戏。感觉太长了,但我不确定。有没有办法简化内部的if语句?我应该使用while还是可以使用其他技术 如果这个问题不好,请原谅我。在发布代码之前,我尽了最大努力修复代码 def win(reason) puts "You win!" exit(0) end def boring(reason) puts reason + " Game over!" exit(0) end puts "Your friend wants to fight no
def win(reason)
puts "You win!"
exit(0)
end
def boring(reason)
puts reason + " Game over!"
exit(0)
end
puts "Your friend wants to fight now!"
friend_conscious = true
friend_bleeding = false
friend_angry = false
while friend_conscious
puts "Do you kick, punch or taunt?"
print "> "
response = gets.chomp
if response == ("kick" || "punch") && !friend_angry
puts "You try to hit your friend."
boring("You lost the fight, you suck!")
elsif response == "taunt" && !friend_angry
puts "Your friend is angry!"
friend_angry = true
elsif response == "taunt" && !friend_bleeding
puts "Your friend is too angry, he knocks you out!"
boring("You lost the fight, you suck!")
elsif response == "kick" && !friend_bleeding
puts "Your friend dodges your kick and knocks you out."
boring("You lost the fight, you suck!")
elsif response == "punch" && !friend_bleeding
puts "Your friend is bleeding"
friend_bleeding = true
elsif response == ("taunt" || "punch") && friend_bleeding
puts "Your friend lunges at you, knocking you to the ground."
puts "He then beats you up."
boring("You lost the fight, you suck!")
elsif response == "kick" && friend_bleeding
puts "You kick your friend in the balls, he falls to the ground"
win("You won the fight! What a great holiday.")
else
puts "Your friend knocks you out."
boring("You lost the fight, you suck!")
end
puts "What's your next move?"
end
这更像是一个代码审查问题。 尽管如此,这里还是有一些建议/意见:
win(reason)
从不使用reason
朋友意识
仅用于while
循环,从不更改。可以去掉它,只需在为true时放入
if response==(“kick”| |“punch”)
不是您想要的。如果response==“kick”| response==“punch”,请尝试if response==“kick”| | response==“punch”
,对于多个匹配,最好使用正则表达式:if response=~/^(kick | punch)$/
将匹配锚定到字符串的开头^
将匹配锚定到字符串的末尾$
- 结果是整个字符串必须匹配
if response !~ /^(kick|punch|taunt)$/
puts "Your friend knocks you out."
boring("You lost the fight, you suck!")
else
if !friend_angry
if response =~ /^(kick|punch)$/
puts "You try to hit your friend."
boring("You lost the fight, you suck!")
elsif response == "taunt"
puts "Your friend is angry!"
friend_angry = true
end
elsif !friend_bleeding
if response == "taunt"
puts "Your friend is too angry, he knocks you out!"
boring("You lost the fight, you suck!")
elsif response == "kick"
puts "Your friend dodges your kick and knocks you out."
boring("You lost the fight, you suck!")
elsif response == "punch"
puts "Your friend is bleeding"
friend_bleeding = true
elsif friend_bleeding
if response =~ /^(taunt|punch)$/
puts "Your friend lunges at you, knocking you to the ground."
puts "He then beats you up."
boring("You lost the fight, you suck!")
elsif response == "kick"
puts "You kick your friend in the balls, he falls to the ground"
win("You won the fight! What a great holiday.")
end
end
puts "What's your next move?"
end
然后,您可以更进一步,将每个主要部分拉到其自己的功能,即:
def process_not_friend_angry(response)
if response =~ /^(kick|punch)$/
puts "You try to hit your friend."
boring("You lost the fight, you suck!")
elsif response == "taunt"
puts "Your friend is angry!"
friend_angry = true
end
end
确保您的函数低于
friend_angry
等人的声明这更像是一个代码审查问题。
尽管如此,这里还是有一些建议/意见:
win(reason)
从不使用reason
朋友意识
仅用于while
循环,从不更改。可以去掉它,只需在为true时放入
if response==(“kick”| |“punch”)
不是您想要的。如果response==“kick”| response==“punch”,请尝试if response==“kick”| | response==“punch”
,对于多个匹配,最好使用正则表达式:if response=~/^(kick | punch)$/
将匹配锚定到字符串的开头^
将匹配锚定到字符串的末尾$
- 结果是整个字符串必须匹配
if response !~ /^(kick|punch|taunt)$/
puts "Your friend knocks you out."
boring("You lost the fight, you suck!")
else
if !friend_angry
if response =~ /^(kick|punch)$/
puts "You try to hit your friend."
boring("You lost the fight, you suck!")
elsif response == "taunt"
puts "Your friend is angry!"
friend_angry = true
end
elsif !friend_bleeding
if response == "taunt"
puts "Your friend is too angry, he knocks you out!"
boring("You lost the fight, you suck!")
elsif response == "kick"
puts "Your friend dodges your kick and knocks you out."
boring("You lost the fight, you suck!")
elsif response == "punch"
puts "Your friend is bleeding"
friend_bleeding = true
elsif friend_bleeding
if response =~ /^(taunt|punch)$/
puts "Your friend lunges at you, knocking you to the ground."
puts "He then beats you up."
boring("You lost the fight, you suck!")
elsif response == "kick"
puts "You kick your friend in the balls, he falls to the ground"
win("You won the fight! What a great holiday.")
end
end
puts "What's your next move?"
end
然后,您可以更进一步,将每个主要部分拉到其自己的功能,即:
def process_not_friend_angry(response)
if response =~ /^(kick|punch)$/
puts "You try to hit your friend."
boring("You lost the fight, you suck!")
elsif response == "taunt"
puts "Your friend is angry!"
friend_angry = true
end
end
确保您的函数低于
friend_angry
等人的声明您可以做两件事,这将大大提高可读性和可维护性。首先,使其面向对象。我不是OO狂热者,但我认为这很适合。第二,将大量的逻辑转移到方法中。这将使代码总体上更具可读性,并且更容易为其编写测试
首先,让我们编写一个简单的类来跟踪您朋友的状态:
class Friend
attr_writer :conscious, :bleeding, :angry
def initialize
@conscious = true
@bleeding = false
@angry = false
end
def conscious?; @conscious end
def bleeding?; @bleeding end
def angry?; @angry end
end
您可以这样使用它:
friend = Friend.new
friend.angry? # => false
friend.angry = true
friend.angry? # => true
接下来是一个跟踪游戏状态的类:
class Game
VALID_MOVES = %w[ kick punch taunt ].freeze
attr_reader :friend
def initialize
@friend = Friend.new
end
def play!
while friend.conscious?
puts "Do you kick, punch or taunt?"
print "> "
response = gets.chomp
move!(response)
puts
end
win!
end
private
def move!(kind)
return send(kind) if VALID_MOVES.include?(kind)
bad_move!
end
# ...
end
我已将游戏循环放入游戏#play代码>方法。当玩家输入移动时,游戏移动调用代码>方法<代码>移动
检查这是否是有效的移动,如果是,则使用send
调用同名的方法,例如,如果玩家输入“kick”
,则调用kick
方法(我们尚未定义)。如果这不是一个有效的移动,游戏#坏的#移动调用代码>方法
在我们充实kick
、punch
等方法之前,我们应该将每个结果放在自己的方法中。您有五个失败条件,我们称之为lose_1
,lose_2
,等等,还有一个获胜条件,win_1
。还有两个条件设置了friend.angry
和friend.blooding
,因此我们也将为这些设置方法。这是一个开始:
def friend_bleeding
puts "Your friend is bleeding"
friend.bleeding = true
end
def friend_angry
puts "Your friend is angry!"
friend.angry = true
end
def win_1
puts "You kick your friend in the balls, he falls to the ground."
friend.conscious = false
end
def lose_1
puts "Your friend dodges your kick and knocks you out."
lose!
end
def lose_2
puts "You try to hit your friend."
lose!
end
# ...
如您所见,friend\u流血
,friend\u生气
,以及win\u 1
更新friend对象的状态。lose.*
方法调用lose代码>方法
现在我们有了这些方法,让我们看看你的游戏逻辑。我花时间将不同的举措和友邦及其结果列成一张表格:
生气吗?流血?结果
----- ------ --------- ---------------
踢出真正的胜利1
踢真假输1
踢错-输2
打孔真的真的输3
打真假朋友!
打孔错误-丢失2
嘲弄真正的失去3
嘲弄真假输4
嘲笑虚伪的朋友
当我们以这种方式对其进行排序时,就可以清楚地知道如何编写我们的kick
、punch
等方法:
def kick
if friend.angry?
return win_1 if friend.bleeding?
lose_1
else
lose_2
end
end
def punch
if friend.angry?
return lose_3 if friend.bleeding?
friend_bleeding
else
lose_2
end
end
def taunt
if friend.angry?
return lose_3 if friend.bleeding?
lose_4
else
friend_angry
end
end
它们的优点是很容易阅读。您可能会注意到,除了调用的结果方法的名称之外,它们都是相同的,如果您查看表,这是有意义的:按“move”分组,第二列和第三列是相同的
我们可以将这些方法组合成一个非常简洁的方法,但可读性会受到很大影响。我们还可以将每一个都转换为一个带有三元运算符的线性,得到相同的结果。我认为这是简洁性和可读性之间的一个很好的折衷
我们还需要一个坏动作
method,但我要将其作为lose_5
方法的别名:
alias :bad_move! :lose_5
最后,我们需要win代码>和丢失代码>结束游戏的方法:
def win!
puts "You won the fight! What a great holiday.",
exit(0)
end
def lose!
puts "You lost the fight, you suck! Game over!"
exit(0)
end
让我们把它们放在一起:
class Friend
attr_writer :conscious, :bleeding, :angry
def initialize
@conscious = true
@bleeding = false
@angry = false
end
def conscious?; @conscious end
def bleeding?; @bleeding end
def angry?; @angry end
end
class Game
VALID_MOVES = %w[ kick punch taunt ].freeze
attr_reader :friend
def initialize
@friend = Friend.new
end
def play!
while friend.conscious?
puts "Do you kick, punch or taunt?"
print "> "
response = gets.chomp
move!(response)
puts
end
win!
end
private
def move!(kind)
return send(kind) if VALID_MOVES.include?(kind)
bad_move!
end
# Moves
def kick
if friend.angry?
return win_1 if friend.bleeding?
lose_1
else
lose_2
end
end
def punch
if friend.angry?
return lose_3 if friend.bleeding?
friend_bleeding
else
lose_2
end
end
def taunt
if friend.angry?
return lose_3 if friend.bleeding?
lose_4
else
friend_angry
end
end
def bad_move!
lose_5
end
# Outcomes
def friend_bleeding
puts "Your friend is bleeding"
friend.bleeding = true
end
def friend_angry
puts "Your friend is angry!"
friend.angry = true
end
def win_1
puts "You kick your friend in the balls, he falls to the ground."
friend.conscious = false
end
def lose_1
puts "Your friend dodges your kick and knocks you out."
lose!
end
def lose_2
puts "You try to hit your friend."
lose!
end
def lose_3
puts "Your friend lunges at you, knocking you to the ground."
puts "He then beats you up."
lose!
end
def lose_4
puts "Your friend is too angry, he knocks you out!"
lose!
end
def lose_5
puts "Your friend knocks you out."
lose!
end
def win!
puts "You won the fight! What a great holiday.",
exit(0)
end
def lose!
puts "You lost the fight, you suck! Game over!"
exit(0)
end
end
Game.new.play!
您可以做两件事,这将对可读性和可维护性产生重大影响。首先,使其面向对象。我不是OO狂热者,但我认为这很适合。其次,移动大量日志