1

我正在尝试在 Ruby 中进行数字猜谜游戏,但是当我想再次玩游戏时,我输入 yes 后程序退出。我尝试使用 catch and throw 但它不起作用。我能得到一些帮助吗?

这是我的代码。

class Game
    def Play
        catch (:start) do
            $a=rand(11)
            puts ($a)
            until $g==$a
                puts "Guess the number between 0-10."
                $g=gets.to_i
                if $g>$a
                    puts "The number you guessed is too high."
                elsif $g==$a
                    puts "Correct you won!!!"
                    puts "Would you like to play again?"
                    $s=gets()
                    if $s=="yes"
                        $c=true
                    end
                    if $c==true
                        throw (:start) 
                    end
                elsif $g<$a
                    puts "The number you guessed is too low."
                end
            end
        end
    end
end
Game.new.Play

编辑:这是我尝试建议后的新代码:

class Game
  def Play
    catch (:start) do
      $a=rand(11)
      puts ($a)
      while $s=="yes"
        until $g==$a
          puts "Guess the number between 0-10."
          $g=gets.chomp.to_i
          if $g>$a
            puts "The number you guessed is too high."
          elsif $g==$a
            puts "Correct you won!!!"
            puts "Would you like to play again?"
            $s=gets.chomp
            if $s=="yes"
              throw (:start)
            end
          elsif $g<$a
            puts "The number you guessed is too low."
          end
        end
      end
    end
  end
end
Game.new.Play
4

4 回答 4

3

你的第一个问题在这里:

$s=gets()
if $s=="yes"
    $c=true
end

gets方法将读取包括换行符'\n'的下一行,并将其与“是”进行比较:

> gets
=> "yes\n" 

在 Ruby 中解决此问题的惯用方法是以下chomp方法:

> gets.chomp
=> "yes"

也就是说,您的代码还有另外两个缺陷。

  1. 您可能来自 PHP、Perl 等语言,甚至只是 Bash 脚本,但 Ruby 不需要在变量之前使用美元符号。使用 $ 提供了一个变量全局范围,这可能不是您想要的。事实上,您几乎从不希望变量具有全局范围。

    Ruby 使用三种类型的符号前缀来表示作用域——例如@,@@ 表示类,$ 表示全局。然而,最常见的变量类型只是本地变量,不需要任何前缀,以及我对您的代码的建议。

  2. 我一直被告知将异常用于控制结构是非常糟糕的做法。使用 while/break 结构可以更好地为您的代码提供服务。

于 2013-11-12T04:36:29.057 回答
1

当您这样做时gets(),它会检索最后带有 '\n' 的整行。您需要使用以下方法修剪换行符:

$g=gets.chomp.to_i

其他也一样gets

于 2013-11-12T04:28:33.333 回答
0

我知道这并不能真正回答你关于为什么你的代码不起作用的问题,但是在看到你发布的代码之后,我只需要重构它。干得好:

class Game
  def initialize
    @answer = rand(11)
  end

  def play
    loop do
      guess = get_guess
      display_feedback guess
      break if guess == @answer
    end
  end

  def self.play_loop
    loop do
      Game.new.play
      break unless play_again?
    end
  end

  private

  def get_guess
    puts "Guess the number between 0-10."
    return gets.chomp.to_i
  end

  def display_feedback(guess)
    if guess > @answer
      puts "The number you guessed is too high."
    elsif guess < @answer
      puts "The number you guessed is too low."
    elsif guess == @answer
      puts "Correct you won!!!"
    end
  end

  def self.play_again?
    puts "Would you like to play again?"
    return gets.chomp == "yes"
  end
end

Game.play_loop
于 2013-11-12T18:03:09.280 回答
0

根据您更新的代码(您修复了其他人显示的换行问题),您的新问题是您已将所有游戏包装在while $s=="true". 您的代码第一次运行时,$snil(从未设置过),因此您永远无法玩。如果您使用局部变量而不是全局变量(s而不是$s),这将变得更加明显,因为代码甚至不会运行。

这是我重新编写游戏的一种工作方式。

class Game
  def play
    keep_playing = true
    while keep_playing
      answer = rand(11)     # Make a new answer each time
      puts answer if $DEBUG # we don't normally let the user cheat
      loop do               # keep going until I break from the loop
        puts "Guess the number between 0-10."
        guess = gets.to_i   # no need for chomp here
        if guess>answer
          puts "The number you guessed is too high."
        elsif guess<answer
          puts "The number you guessed is too low."
        else
          puts "Correct you won!!!",
               "Would you like to play again?"
          keep_playing = gets.chomp.downcase=="yes"
          break
        end
      end
    end
  end
end
Game.new.play
于 2013-11-12T14:28:48.857 回答