在内部重新启动 Ruby 程序

Restart Ruby program internally

我正在Ruby写一个非常简单的地下城冒险游戏(新手练习)。我想在整个过程中都用名字来称呼玩家,所以我自然要确保如果玩家将空名称传递给我的 Player initialize 方法,如果告诉他们他们不能这样做,然后提示他们重试。

class Player
    attr_accessor :name, :location

    def initialize(name)
        if name.empty? == false
            @name = name
        else
            puts "You did not enter your name! Try again, please"
            load 'game.rb'
        end
    end
end

文件名是 'game.rb' 所以每次玩家决定不输入他们的名字时,我基本上都会在这里重新加载整个文件。这是愚蠢的...

它有效,但以最糟糕的方式......我必须 'clever' 了解我退出程序的位置,这样玩家就不会受到我基本上所有 Inception 的事实的影响每次玩家开始新游戏而忘记输入他们的名字时,每个人都会在游戏中启动游戏。例如,如果他们 3 次没有注意到他们需要输入他们的名字,因为他们没有注意,我实际上有 4 个游戏 运行(原始的,以及 3 个没有输入他们的名字的提示) 并且他们要么需要在玩腻了游戏时就结束这些游戏,要么我基本上只能在一个关键字上硬着头皮退出整个游戏。

我的问题是:有没有办法写出我的错误 "You did not enter..." 退出当前游戏会话,然后重新启动游戏?我真正想做的就是确保空字符串不会传递给我的初始化方法,可能是通过引发异常,然后在脚本开头重新开始,而不是游戏中的游戏。

这里是完整代码的 link 以获得更多见解:http://repl.it/8QY

如果不看整个游戏结构很难知道,但你的主文件可能看起来像

game_initialized = false
while ! game_initialized
  begin
    # here, initialize the game, including initialization
    game_initialized = true
  rescue NoNameError
    # do nothing, but it will restart the game
  end
end
# now play the game

然后在构造函数中添加

class NoNameError < Exception
end

class Player
  attr_accessor :name, :location

  def initialize(name)
    if name.empty? == false
      @name = name
    else
      puts "You did not enter your name! Try again, please"
      raise NoNameError
    end
  end
end

这应该让你继续。

我认为 Vincent 的回答很好,它肯定比我的更 OO,但一个简单的方法是在游戏开始时做这样的事情:

print "Welcome!  "
in_name = ""
while true
  puts "What is your name?"
  in_name = gets.chomp
  in_name.empty? ? (puts "You must enter a name before continuing") : break
end

示例:

Welcome!  What is your name?

You must enter a name before continuing
What is your name?
Anthony

如果你想让你的逻辑在播放器中,你可以尝试这样的事情:

class Player
  attr_accessor :name, :location

  def initialize(name)
    @name = keep_asking_for_name_if_not_already_entered(name)
  end

  def keep_asking_for_name_if_not_already_entered(name)
    return name unless name.empty?
    loop do
      puts 'You did not enter your name! Enter a name, please:'
      name = gets.chomp
      break(name) unless name.empty?
    end
  end
end