1

我基本上不明白这里发生了什么。下面我的状态机。但它不起作用。它要么返回两个选择的相反值,一遍又一遍(开始)相同的选择,要么返回“未知命令”。我已经通过在各个点打印变量@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
4

2 回答 2

1

你会没事的,只是把事情弄干一点。此外,您有两个单独的循环结构,这会导致不良行为。您的: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
于 2013-06-06T16:19:24.070 回答
0

case 语句的开头应该是 :beginning 即一个符号,否则您正在评估针对方法的下一步操作。此外,当您递归一个永远不会导致开始的 case 语句时,这可能意味着您最终会陷入无限递归。(抱歉,如果开头只是一个错字)

您还混合了符号和字符串(通常应该避免)。在说明中,您将 @next_action 创建为一个字符串,但通过 Foo.new 是一个符号。:beginning != "开始" 也是。我建议下一个动作始终是一个符号,因为符号(据我所知)用于指示在作为参数传递给函数时应基于符号采取的动作。尽管它基于用户输入,但将其保留为字符串也很有意义。

函数调用 play 也不应该在 case 语句之外,然后删除 while true。这意味着在创建@next_action 之后程序会继续。基本上我认为这永远不会停止,而真正的手段永远持续下去,你必须提供 abreak来阻止它。我想你会希望它继续下去,除非有一个未知的动作。或者至少重置未知动作的动作,即:

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

或者如果用户输入了错误的命令,这将永远持续并从一开始就启动用户。

  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

我希望这会有所帮助。

于 2013-06-06T16:31:24.723 回答