Class: TicTacToe::Strategy::ThreeByThree::Heuristic

Inherits:
Object
  • Object
show all
Defined in:
lib/tic_tac_toe/strategies/three_by_three_strategy.rb

Overview

Brute Force Implementation for the Three by Three Strategy This implementation uses loops to try a change all of the board values and checking the result

For example, win! is implemented by trying every cell, and checking if it was a winning solution

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(board, letter) ⇒ Heuristic

Returns a new instance of Heuristic.



40
41
42
43
# File 'lib/tic_tac_toe/strategies/three_by_three_strategy.rb', line 40

def initialize(board, letter)
  @board, @letter, @state = board, letter, PotentialState.new(board, letter)
  @other_player = other_player
end

Instance Attribute Details

#boardObject (readonly)

Returns the value of attribute board.



38
39
40
# File 'lib/tic_tac_toe/strategies/three_by_three_strategy.rb', line 38

def board
  @board
end

Instance Method Details

#block(board = @board, letter = @letter) ⇒ Object

Try placing the opponent’s letter at every available position If the board is solved, block them at that position



58
59
60
61
62
63
64
65
66
# File 'lib/tic_tac_toe/strategies/three_by_three_strategy.rb', line 58

def block(board = @board, letter = @letter)
  state = PotentialState.new(board, other_player(letter))
  each_position do |row, column|
    if state.at(row, column).solved?
      return [row, column]
    end
  end
  false
end

#block_forkObject

Try placing the opponent’s letter at every position. If there are now two winning solutions for next turn, block them there



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/tic_tac_toe/strategies/three_by_three_strategy.rb', line 79

def block_fork
  PotentialState.new(@board, @other_player).each_forking_position do |row, column|

    # Simulate blocking the fork
    temp_board = @board.clone
    temp_board.play_at(row, column, @letter)

    # Search for the elusive double fork
    if PotentialState.new(temp_board, @other_player).forking_positions.any?
      return force_a_block 
    end

    return [row, column]
  end
  false
end

#centerObject



96
97
98
99
# File 'lib/tic_tac_toe/strategies/three_by_three_strategy.rb', line 96

def center
  return false if @board.get_cell(@board.size/2, @board.size/2)
  [@board.size/2, @board.size/2]
end

#empty_cornerObject

Cycle though all of the corners, until one is found that is empty



116
117
118
119
120
121
122
# File 'lib/tic_tac_toe/strategies/three_by_three_strategy.rb', line 116

def empty_corner
  corners.each_with_index do |corner, index|
    next if corner
    return corner_from_index(index)
  end
  false
end

#empty_sideObject

Place letter at a random empty cell, at this point it should only be sides left



125
126
127
128
129
130
# File 'lib/tic_tac_toe/strategies/three_by_three_strategy.rb', line 125

def empty_side
  @board.empty_positions do |row, column|
    return [row, column] 
  end
  false
end

#forkObject

Try placing the letter at every position. If there are now two winning solutions for next turn, go there



70
71
72
73
74
75
# File 'lib/tic_tac_toe/strategies/three_by_three_strategy.rb', line 70

def fork
  @state.each_forking_position do |row, column|
    return [row, column]
  end
  false
end

#opposite_cornerObject

Cycle through all of the corners looking for the opponent’s letter If one is found, place letter at the opposite corner



103
104
105
106
107
108
109
110
111
112
113
# File 'lib/tic_tac_toe/strategies/three_by_three_strategy.rb', line 103

def opposite_corner
  first = 0
  last = @board.size - 1
  corners.each_with_index do |corner, index|
    if corner == @other_player
      next if @board.get_cell(*opposite_corner_from_index(index).compact)
      return opposite_corner_from_index(index)
    end
  end
  false
end

#winObject

Try placing letter at every available position If the board is solved, do that



47
48
49
50
51
52
53
54
# File 'lib/tic_tac_toe/strategies/three_by_three_strategy.rb', line 47

def win
  each_position do |row, column|
    if @state.at(row, column).solved?
      return [row, column]
    end
  end
  false
end