2
RSpec noob需要幫助。我的大腦是玉米粥現在...我試圖創建一個基本的「我的存在,我返回一個值」在我的代碼,此方法設置測試...rspec給出未定義的方法
def attempt_win(board)
@ai_winmoves.each do |k, v| # go through each win move in the ai_winmoves array located above.
ai_keys = v.select{ |k, v| v == "O"}.keys # grab all computer player's Os from the value hash
intersection = ai_keys & @keys_with_o # get common elements between two arrays..note: keys_with_o = all current O's on game board
if intersection.length >=2 # when two intersections exist it means two O's are on the board
@answers_array << k # add to answers array per iteration
@answers_array.each do |key|
# answer = @anskey[@thing.last].to_sym
puts "which moves can ai win with?"
puts @anskey[key]
answer = @anskey[key].to_sym
puts "attempt win"
puts answer
if board.grid[answer] == " " #if win move space is empty take it
@move = answer
else #check for a block move
# attempt_block # handled at line 162
end
end
end
end # END @ai_winmoves.each do |k,v|
末
這裏是我的測試代碼...
describe 'attempt_win' do
before (:each) do
@board.grid[:b2] == "X"
end
xit 'computer looks for any possible win move'
it 'computer returns a value' do
@player_computer.attempt_win(@board).should_not be(nil)
end
end
這裏是RSpec的失敗我得到...
1) Player class attempt_win computer returns a value
Failure/Error: @player_computer.attempt_win(@board).should_not be(nil)
NoMethodError:
undefined method `each' for nil:NilClass
# ./lib/player.rb:171:in `attempt_win'
# ./spec/player_spec.rb:47:in `block (3 levels) in <top (required)>'
THAT'S IT .....但
如果你想看到完整的類文件player.rb,它的測試文件player_spec.rb看看下面...
# TODO - send error output if move already taken
# TODO - better WIN detection
class Player
attr_reader :boardpiece # i exist so game.rb can read me
def initialize(letter)
@boardpiece = letter
end
def move_human(game, board)
@game_two = game
puts "human move..."
human_move = gets.chomp
human_symbol = human_move.to_sym
# look for move as key in board.grid
if board.grid.has_key?(human_symbol)
if board.grid[human_symbol] == " "
#puts "bingo"
@move = human_symbol
else
puts "spot taken...try again"
move_human(@game_two, board)
end
else
puts "invalid move...try again"
move_human(@game_two, board)
end
end
def move_computer(game, board)
# ai should do three things
# attempt win
# block human
# random move
puts "computer move..."
# all possible third moves as 'O' (computer)
@human_winmoves = {
:wm01 => {:a1=>"X", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>"X", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm02 => {:a1=>" ", :a2=>"X", :a3=>" ", :b1=>" ", :b2=>"X", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm03 => {:a1=>" ", :a2=>" ", :a3=>"X", :b1=>" ", :b2=>"X", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm04 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>"X", :b2=>"X", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm05 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>"X", :b3=>"X", :c1=>" ", :c2=>" ", :c3=>" "},
:wm06 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>"X", :b3=>" ", :c1=>"X", :c2=>" ", :c3=>" "},
:wm07 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>"X", :b3=>" ", :c1=>" ", :c2=>"X", :c3=>" "},
:wm08 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>"X", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>"X"},
#check those corners
:wm09 => {:a1=>"X", :a2=>"X", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm10 => {:a1=>"X", :a2=>" ", :a3=>" ", :b1=>"X", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm11 => {:a1=>" ", :a2=>"X", :a3=>"X", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm12 => {:a1=>" ", :a2=>" ", :a3=>"X", :b1=>" ", :b2=>" ", :b3=>"X", :c1=>" ", :c2=>" ", :c3=>" "},
:wm13 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>"X", :c1=>" ", :c2=>" ", :c3=>"X"},
:wm14 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>"X", :c3=>"X"},
:wm15 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>"X", :c2=>"X", :c3=>" "},
:wm16 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>"X", :b2=>" ", :b3=>" ", :c1=>"X", :c2=>" ", :c3=>" "},
#check opposites
:wm17 => {:a1=>"X", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>"X", :c2=>" ", :c3=>" "},
:wm18 => {:a1=>" ", :a2=>"X", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>"X", :c3=>" "},
:wm19 => {:a1=>" ", :a2=>" ", :a3=>"X", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>"X"},
:wm20 => {:a1=>"X", :a2=>" ", :a3=>"X", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm21 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>"X", :b2=>" ", :b3=>"X", :c1=>" ", :c2=>" ", :c3=>" "},
:wm22 => {:a1=>"X", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>"X"},
:wm23 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>"X", :c2=>" ", :c3=>"X"},
:wm24 => {:a1=>" ", :a2=>" ", :a3=>"X", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>"X", :c2=>" ", :c3=>" "},
#check crazy
:wm25 => {:a1=>" ", :a2=>"X", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>"X", :c2=>" ", :c3=>" "},
:wm26 => {:a1=>" ", :a2=>"X", :a3=>" ", :b1=>"X", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm27 => {:a1=>" ", :a2=>"X", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>"X"},
:wm28 => {:a1=>" ", :a2=>"X", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>"X", :c1=>" ", :c2=>" ", :c3=>" "},
:wm29 => {:a1=>"X", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>"X", :c3=>" "},
:wm30 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>"X", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>"X", :c3=>" "},
:wm31 => {:a1=>" ", :a2=>" ", :a3=>"X", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>"X", :c3=>" "},
:wm32 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>"X", :c1=>" ", :c2=>"X", :c3=>" "},
:wm33 => {:a1=>" ", :a2=>"X", :a3=>" ", :b1=>"X", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm34 => {:a1=>" ", :a2=>" ", :a3=>"X", :b1=>"X", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm35 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>"X", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>"X", :c3=>" "},
:wm36 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>"X", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>"X"},
:wm37 => {:a1=>"X", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>"X", :c1=>" ", :c2=>" ", :c3=>" "},
:wm38 => {:a1=>" ", :a2=>"X", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>"X", :c1=>" ", :c2=>" ", :c3=>" "},
:wm39 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>"X", :c1=>"X", :c2=>" ", :c3=>" "},
:wm40 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>"X", :c1=>" ", :c2=>"X", :c3=>" "}
}
@ai_winmoves = {
:wm01 => {:a1=>"O", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>"O", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm02 => {:a1=>" ", :a2=>"O", :a3=>" ", :b1=>" ", :b2=>"O", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm03 => {:a1=>" ", :a2=>" ", :a3=>"O", :b1=>" ", :b2=>"O", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm04 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>"O", :b2=>"O", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm05 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>"O", :b3=>"O", :c1=>" ", :c2=>" ", :c3=>" "},
:wm06 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>"O", :b3=>" ", :c1=>"O", :c2=>" ", :c3=>" "},
:wm07 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>"O", :b3=>" ", :c1=>" ", :c2=>"O", :c3=>" "},
:wm08 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>"O", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>"O"},
#check those corners
:wm09 => {:a1=>"O", :a2=>"O", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm10 => {:a1=>"O", :a2=>" ", :a3=>" ", :b1=>"O", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm11 => {:a1=>" ", :a2=>"O", :a3=>"O", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm12 => {:a1=>" ", :a2=>" ", :a3=>"O", :b1=>" ", :b2=>" ", :b3=>"O", :c1=>" ", :c2=>" ", :c3=>" "},
:wm13 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>"O", :c1=>" ", :c2=>" ", :c3=>"O"},
:wm14 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>"O", :c3=>"O"},
:wm15 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>"O", :c2=>"O", :c3=>" "},
:wm16 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>"O", :b2=>" ", :b3=>" ", :c1=>"O", :c2=>" ", :c3=>" "},
#check opposites
:wm17 => {:a1=>"O", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>"O", :c2=>" ", :c3=>" "},
:wm18 => {:a1=>" ", :a2=>"O", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>"O", :c3=>" "},
:wm19 => {:a1=>" ", :a2=>" ", :a3=>"O", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>"O"},
:wm20 => {:a1=>"O", :a2=>" ", :a3=>"O", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm21 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>"O", :b2=>" ", :b3=>"O", :c1=>" ", :c2=>" ", :c3=>" "},
:wm22 => {:a1=>"O", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>"O"},
:wm23 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>"O", :c2=>" ", :c3=>"O"},
:wm24 => {:a1=>" ", :a2=>" ", :a3=>"O", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>"O", :c2=>" ", :c3=>" "},
#check crazy
:wm25 => {:a1=>" ", :a2=>"O", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>"O", :c2=>" ", :c3=>" "},
:wm26 => {:a1=>" ", :a2=>"O", :a3=>" ", :b1=>"O", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm27 => {:a1=>" ", :a2=>"O", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>"O"},
:wm28 => {:a1=>" ", :a2=>"O", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>"O", :c1=>" ", :c2=>" ", :c3=>" "},
:wm29 => {:a1=>"O", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>"O", :c3=>" "},
:wm30 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>"O", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>"O", :c3=>" "},
:wm31 => {:a1=>" ", :a2=>" ", :a3=>"O", :b1=>" ", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>"O", :c3=>" "},
:wm32 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>"O", :c1=>" ", :c2=>"O", :c3=>" "},
:wm33 => {:a1=>" ", :a2=>"O", :a3=>" ", :b1=>"O", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm34 => {:a1=>" ", :a2=>" ", :a3=>"O", :b1=>"O", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>" "},
:wm35 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>"O", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>"O", :c3=>" "},
:wm36 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>"O", :b2=>" ", :b3=>" ", :c1=>" ", :c2=>" ", :c3=>"O"},
:wm37 => {:a1=>"O", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>"O", :c1=>" ", :c2=>" ", :c3=>" "},
:wm38 => {:a1=>" ", :a2=>"O", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>"O", :c1=>" ", :c2=>" ", :c3=>" "},
:wm39 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>"O", :c1=>"O", :c2=>" ", :c3=>" "},
:wm40 => {:a1=>" ", :a2=>" ", :a3=>" ", :b1=>" ", :b2=>" ", :b3=>"O", :c1=>" ", :c2=>"O", :c3=>" "}
}
# match current answers located in @thegrid with possible @anskey array, iterate for each item
@anskey={
:wm01=>"c3",:wm02=>"c2",:wm03=>"c1",:wm04=>"b3",:wm05=>"b1",:wm06=>"a3",:wm07=>"a2",:wm08=>"a1",
:wm09=>"a3",:wm10=>"c1",:wm11=>"a1",:wm12=>"c3",:wm13=>"c3",:wm14=>"c1",:wm15=>"c3",:wm16=>"a1",
:wm17=>"b1",:wm18=>"b2",:wm19=>"b3",:wm20=>"a2",:wm21=>"b2",:wm22=>"b2",:wm23=>"c2",:wm24=>"b2",
:wm25=>"a1",:wm26=>"a1",:wm27=>"a3",:wm28=>"a3",:wm29=>"c1",:wm30=>"c1",:wm31=>"c3",:wm32=>"c3",
:wm33=>"a1",:wm34=>"a1",:wm35=>"c1",:wm36=>"c1",:wm37=>"a3",:wm38=>"a3",:wm39=>"c3",:wm40=>"c3"
}
#
# scan board for available move locations
@keys_with_o = board.grid.select{ |k, v| v == "O" }.keys # find Os on the board
@keys_with_x = board.grid.select{ |k, v| v == "X" }.keys # find Xs on the board
@answers_array = [] # initialize answers array
if board.grid[:b2] == " " #AND center spot is empty
ai_spot = "b2"
# puts "ai takes center "+ai_spot
@move = ai_spot.to_sym #must return this answer as a symbol
else
# TODO - Ai attempts win
i = 0
until i == 4
attempt_win(board) #run 3x then run attempt_block
i = i+1 # add 1 to i
if i == 4
puts "running attempt_block..."
attempt_block(board)
end
end
end
return @move # had this guy in the wrong place
end
def attempt_win(board)
@ai_winmoves.each do |k, v| # go through each win move in the ai_winmoves array above.
ai_keys = v.select{ |k, v| v == "O"}.keys # grab all computer player's Os from the value hash
intersection = ai_keys & @keys_with_o # get common elements between two arrays..note: keys_with_o = all current O's on game board
if intersection.length >=2 # when two intersections exist it means two O's are on the board
@answers_array << k # add to answers array per iteration
@answers_array.each do |key|
# answer = @anskey[@thing.last].to_sym
puts "which moves can ai win with?"
puts @anskey[key]
answer = @anskey[key].to_sym
puts "attempt win"
puts answer
if board.grid[answer] == " " #if win move space is empty take it
@move = answer
else #check for a block move
# attempt_block # handled at line 162
end
end
end
end # END @ai_winmoves.each do |k,v|
end
def attempt_block(board)
puts "attempt block method - hi"
# thing = [] # initialize thing array
@human_winmoves.each do |k,v| # for test - go threw each win moves.
# get common elements between two arrays..recall from above that v contains a hash
human_keys = v.select{ |k, v| v == "X"}.keys
# which moves can I take to block human
intersection = human_keys & @keys_with_x
if intersection.length >= 2
puts "intersection"
puts intersection
@answers_array << k # adds a key per iteration
puts "@answers_array << k"
puts @anskey[k]
@answers_array.each do |key|
puts "which moves can ai block with?"
puts @anskey[key]
answer = @anskey[key].to_sym
puts "attempt block"
puts answer
# if board.spot_taken?(answer)
if board.grid[answer] != " " # spot taken
puts "space taken can not block 2: " + answer.to_s
else
puts answer.to_s+" blocked"
@move = answer # for test - at last intersection value found...return it as move value
return @move
end
end
end
end # END @human_winmoves.each do |k,v|
end
end
如果你想看到整個player_spec.rb文件...
require 'game'
require 'board'
describe 'Player class' do
before (:each) do
#Dry it up
@player_human = Player.new('X')
@player_computer = Player.new('O')
@board = Board.new
@game = Game.new(@player_human, @player_computer, @board)
end
describe 'move_human' do
before (:each) do
# first set up my expectations
@player_human.should_receive(:puts).with("human move...")
@player_human.stub(:gets).and_return("a1")
end
it 'receives cli input and prints text to screen' do
# now trigger them
@player_human.move_human("X", @board)
end
it 'returns a move value' do
# now trigger them
@player_human.move_human("X", @board).should eq(:a1) #return the value is what I mocked?
end
end
describe 'move_computer' do
it 'should print - ...computer move... - to screen' do
# first set up my expectations
@player_computer.should_receive(:puts).with("computer move...")
# now trigger them
@player_computer.move_computer("O", @board)
end
it 'returns expected first move b2' do
@player_computer.move_computer("O", @board).should eq(:b2)
end
end
describe 'attempt_win' do
before (:each) do
@board.grid[:b2] == "X"
end
xit 'computer looks for any possible win move'
it 'computer returns a value' do
@player_computer.attempt_win(@board).should_not be(nil)
end
end
describe 'attempt_block'do
xit 'looks for a block move'
end
end
我會建議在調試中運行它。如果你在閱讀之前還沒有這樣做。它將極大地幫助你解決這個和未來的問題。 –
是這樣嗎? ... http://pivotallabs.com/users/chad/blog/articles/366-ruby-debug-in-30-seconds-we-don-t-need-no-stinkin-gui- – thefonso
你知道,給我們有這麼多的代碼來閱讀......你需要首先縮小它的範圍。你可以通過逐漸簡化程序,刪除那些不會導致錯誤的部分,並隔離儘可能短的代碼片段和測試代碼來完成相同的錯誤。在這一點上,(1)你會自己理解錯誤出現的原因,或者(2)你仍然不理解錯誤,並且你在問這個錯誤。現在我不能滿足你的問題。 –