Ruby的Hangman项目,如果用户先输入了一个不同的字母,则字母“m”将被注册为已经输入

3duebb1j  于 2023-04-05  发布在  Ruby
关注(0)|答案(1)|浏览(106)
class Game
  def initialize
    @word = key_generator
    @guesses = 10
    @guess = ''
    @word_clues = ''
    @winner = false
    @word.length.times { |_l| @word_clues << '_' }
    @lettersleft = 0
  end

  def guess_checker(get_guess)
    return unless get_guess == 'exit'

    puts "\nBye Bye :)\n".red
    exit(true)
  end

  def enter_guess
    p @word

    puts "Enter a single letter guess\n"
    get_guess = gets.chomp.downcase
    raise "You've already guessed that letter!" if @guess.include? get_guess
    unless /[[:alpha:]]/.match(get_guess) && get_guess.length == 1 || get_guess == 'exit'
      raise "Invalid input: #{get_guess}. Try again!"
    end

    guess_checker(get_guess)
    guessed_letters(get_guess)
    display_guesses(get_guess)
    lettercount(get_guess)
  rescue StandardError => e
    puts e.to_s.red
  end

  def guessed_letters(char)
    if @word.include?(char)
      @guess << char.cyan
      puts "\nNice one! #{@guesses.to_s.cyan} guesses left."
    else
      @guess << char.red
      @guesses -= 1
      puts "\nNot so lucky, sorry! #{@guesses.to_s.cyan} guesses left.\n"
    end
  end

  def key_generator
    word_list = File.open('words_no_swears.txt')
    words = []

    word_list.each_line do |l|
      l = l.chomp
      words << l if l.length <= 12 && l.length >= 5
    end

    word_list.close
    words.sample
  end

  def winner_check
    return unless @word == @word_clues

    @winner = true
  end

  def game_play
    if @guesses >= 2 && @winner == false
      enter_guess
      puts
      puts "   Guesses: #{@guess}"
      puts
    elsif @guesses == 1 && @winner == false
      puts "\nLast guess!\n".cyan
      enter_guess
      display_guesses(@guess)
    else
      win_anouncement = "\nYou got it!\n"
      puts win_anouncement.cyan
      exit
    end
  end

  def go_time
    until @guesses == 0
      winner_check
      game_play
      puts @lettersleft
    end
    return unless @guesses == 0 && @winner == false

    puts "\n  Tough luck,\n  The word was #{@word.cyan}\n  Play again? [y/n]"
    entry = gets.chomp
    return unless entry == 'y'

    restart
    go_time
  end

  def restart
    @word = key_generator
    @guesses = 10
    @guess = ''
    @word_clues = ''
    @winner = false
    @word.length.times { |_l| @word_clues << '_' }
  end

  def display_guesses(char)
    @word.split('').each_with_index do |v, i|
      @word_clues[i] = char if v == char
    end
    puts
    puts '  ' + @word_clues.magenta
  end

  def lettercount(char)
    @word.split('').each do |v|
      @lettersleft += 1 if char == v
    end
    puts "letters to go: #{(@word.length - @lettersleft).to_s.cyan}"
  end
end

这里是几乎整个代码.我不知道哪些具体部分将是相关的,因为我不知道在哪里提出的问题.这是一个相对粗糙的草案,我知道.非常感谢你的帮助.
我已经尝试使用各种放置和扫描代码的问题.我没有发现任何.我已经尝试运行程序在replit和bash与相同的结果.该程序要求用户输入一个字母,检查该字母还没有猜到已经.然而,当用户的第一猜测不是字母“m”时,对重复字母的检查似乎认为字母“m”被猜测。

mum43rcc

mum43rcc1#

一般注意事项

首先,你的代码中有很多问题,这里不适合进行代码检查。如果你不能对你的方法进行单元测试,而且你还没有stepped through your code with a debugger,那么很难提供一个不是其他许多完美有效的解决方案之一的解决方案。
也就是说,您有许多问题需要解决:
1.永远不要为预期的行为引发异常。异常是为了 * 异常 *,而不是为了流控制。所以,请停止这样做。
1.你在获取单个字符时做了很多工作。使用如下代码:

require "io/console"
char = $stdin.getch

它使你的意图更清晰,代码更易读。
1.在不花费大量时间调试代码的情况下,我建议您添加以下内容:

@unguessed_letters = ("a".."z").to_a

添加到类示例变量中,然后在检查猜测的字符是否存在后将其从数组中删除。这看起来比您当前所做的要简单得多,也更不容易出错。
这可能会改善你的代码,但不一定会修复错误。你的代码只是很难阅读和调试当前编写的代码,简化不工作的代码是找到根本原因的好方法。

基于字符的输入循环示例

第二,你的代码可以从一个简单的循环中受益,这个循环可以根据之前猜测的字符和用户试图完成的单词来测试字符。正如敏捷宣言所说,优化“未完成的工作”的数量。作为一个例子,考虑以下代码,它假设您已经编写了#completed?和#reveal_letter方法。请注意,在这个例子中,您可以在 * 之后 * 删除猜测的字母。

require "io/console"

@guesses_remaining = 10
@unguessed_letters = ("a".."z").to_a

# This is an example, and depends on some methods
# you haven't written yet, like a Boolean result
# from #completed? and action for #reveal_letter.
#
# @todo You also need to handle CTRL-C and CTRL-D
#   if you want to exit to loop before you run out
#   of guesses. See Signal#trap and Signal#list,
#   but you'll have to handle CTRL-D explicitly if
#   you decide to allow EOF as way for the user to
#   exit the loop.
# @return [String, nil] @word if entire word was
#   revealed; otherwise nil when the loop runs
#   out of remaining guesses
while @guesses_remaining.nonzero?
  @guess = $stdin.getch
  next if @guess.match? /$/

  if @unguessed_letters.include? @guess
    reveal_letter(@guess) if @word.include?(@guess)
  else
    # assumes you only lose a remaining guess
    # if you've guessed wrong; modify if you
    # use different rules
    @guesses_remaining -= 1
  end

  @unguessed_letters.delete @guess
  break @word if completed?(@word)
end

这并不意味着要彻底重写代码,也不是要调试现有的代码。它只是一个务实的替代方案,一次处理一个字符,并使用一个简单的循环来管理猜测和意外按下RETURN而不选择字母。
它应该足以让你朝着一个更好的方向开始,但它既不完整也不完全符合习惯,它只是试图让你的代码更容易推理和调试,剩下的就取决于你了。

相关问题