class Game attr :repository, :id, :board, :player, :winner def initialize(repository:, id:, board:, player:) @id = id @repository = repository @board = board @player = player end def winner RUNS_OF_THREE.each do |tiles| %i(player_1 player_2).each do |player| return player if tiles.all? { |at| fetch_tile(at) == player } end end nil end def finished? winner ? true : false end def make_move!(as:, at:) MakeMoveCommand.new(game: self, player: as, position: at).apply! end def fetch_tile(position) row, col = BOARD_MAP.fetch(position) board.fetch(row).fetch(col) end def apply_move!(position:) row, col = BOARD_MAP.fetch(position) board.fetch(row)[col] = player @player = { player_1: :player_2, player_2: :player_1 }.fetch(player) repository.store self end BOARD_MAP = { top_left: [0, 0], top: [0, 1], top_right: [0, 2], left: [1, 0], center: [1, 1], right: [1, 2], bottom_left: [2, 0], bottom: [2, 1], bottom_right: [2, 2], } RUNS_OF_THREE = [ [:top_left, :center, :bottom_right], [:top_right, :center, :bottom_left], [:top_left, :left, :bottom_left], [:top, :center, :bottom], [:top_right, :right, :bottom_right], [:top_left, :top, :top_right], [:left, :center, :right], [:bottom_left, :bottom, :bottom_right], ] end