I have 2 classes: Game and Player. This is a Tic-tac-toe game.
class Game
attr_accessor :player_1, :player_2, :numbers, :board
def initialize(player_1, player_2)
@player_1 = player_1
@player_2 = player_2
@numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
end
end
class Player
attr_reader :name
attr_accessor :selection
def initialize(name)
@name = name
@selection = []
end
def play(game)
print "#{name}, please pick a number: "
number = gets.chomp.to_i
print "#{name} selected #{number}"
puts
selection << number
index = game.numbers.find_index(number)
if (name == 'player_1')
game.numbers[index] = 'X'
else
game.numbers[index] = 'O'
end
end
end
Codes to initialise Player
and Game
:
p1 = Player.new('player_1')
p2 = Player.new('player_2')
game = Game.new(p1, p2)
I setup the Player in the way that whenever a player pick a number (example: with p1.play(game)
), the number will be stored in selection
of Player
and numbers
in Game
will be updated with "x" / "o".
Once the steps above completed, I update :player_1
and :player_2
in Game
with:
game.player_1 = p1
& game.player_2 = p2
Print out the game.player_1.selection
and the result is expected. However, I skipped the game.player_1 = p1
& game.player_2 = p2
once by mistake and print game.player_1.selection
again. To my surprise, the result for both ways is the same regardless I execute game.player_1 = p1
& game.player_2 = p2
.
So I would like to get clarification, as a newbie to OOP world; what is the correct way to update player_1
/ player_2
for my case? Thanks.
Variables are used to refer to objects. You set the object by assigning it to the variable via =
, e.g.:
a = "hello"
You can now refer to "hello"
via a
, e.g.
a << " world"
a #=> "hello world"
Because of this usage, you might think that you modified a
. But this isn't quite correct. You actually modified the object, a
is referring to, i.e. the string "hello"
which then became "hello world"
.
This distinction is important when you assign an object to more than one variable, e.g.:
a = "hello"
b = a
a << " world"
a #=> "hello world"
b #=> "hello world"
b = a
will make b
refer to the same object, a
is referring to. I think of it as:
variable object
a ───────┐
"hello"
b ───────┘
When calling a << " world"
the object gets modified, i.e.:
variable object
a ───────┐
"hello world"
b ───────┘
Inspecting a
and b
afterwards merely shows that modification.
what is the correct way to update
player_1
/player_2
for my case?
You don't have to. In your code, p1
and game.player_1
already refer to the same object, an instance of Player
. Therefore, updating that player instance is all you have to do.
Setting game.player_1 = p1
is actually superfluous because game.player_1
already referred to p1
. You were merely re-assigning the very same object.