-
Notifications
You must be signed in to change notification settings - Fork 0
/
tic_tac_toe_ai.rb
executable file
·87 lines (76 loc) · 2.08 KB
/
tic_tac_toe_ai.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
require './tic_tac_toe_solution'
class TicTacToeNode
attr_accessor :board, :mark, :prev_move_pos
MARK = {:o => :x, :x => :o}
def initialize(board, mark, prev_move_pos = nil)
@board = board
@mark = mark
@prev_move_pos = prev_move_pos
end
def children # current state of board
open_spots = []
self.board.rows.each_with_index do |row, i|
row.each_with_index do |column, j|
if self.board.empty_spot?([i,j])
open_spots << [i,j]
end
end
end
child_boards = []
open_spots.each do |spot|
board_template = self.board.dup
board_template[spot] = self.mark
child_boards << TicTacToeNode.new(board_template, MARK[self.mark], spot) # recursively flip mark
end
child_boards
end
def winning_node?(player)
if self.board.winner == player
#puts "winning node"
return true
elsif !self.board.over?
new_children = self.children
#all and any depending on whose turn it is
if self.mark == player
new_children.any? {|child| child.winning_node?(player)}
else
children.all? {|child| child.winning_node?(player)}
#new_children.none? {|child| !child.winning_node?(player)}
end
else
#puts "ain't got nothing"
return false
end
end
def losing_node?(player)
if self.board.winner == MARK[player]
return true
elsif !self.board.over?
if self.mark == player
return self.children.all? {|child| child.losing_node?(player)}
elsif self.mark != player
return self.children.any? {|child| child.losing_node?(player)}
end
else
return false
end
end
end
class ComputerPlayer
def move(game, mark)
start_node = TicTacToeNode.new(game.board, mark)
start_node.children.each do |child|
if child.winning_node?(mark)
p mark
p child.prev_move_pos
p child.board
return child.prev_move_pos
end
end
start_node.children.each do |child|
if child.losing_node?(mark) == false
return child.prev_move_pos
end
end
end
end