Reputation: 3229
I am doing a tic tac toe from The Odin Project. I have two classes: Board
(which contains the board, which contains all the individual "X" and "O"), and Game
, which starts the game, keeps track of which round, check wins/etc. I am not doing any A.I. stuff.
I have my basic framework set up:
class Board
attr_accessor :board
def initialize
@board = Array.new(3, Array.new(3, 'X'))
end
def display_board
@board.each.with_index do |row, i|
row.each.with_index do |column, j|
print "|#{i}#{j}|"
end
puts
end
end
end
class Game
def initialize(player1, player2, board)
@board = board
@player1 = player1
@player2 = player2
end
def check_board
if @board.board[0][0] && @board.board[1][1] && @board.board[2][2]
puts "Winner!"
end
end
end
board = Board.new
game = Game.new('X', 'O', board)
game.check_board
The Board
and Game
need to talk to each other. Passing the Board
class object into another classes' initialize
feels odd or wrong. But I don't know if there is a better way to have classes talking to each other or one class having another class stored in it's variable.
Is this the right way to go about this? What is the best way to keep classes separate but also talk to each other? Should I initialize both objects outside and let them talk to each other that way? Or initialize one in the other class, and let that class do all the heavy lifting?
Upvotes: 0
Views: 54
Reputation: 46379
The question of where to initialize objects is one experienced developers will argue about endlessly.
Something to consider is lifecycle and "ownership". In this case, the board object may be considered to have a "strong child relationship" with the game, because it lives and dies with the game. From an external perspective, it's not even clear there needs to be a "board" at all - it could be entirely encapsulated by the game ... but the board is being used simply to "de-compose" the game into parts (other parts might include pieces on the board, or the score, for example).
For that reason, there's a good arugment for creating the board inside the game constructor. The constructor could still contain a "board spec" object or board parameters if you wanted to give some flexibility (e.g. board_size), but the game itself can be completely responsible for creating and destroying the board.
Others would still argue it's better to pass the board object in (as in your example) for the sake of simplicity and flexibility. See? There's never one answer. Your best bet as a student is experimenting with different models and learn about their strengths and weaknesses in practice. And familiairize yourself with YAGNI because thinking in practical terms is often the best way out of these academic debates.
Upvotes: 2