class AI

Attributes

best_move[RW]

Public Class Methods

create(game, type, computer) click to toggle source
# File lib/ttt-cli/ai.rb, line 6
def self.create(game, type, computer)
  type.new(game, computer)
end
new(game, computer) click to toggle source
# File lib/ttt-cli/ai.rb, line 10
def initialize(game, computer)
  @game = game
  @board = game.board
  @computer = computer
  @enemy = @game.first_player
  @best_move = nil
end

Public Instance Methods

move_generate() click to toggle source

Метод для генерации хода AI

# File lib/ttt-cli/ai.rb, line 19
def move_generate; end

Private Instance Methods

is_first_move?() click to toggle source
# File lib/ttt-cli/ai.rb, line 23
def is_first_move?
  @board.empty_cells.size == 9 ||
    @board.empty_cells.size == 8
end
minimax(board, player, depth = 0, moves = {}) click to toggle source

основная минимакс-функция возвращает значение, если найдено конечное состояние(+10, 0, -10) проходит по всем пустым клеткам на поле вызывает минимакс функцию для каждой из них (рекурсия) оценивает полученные значения и возвращает наилучшее из них

# File lib/ttt-cli/ai.rb, line 34
def minimax(board, player, depth = 0, moves = {})
  # копия доски
  new_board = board.dup
  # индексы свободных клеток
  empty_indices = new_board.empty_cells

  # проверка на терминальное состояние
  return 10 - depth if @game.won?(@computer)
  return -10 + depth if @game.won?(@enemy)
  return 0 if @game.draw?

  empty_indices.each do |index|
    new_board.fill_cell(index, player.token)
    next_player = opponent(player)
    moves[index] = minimax(new_board, next_player, depth + 1)
    new_board.reset_cell(index)
  end

  # возвращаем наилучшее значение
  minimax_score(moves, player)
end
minimax_score(moves, player) click to toggle source

метод для оценки полученных значений возвращает наилучшее значение

# File lib/ttt-cli/ai.rb, line 58
def minimax_score(moves, player)
  if player.token == @computer.token
    @best_move, best_score = moves.max_by { |_, v| v }
  else
    @best_move, best_score = moves.min_by { |_, v| v }
  end

  best_score
end
opponent(player) click to toggle source

метод для выбора оппонента для текущего игрока

# File lib/ttt-cli/ai.rb, line 69
def opponent(player)
  if player.token == @computer.token
    @enemy
  else
    @computer
  end
end