Tic Tac Toe game spec error

Could anybody help me with this error in the Tic tac toe exercise.

Failures:

  1. Game switch_players! updates the value of current_player
    Failure/Error: expect(game.current_player).to be(player_two)

    expected #RSpec::70104697677760:Mocks::Double => #<RSpec::Mocks::Double:0x3fc2859a27c0 @name=“player”>
    got #RSpec::70104697679980:Mocks::Double => #<RSpec::Mocks::Double:0x3fc2859a306c @name=“player”>

    Compared using equal?, which compares object identity,
    but expected and actual are not the same object. Use
    expect(actual).to eq(expected) if you don’t care about
    object identity in this example.

    Diff:
    @@ -1,2 +1,2 @@
    -#<RSpec::Mocks::Double:0x3fc2859a27c0 @name=“player”>
    +#<RSpec::Mocks::Double:0x3fc2859a306c @name=“player”>

    ./spec/game_spec.rb:59:in `block (3 levels) in <top (required)>’

Finished in 0.02095 seconds (files took 0.12929 seconds to load)
28 examples, 1 failure

This is the error that is coming up from game spec.

Post your code for switch_players!

class Game
attr_accessor :board, :current_player, :player_one, :player_two
def initialize(player_one,player_two)
@board=Board.new
@player_one=player_one
@player_two=player_two
player_one.mark=:X
player_two.mark=:O
@current_player=player_one
end

def play_turn

move_one=current_player.get_move
self.board.place_mark(move_one,current_player.mark)
switch_players!
current_player.display(board)
end

def switch_players!

if current_player==player_one
current_player=player_two
else
current_player=player_one
end
end
end

Be sure to use the ‘@’ prefix for a Class’s instance variables!

Since you’re using attr_accessor, you don’t need to use @ before your instance variables, but when you’re setting the value of current_player you need to include self.. If you don’t, Ruby thinks you are creating a new local variable rather than reassigning an instance variable. To reassign current_player you have to do either
self.current_player =
or
@current_player =

It’s probably less confusing just to use @ before all your instance variables like Luke said.

Thank you so much @ThaBullfrog and @Luke_Dreyer
Got it.

Hi Jeremiah,

I ran into the same error/concern originally posted by Natasha on this thread.

Given that I have used attr_accessor with current_player, is it really just behaving equivalent to attr_reader ? Based on your explanation above, any attempt to write to current_player (w/o the @ or self prefix) creates a new local variable and doesn’t modify/write the instance variable.

No, attr_accessor acts like a combination of attr_reader and attr_writer.
attr_accessor :current_player writes the following code for you:

def current_player
  @current_player
end

def current_player=(value)
  @current_player = value
end

It’s just, in order to call current_player=, you need to include self.. This is because you have to remove ambiguity between creating a new local variable, current_player, and calling the method, current_player=. They have the same syntax unless you include self.

Here’s how you call it:

self.current_player = @player_one

So attr_accessor does create the writer method. This allows you to access the variable from outside the class like this:

game = Game.new
game.current_player = some_player

And it also gives you a writer method inside the class, but you have to call it with self.

1 Like