Перезапустите программу Ruby внутри

Я пишу очень простую приключенческую игру в подземелье на Ruby (практика для новичка). Я хочу обращаться к игроку по имени повсюду, поэтому, естественно, я хочу быть уверенным, что если игрок передаст пустое имя моему методу инициализации игрока, if сообщит им, что они не могут этого сделать, а затем предложит повторить попытку.

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', поэтому я перезагружаю здесь весь файл каждый раз, когда игрок решает не вводить свое имя. Что глупо...

Это работает, но в худшем случае... Мне пришлось «умничать» в том, где я вышел из программы, чтобы игрок был изолирован от того факта, что я в основном использую Inception для всех и запускаю игру в game каждый раз, когда игрок начинает новую игру и не вводит свое имя. Например, если они не замечают 3 раза, что им нужно ввести свое имя, потому что они не обращают внимания, у меня фактически запущено 4 игры (оригинал и 3, вызванные не вводом их имени), и они d либо нужно заканчивать каждую из этих игр, когда они устанут играть, либо мне пришлось резко выйти из всего этого по одному ключевому слову.

У меня такой вопрос: есть ли способ написать мою ошибку "Вы не вошли..." выйти из текущей игровой сессии и перезапустить игру? Все, что я действительно хочу сделать, это гарантировать, что пустая строка не будет передана моему методу инициализации, возможно, путем возбуждения исключения, а затем начать с начала сценария без игры внутри игры.

Вот ссылка на полный код для получения дополнительной информации: http://repl.it/8QY


person DanielNordby    schedule 17.01.2015    source источник
comment
Попытка перезагрузить game.rb звучит как совершенно неправильный способ сделать это - почему бы просто не вызвать gets (или что-то еще, что вы используете для чтения ввода) несколько раз, пока не будет предоставлен правильный ввод.   -  person Frederick Cheung    schedule 17.01.2015
comment
@FrederickCheung А, в этом гораздо больше смысла. Дух. Не могли бы вы предложить простой цикл вокруг вызова gets, чтобы позаботиться об этом?   -  person DanielNordby    schedule 17.01.2015


Ответы (3)


Трудно понять, не видя всей структуры игры, но ваш основной файл может выглядеть так:

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

Это должно вас завести.

person Vincent Fourmond    schedule 17.01.2015
comment
Хотя это сработает, я не думаю, что отсутствие имени следует рассматривать как исключительный сценарий. Я думаю, было бы так же легко продолжать спрашивать, пока вы не получите действительное имя. - person Justin Wood; 17.01.2015
comment
Спасибо! Мне очень нравится то, что ты здесь сделал. Это то, что я пытался сделать все время, но я не мог полностью осознать это. Чтобы было ясно, по сути, весь мой код (при условии, что я отвратительный человек и помещаю весь свой код в один файл) будет находиться между «начать» и «спасать», верно? Затем я мог бы добавить любое количество спасательных операций, которые мне могут понадобиться, включая мое спасение NoNameError... - person DanielNordby; 17.01.2015
comment
@SkeletorDan Насколько я понимаю, вам не нужно иметь всю игру в блоке начала / спасения, только инициализацию. Я буду обновлять ответ, чтобы отразить это. - person Vincent Fourmond; 18.01.2015
comment
@JustinWood Что заставляет вас думать, что это исключительный сценарий? Использование исключений — это просто очень удобный способ управления потоком в этом случае. Вот для чего нужны исключения. - person Vincent Fourmond; 18.01.2015
comment
Исключения @VincentFourmond не следует использовать в качестве потока управления. Существуют различные конструкции потока управления, которые можно использовать в этом сценарии. Исключения предназначены для обработки исключительных обстоятельств. Это достойное объяснение того, когда следует использовать исключения. - person Justin Wood; 18.01.2015

Я думаю, что ответ Винсента хорош, он, безусловно, больше 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
person Anthony    schedule 17.01.2015
comment
Спасибо @Энтони! Я согласен, у Винсента есть хорошее понимание, которое я реализую, когда у меня будет время, но я использовал вашу реализацию в сочетании с комментарием Фредерика вверху, чтобы заставить ее работать так, как я ожидал. Кое-что о том, чтобы слишком долго смотреть на свой собственный код... в любом случае, действительно ли break делает цикл while ложным, эффективно заканчивая его? - person DanielNordby; 17.01.2015
comment
На самом деле он не устанавливает его в false, но завершает блок while. Подробнее см. здесь - person Anthony; 17.01.2015

Если вы хотите, чтобы ваша логика была в Player, вы можете попробовать что-то вроде этого:

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
person daremkd    schedule 17.01.2015
comment
Имеет смысл. Вероятно, мне не следует запускать логику в методе инициализации, а лучше создать метод для ее обработки. Хорошая точка зрения! Гораздо чище, чем моя попытка. - person DanielNordby; 19.01.2015