我从根本上不明白这里发生了什么。 play 下面是我的状态机。但它不起作用。它要么返回两个选择的反面,一遍又一遍(开始),或'未知命令'。我已经通过在各个点打印变量@next_action的值来测试它,结果是不一致的。有时case语句的结果是 instruct ,但它会打印 display 。有时反之亦然,有时候是未知的命令。是的,我调整代码来产生这些不同的结果。但并不多。从来没有像预期的那样表现。
显然,我不明白我所写的逻辑。我想要做的就是将case语句的结果作为方法调用传递并保持所有循环。我是一个红宝石的新手和那些试图帮助的人,或者以一种我似乎不理解的方式描述事物,或者我在解释/显示我的确切方面做得很差我试图做。
非常感谢任何帮助。
class Foo
def initialize(start_action)
@start = start_action
@users = %w(Adam Sarah Kanye)
@points = %w(100 200 300)
end
def play
puts @next_action
while true
case @next_action
when beginning
beginning
when "instruct"
instructions
when "display"
display_users
else
puts "Unknown command."
play
end
puts "\n----------"
end
end
def prompt
puts "\n----------"
print "> "
end
def beginning
puts <<-INTROTEXT
This is intro text.
INTROTEXT
prompt; @next_action = gets.chomp.to_s
end
def instructions
puts <<-INSTRUCT
These are instructions.
INSTRUCT
prompt; @next_action = gets.chomp.to_s
end
def display_users
puts "\nYour users now include:"
puts "\nName\tPoints"
puts "----\t------"
@users.each_with_index do |item, index|
puts "%s\t%s" % [item, @points[index]]
end
prompt; @next_action = gets.chomp
end
end
start = Foo.new(:beginning)
start.play
答案 0 :(得分:1)
你会好的,只是DRY事情。此外,您有两个独立的循环结构,这会导致不良行为。您的:play
方法包含一个无限循环,它自己将:play
作为最后一步。你真的只需要一个或另一个。我已经调整了一些内容来集中:prompt
功能并使用一个没有递归的循环(即:play
不再调用自身)来实现我认为你期望的行为:
class Foo
def initialize
@next_action = "beginning"
@users = %w(Adam Sarah Kanye)
@points = [100, 200, 300]
end
def play
while true
act
prompt
end
end
def prompt
puts "\n----------"
print "> "
@next_action = gets.chomp.to_s
end
def act
case @next_action
when "beginning"
beginning
when "instruct"
instructions
when "display"
display_users
else
puts "I don't know how to '#{@next_action}'."
end
end
def beginning
puts <<-INTROTEXT
This is intro text.
INTROTEXT
end
def instructions
puts <<-INSTRUCT
These are instructions.
INSTRUCT
end
def display_users
puts "\nYour users now include:"
puts "\nName\tPoints"
puts "----\t------"
@users.each_with_index do |item, index|
puts "%s\t%s" % [item, @points[index].to_s]
end
end
end
Foo.new.play
答案 1 :(得分:0)
案例陈述中的开头应该是:开头即一个符号,否则你正在评估针对某个方法的下一个行动。另外,当你在一个永远不会导致开始的case语句中进行递归时,这可能意味着你最终会进行无限递归。 (道歉,如果开头只是一个错字)
您也在混合符号和字符串(通常应该避免)。在说明中,您将@next_action创建为字符串,但通过Foo.new创建符号。 :开始!=“开始”也。我建议下一个动作永远是一个符号,因为符号(据我所知)用于表示当作为参数传递给函数时,应根据符号采取动作。虽然它基于用户输入,但将它保留为字符串也是有意义的。
也不应该将函数调用play放在case语句之外,然后删除while true。这意味着在创建@next_action之后,程序继续。基本上我不认为这会永远停止,而真正意味着永远持续,你必须提供break
来阻止它。我想你会希望它继续下去,除非有一个未知的动作。或者至少重置对未知动作的动作,即:
class Foo
def initialize(start_action)
@start = start_action
@users = %w(Adam Sarah Kanye)
@points = %w(100 200 300)
end
如果有人输入错误的指示但是继续
,这个会停止 def play
puts @next_action
case @next_action
when :beginning
beginning
when :instruct
instructions
when :display
display_users
else
puts "Unknown command."
raise Foo::UnknownCommand
end
puts "\n----------"
play
end
OR这将永远持续,并在用户输入错误的命令时启动用户。
def play
puts @next_action
while true
case @next_action
when :beginning
beginning
when :instruct
instructions
when :display
display_users
else
puts "Unknown command."
@next_action = :beginning
end
puts "\n----------"
end
end
和其他
def prompt
puts "\n----------"
print "> "
end
def beginning
puts <<-INTROTEXT
This is intro text.
INTROTEXT
prompt; @next_action = gets.chomp.to_sym
end
def instructions
puts <<-INSTRUCT
These are instructions.
INSTRUCT
prompt; @next_action = gets.chomp.to_sym
end
def display_users
puts "\nYour users now include:"
puts "\nName\tPoints"
puts "----\t------"
@users.each_with_index do |item, index|
puts "%s\t%s" % [item, @points[index]]
end
prompt; @next_action = gets.chomp.to_sym
end
end
start = Foo.new(:beginning)
start.play
我希望有所帮助。