class TicTacToe::ComputerPlayer

Attributes

player_mark[R]

Public Class Methods

new(parameters) click to toggle source
# File lib/computer_player.rb, line 7
def initialize(parameters)
  @player_mark = parameters[:player_mark]
  @opponent_mark = parameters[:opponent_mark]
end

Public Instance Methods

move(game) click to toggle source
# File lib/computer_player.rb, line 12
def move(game)
  @board = game.board
  if @board.all_blank? && @board.size.odd?
    [:row, :col].map { @board.size / 2 }
  else
    choose_best_move
  end
end

Private Instance Methods

choose_best_move() click to toggle source
# File lib/computer_player.rb, line 23
def choose_best_move
  @negamax ||= create_negamax
  @negamax.apply(initial_node).fetch(:last_move_made)
end
create_child_node_generator() click to toggle source
# File lib/computer_player.rb, line 45
def create_child_node_generator
  lambda do |node|
    board = node.fetch(:board)
    current_player_mark = node.fetch(:current_player_mark)

    board.blank_space_coordinates.map do |coordinates|
      child_node = {
        board: board.mark_space(current_player_mark, coordinates),
        current_player_mark: toggle_mark(current_player_mark),
        last_move_made: coordinates
      }
      child_node
    end
  end
end
create_evaluation_heuristic() click to toggle source
# File lib/computer_player.rb, line 69
def create_evaluation_heuristic
  lambda do |node|
    board = node.fetch(:board)

    board.lines.each do |line|
      return 1 if line.all? { |mark|  mark == @player_mark }
      return -1 if line.all? { |mark|  mark == @opponent_mark }
    end
    0
  end
end
create_negamax() click to toggle source
# File lib/computer_player.rb, line 28
def create_negamax
  parameters = {
    child_node_generator: create_child_node_generator,
    terminal_node_criterion: create_terminal_node_criterion,
    evaluation_heuristic: create_evaluation_heuristic
  }
  Negamax.new(parameters)
end
create_terminal_node_criterion() click to toggle source
# File lib/computer_player.rb, line 61
def create_terminal_node_criterion
  lambda do |node|
    board = node.fetch(:board)

    board.has_winning_line? || board.all_marked?
  end
end
initial_node() click to toggle source
# File lib/computer_player.rb, line 37
def initial_node
  {
    board: @board,
    current_player_mark: @player_mark,
    last_move_made: nil
  }
end
toggle_mark(mark) click to toggle source
# File lib/computer_player.rb, line 81
def toggle_mark(mark)
  mark == @player_mark ? @opponent_mark : @player_mark
end