I'm trying to make a simple Tic Tac Toe game and I can't connect the classes properly
class Player
def current_player
player = 'X'
player = 'O' if Turn.turn_count.odd?
player
end
end
class Board
attr_accessor :board
def initialize
@board = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
end
WIN_COMBINATIONS = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[6, 4, 2],
[0, 4, 8]
].freeze
def display_board
puts " #{@board[0]} | #{@board[1]} | #{@board[2]} "
puts ' ----------- '
puts " #{@board[3]} | #{@board[4]} | #{@board[5]} "
puts ' ----------- '
puts " #{@board[6]} | #{@board[7]} | #{@board[8]} "
end
end
class Winner
def initialize
@board = Board.new
end
def won?
Board.WIN_COMBINATIONS.detect do |combo|
@board[combo[0]] == @board[combo[1]] &&
@board[combo[1]] == @board[combo[2]] &&
position_taken?(combo[0])
end
end
def full?
Turn.turn_count == 9
end
def draw?
!won? && full?
end
def over?
won? || full? || draw?
end
def winner
@board[winner.first] if winner == won?
end
end
class TicTacToe
def initialize
@board = Board.new
@turn = Turn.new
end
def play
until @winner.over?
Winner.turn()
if Winner.won?
winner = Winner.winner()
puts "Congratulations #{winner}!"
elsif Winner.draw?
puts 'Tic Tac Toe Game!'
end
end
end
end
class Turn
def input_to_index(input)
input.to_i - 1
end
def move(position, token = 'X')
@board[position] = token
end
def position_taken?(input)
@board[input] == 'X' || @board[input] == 'O'
end
def valid_move?(input)
input.between?(0, 8) && !position_taken?(input)
end
def turn
puts 'Choose a spot between 1-9'
spot = gets.strip
spot = input_to_index(spot)
if valid_move?(spot)
move(spot, current_player)
else
turn
end
display_board
end
def turn_count
taken = 0
@board.each do |i|
taken += 1 if i.include?('X') || i.include?('O')
end
taken
end
end
game = TicTacToe.new
game.play```
This was more like a comment, but you have so many problems in your code that I preferred to put it here as an answer, even if it's not the answer you might expect.
Starting because the code cannot be executed, as soon as it is called
play
it throws you aundefined method 'over?'
because@winner
it is not defined.You call instance methods
def turn_count
as if they were class methods as inDefines
attr_accessor :board
, to never use it in the classBoard
, since you call@board
.In the class
Turn
you call@board
, but it's not even defined inside the class. If you want to interconnect the instances, you must pass them as a parameter at some point, either in the constructor (preferably) or when a method is called, but an instance of the classTurn
has no way of knowing about the existence of the board attributes, if you don't explicitly let them know in some way.I suggest you give an OOP manual or tutorial another look, because even though at first glance it looks like the entities or objects are well defined, they clearly don't connect as they should. And yes, that is what you are asking, but starting out there is no way to see that without even knowing the approach of the exercise. Coming up with code that was made with a thought in mind and asking how this OOP code can be done can eventually be a task where you just completely throw out what you've done, because everyone may have their own way of looking at the problem and how to solve it.
I would suggest that you create a new question with a specific problem that you are having in your code, the current one is not specific and is open to the interpretation of each one.
Cheers