class Hangman
attr_reader :guesser, :referee, :board
def initialize(options = {})
@guesser = options[:guesser]
@referee = options[:referee] #class objects
end
def play
setup
take_turn until over?
conclude
end
def setup
secret_length = @referee.pick_secret_word
@guesser.register_secret_length(secret_length)
@board = Array.new(secret_length)
end
def take_turn
letter = @guesser.guess(@board)
correct_indicies = @referee.check_guess(letter)
self.update_board(letter,correct_indicies)
@guesser.handle_response(letter,correct_indicies)
end
def update_board(letter,correct_indicies)
correct_indicies.each{|index| @board[index] = letter}
end
private
def over?
@board.count(nil) == 0
end
def conclude
puts "Congrats the game is over."
puts "The hidden word was #{board.join}"
end
end
class HumanPlayer
def initialize
@guessed_letters = []
end
def pick_secret_word
puts "Enter the length of your word."
gets.chomp.to_i
end
def register_secret_length(length)
puts "The length of the word is #{length}"
end
def guess(board)
print_board(board)
print "> "
guess = gets.chomp
processed_guess(guess)
end
def check_guess(letter)
puts "The letter, #{letter}, guessed was at these indicies."
puts "Input formart ex. (2 4 6)"
indicies = gets.chomp.split(" ").map(&:to_i)
end
def handle_response(letter, indicies)
puts "Found #{letter} at positions #{indicies}"
end
private
def print_board(board)
board_string = board.map do |el|
el.nil? ? "_" : el
end.join("")
puts "Secret word: #{board_string}"
end
def processed_guess(guess)
unless @guessed_letters.include?(guess) || guess.length > 1
@guessed_letters << guess
return guess
else
puts "You have already guessed #{guess}"
puts "Please try again."
puts "You have guessed #{@guessed_letters}"
print "> "
guess = gets.chomp
processed_guess(guess)
end
end
end
class ComputerPlayer
attr_reader :secret_word, :secret_word_length, :candidate_words,
:guessed_letters
def initialize(dictionary = ComputerPlayer.default_dictionary)
@dictionary = dictionary
@alphabet = ("a".."z").to_a
@guessed_letters = []
end
def self.default_dictionary
contents = File.readlines("dictionary.txt").map{|word| word.chomp}
end
def pick_secret_word
@secret_word = @dictionary.sample
print @secret_word
secret_word_length = @secret_word.length
end
def check_guess(letter)
secret_word_arr = @secret_word.chars
secret_word_arr.each_index.select{|index| @secret_word[index] == letter}
end
def register_secret_length(secret_length)
@candidate_words = @dictionary.select{|word| word.length == secret_length}
end
def guess(board)
print_board(board)
letter = guess_most_common
processed_most_common(letter)
puts "HERE #{@guessed_letters}"
letter
end
def handle_response(letter, indicies)
@candidate_words.select! do |word|
indicies == word.chars.each_index.select {|index| word[index] == letter} #so the problem here is if you guess "r" give correct index of [0] and it checks "rear" it would assume its correct even tho theres an extra "r"
end
puts "Found #{letter} at positions #{indicies}"
end
def guess_most_common
puts "HERE2 #{@guessed_letters}"
most_common_hash = Hash.new(0)
uniq_candidate_arr = @candidate_words.map{|word| word.chars.uniq.join}
uniq_candidate_arr.join.each_char{|char| most_common_hash[char] += 1 unless @guessed_letters.include?(char)
p char}
print "#{most_common_hash}"
most_common_letter = most_common_hash.sort_by{|key,value| value}.reverse.to_h.keys.first
end
private
def print_board(board)
board_string = board.map do |el|
el.nil? ? "_" : el
end.join("")
puts "Secret word: #{board_string}"
end
def processed_most_common(letter)
@guessed_letters << letter unless @guessed_letters.include?(letter)
end
end
if __FILE__ == $PROGRAM_NAME
my_computer = ComputerPlayer.new
my_human = HumanPlayer.new
game = Hangman.new({guesser:my_human, referee:my_computer})
game.play
end
很抱歉,如果这是一个糟糕的格式,但我正在处理一个Hangman项目,但卡住了。我试图让ComputerPlayer猜出最常见的字母。在猜到最常见的字母之后,它会猜到下一个最常见的字母,然后是第四个字母。
我已经制作了一个@guessed_letters = []来跟踪我已经猜到过的字母,所以下次计算机猜到一封信时我就算不上了。
问题是@guessed_letter没有正确跟踪我的猜测字母。我把它们印在两个区域。一个在ComputerPlayer#guess中,一个在ComputerPlayer#guess_most_common中。 guess方法使用已经猜到的字母正确打印@guessed_letters数组。 guess_most_common方法总是打印一个空的@guessed_letters数组。怎么可能他们都打印不同的东西?
答案 0 :(得分:1)
所以你的问题是,在下面的RSpec测试案例中,“HERE2”是一个空数组,不包含猜测“e”,但是:
describe "Phase III" do
describe "#guess" do
let(:guesser) { ComputerPlayer.new(["reel","keel","meet"]) }
before(:each) { guesser.register_secret_length(4) }
context "when a guess has been made" do
it "returns the most common letter in the remaining #candidate_words" do
board = [nil, "e", "e", nil]
expect(guesser.guess(board)).to eq("l")
end
end
end
原因是你没有告诉任何代码,你已经猜到了“e”,但是(你没有用“e”调用processed_most_common
)。你只告诉guesser
董事会处于一个状态,即2个中间字母是“e”。
例如,如果我们将测试更改为:
context "when a guess has been made" do
it "returns the most common letter in the remaining #candidate_words" do
board = [nil, "e", "e", nil]
guesser.guess(board) # guesses 'e' and marks it as guessed.
expect(guesser.guess(board)).to eq("l")
end
end
现在,我们让董事会处于一个状态,让它知道“e”位于中间2个位置,然后我们告诉它猜测最常见的字母,这仍然是“e”因为{{ 1}}不知道它猜对了(因为它没有)。在那之后,我们告诉它猜测下一个字母,这次是“l”,并且“HERE2”代码正确地输出“e”已经猜到了(因为它已经有了)。
还有其他方法可以解决此问题,您只需要确保使用“e”调用guesser
,以解决您所看到的问题。但是如果你让代码完成了整个猜测过程,那么你最终就不会错过任何可能预期的步骤。