RSpec noob需要帮助。我的大脑现在已经糊涂了......我正试图在我的代码中为这个方法创建一个基本的“我存在并且我返回一个值”...
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)>'
那是......但是
如果您想查看整个类别文件,请参阅播放器.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
答案 0 :(得分:0)
如果您知道如何正确阅读,错误会非常清楚地告诉您错误:
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)>'
这告诉你几件事:
@player_computer.attempt_win(@board).should_not be(nil)
。each
。nil
。./lib/player.rb:171
方法的attempt_win
或attempt_win
调用的某个内部库方法中。 (您可以使用--backtrace
标志运行您的规范以获得完整的回溯。默认情况下,RSpec会尝试将其过滤为仅相关的行以减少噪音。)查看您的代码时,错误表明@ai_winmoves
尚未初始化,并且在调用nil
时值为attempt_win
。