Class: TicTacToe::AIRules::UnbeatableAI

Inherits:
Object
  • Object
show all
Defined in:
lib/ttt/ai/unbeatable_ai.rb

Constant Summary collapse

MAX_SCORE =
100
MIN_SCORE =
-100
TIED_SCORE =
0

Class Method Summary collapse

Class Method Details

.check_game_state(board, mark, depth) ⇒ Object



51
52
53
54
55
# File 'lib/ttt/ai/unbeatable_ai.rb', line 51

def self.check_game_state(board, mark, depth)
  return TIED_SCORE if board.tied_game?
  return MAX_SCORE + depth if board.winner == mark
  MIN_SCORE + depth
end

.game_done?(board, depth) ⇒ Boolean

Returns:

  • (Boolean)


57
58
59
# File 'lib/ttt/ai/unbeatable_ai.rb', line 57

def self.game_done?(board, depth)
  board.has_winner? || board.tied_game? || depth == 6
end

.make_move(board, mark) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/ttt/ai/unbeatable_ai.rb', line 8

def self.make_move(board, mark)
  best_score = MIN_SCORE
  best_space = 0
  opponent_mark = mark == "X" ? "O" : "X"

  board.empty_spaces.each do |space|
    board.place_move(mark, space)
    score = minimax(board, opponent_mark, 0, MIN_SCORE, MAX_SCORE, false, -1)
    board.undo_move(space)

    if score > best_score
      best_score = score
      best_space = space
    end
  end
  return best_space
end

.minimax(board, mark, depth, score_min, score_max, max_player, color) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/ttt/ai/unbeatable_ai.rb', line 26

def self.minimax(board, mark, depth, score_min, score_max, max_player, color)
  opponent_mark = mark == "X" ? "O" : "X"

  return check_game_state(board, mark, depth) * color if game_done?(board, depth)

  if max_player
    board.empty_spaces.each do |spaces|
      board.place_move(mark, spaces)
      score_min = [score_min, minimax(board, opponent_mark, depth + 1, score_min, score_max, !(max_player), -color)].max
      board.undo_move(spaces)
      break if score_min >= score_max
    end
    return score_min
  else

    board.empty_spaces.each do |spaces|
      board.place_move(mark, spaces)
      score_max = [score_max, minimax(board, opponent_mark, depth + 1, score_min, score_max, !(max_player), -color)].min
      board.undo_move(spaces)
      break if score_min >= score_max
    end
    return score_max
  end
end