Hangman - HumanPlayer pick_secret_word not accepting my input

My HumanPlayer class doesn’t accept my input when initializing @secret_word. In Terminal, instead of accepting my input, it just skips line when I hit enter like this:

class Hangman
  attr_reader :guesser, :referee, :board

  def initialize(players)
    @guesser = players[:guesser]
    @referee = players[:referee]
  end

  def setup
    secret_word_length = @referee.pick_secret_word
    @guesser.register_secret_length(secret_word_length)
    @board = Array.new(secret_word_length - 1)
  end

  def take_turn
    letter_guess = @guesser.guess(board)
    letter_guess_indices = @referee.check_guess(letter_guess)
    update_board(letter_guess, letter_guess_indices)
    @guesser.handle_response(letter_guess, letter_guess_indices)
  end

  def update_board(letter_guess, letter_guess_indices)
    letter_guess_indices.each do |idx|
      @board[idx] = letter_guess
    end
    @board
  end

  def play
    setup

    until board.none? { |ele| ele == nil }
      take_turn
    end

    puts "GUESSER WON"
    p @board
  end
end









class HumanPlayer

  def pick_secret_word
    puts "PICK YOUR SECRET WORD!"
    @secret_word = gets.chomp.to_s
    @secret_word.length
  end

  def check_guess(letter)
    letter_indices = []

    @secret_word.chars.each_with_index do |char, idx|
      letter_indices << idx if char == letter
    end

    letter_indices
  end

  def register_secret_length(length)
    puts "THE WORD IS #{length} LETTERS LONG"
  end

  def guess(board)
    p board
    puts "GUESS A LETTER!"
    guess_letter = gets.chomp.to_s
  end

  def handle_response(letter_guess, letter_guess_indices)
    if letter_guess_indices.empty?
      puts "YOUR LETTER WAS NOT FOUND ON THE BOARD"
    else
      puts "#{letter_guess} WAS FOUND AT #{(letter_guess_indices.each {|num| num + 1}).to_s}"
    end
  end

  def candidate_words
    @candidate_words
  end
end











class ComputerPlayer
  def initialize(dictionary = File.readlines('lib/dictionary.txt'))
    @dictionary = dictionary
  end

  def pick_secret_word
    @secret_word = @dictionary.sample
    @secret_word.length
  end

  def check_guess(letter)
    letter_indices = []

    @secret_word.chars.each_with_index do |char, idx|
      letter_indices << idx if char == letter
    end

    letter_indices
  end

  def register_secret_length(length)
    right_length_words = @dictionary.select { |word| word.length == length }
    @candidate_words = right_length_words
  end

  def guess(board)
    letter_count = Hash.new(0)

    if board.all? { |el| el == nil }
      @dictionary.join("").split("").each {|letter| letter_count[letter] += 1}
      sorted_letter_count = letter_count.sort_by { |letter, count| count }
      return sorted_letter_count.last[0]
    else
      @candidate_words.join("").split("").each {|letter| letter_count[letter] += 1 unless board.include?(letter)}
      sorted_letter_count = letter_count.sort_by { |letter, count| count }
      return sorted_letter_count.last[0]
    end
  end

  def handle_response(letter_guess, letter_guess_indices)
    right_index_letter_words = []

    @candidate_words.each do |word|
      right_place = true

      right_place = false if letter_guess_indices.empty? && word.include?(letter_guess)
      letter_guess_indices.each do |idx|
        right_place = false if word[idx] != letter_guess
      end
      word.chars.each_with_index do |letter, idx|
        right_place = false if (letter == letter_guess) && !(letter_guess_indices.include?(idx))
      end
      right_index_letter_words << word if right_place == true
    end

    @candidate_words = right_index_letter_words
  end

  def candidate_words
    @candidate_words
  end

  def [](pos)
    row, col = pos
    @grid[row][col]
  end
end

Hi Josh,

If your code is passing all the specs, then it might have to do with some specifics of take_turn? I also noticed that you called .play twice and I wonder if that’s causing pry to do something funky. Keep at it!

1 Like

Hi Josh,

I did some debugging for you and the code hangs at ComputerPlayer#register_secret_length(length). You might want to look into that method and see everything is going as expected.

Michael

1 Like

Hi Josh,

I think I found your error. Your dictionary is not parsed correctly. You will need to run :chomp on all the lines after you read lines to get rid of the newlines. You can run map(&:chomp) after your readlines method to accomplish this.

Michael

2 Likes

Ah I got it. Thank you Michael! I do have one question though,

When I just do readlines, are the words in the dictionary forming an array of words that are not strings? (like [apple, banana]) and chomp is turning them into strings? ([“apple”, “banana”])

Hi JChoi,

When you do readlines, you get an array like this [“apple/n”, “banana/n”]. Chomp then removes the newline or /n so you get [“apple”, “banana”].

1 Like

ohhh that makes a lot of sense now. Thank you again!