-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgame.py
More file actions
184 lines (157 loc) · 6.24 KB
/
game.py
File metadata and controls
184 lines (157 loc) · 6.24 KB
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
import numpy as np
import time
from minimax import minimax, minValue, maxValue
from minimaxDepthLimit import minimaxDepth, minValueDepth, maxValueDepth
from alphabeta import alphaBeta, minValueAB, maxValueAB
from alphabetaDepthLimit import alphaBetaDepth, minValueABDepth, maxValueABDepth
from alphabetaHeuristic import alphaBetaDepthHeuristic, minValueABDepthHeuristic, maxValueABDepthHeuristic
class Game:
def __init__(self, size):
self.board = np.zeros([size, size]) # initialize board to 0's
self.size = size
def checkMove(self, row, col):
#Returns false if move is out of bounds
if row < 0 or row >= self.size:
return False
if col < 0 or col >= self.size:
return False
return True
# A simple display of the tic-tac-toe board
def display(self):
n = self.size
for i in range(n):
for j in range(n):
if self.board[i][j] == 0:
print("_", end=' ')
elif self.board[i][j] == 1:
print("O", end=' ')
else:
print("X", end=' ')
print()
# Returns true if the board is a terminal state
def isTerminal(self, state):
return self.checkRowsCols(state) or self.checkDiagonals(state) or self.checkFull(state)
# Returns true of a row is filled with X's or O's
def checkValues(self, list):
temp = set(list)
if (len(temp)) == 1: # If row only has one symbol
if not(list[0] == 0): # If row is not empty
return True # Either filled with x's or o's
def checkRowsCols(self, state):
# Check rows in self.board and cols using transpose
for board in [state, np.transpose(state)]:
for row in board:
if self.checkValues(row):
return True
return False
# Check if one of the diagonals is filled up
def checkDiagonals(self, state):
# Top left to bottom right
# (0,0), (1,1), ..., (n-1, n-1)
diagonal1 = [state[i][i] for i in range(self.size)]
# Bottom left to top right
# (2,0), (1,1), (0,2)
# i-1, j+1
diagonal2 = [state[self.size - 1 - i][i] for i in range(self.size)]
return self.checkValues(diagonal1) or self.checkValues(diagonal2)
# Checks if board has any open spaces left
def checkFull(self, state):
return not(0 in state)
# Returns possible action for player
def getActions(self, state):
# Check if (i, j) is a 0
possibleActions = [(i, j) for i in range(self.size) for j in range(self.size) if state[i][j] == 0]
#Return actions here
return possibleActions
# Reurns the reward value
def utility(self, state, player):
# Row/Col filled
for board in [state, np.transpose(state)]:
for row in board:
if self.checkValues(row):
if (row[0] == player):
return 100
else:
return -100
# Diagonal filled
diagonal1 = [state[i][i] for i in range(self.size)]
diagonal2 = [state[self.size - 1 - i][i] for i in range(self.size)]
if self.checkValues(diagonal1):
if (diagonal1[0] == player):
return 100
else:
return -100
elif self.checkValues(diagonal2):
if (diagonal2[0] == player):
return 100
else:
return -100
# Tie
return 0
# Returns the updated board after an action is taken
def result(self, state, action, player):
newState = state.copy()
(i, j) = action
newState[i][j] = player
return newState
# Heuristic used for determining how many possible wins there are for a player
# Used in alphaBetaHeuristic
def heuristic(self, state, player):
# number of possible winning rows/cols/diagonals
oppositePlayers = {1:2, 2:1}
possibleWins = 0
for board in [state, np.transpose(state)]:
for row in board:
if oppositePlayers[player] not in row:
possibleWins += 1
diagonal1 = [state[i][i] for i in range(self.size)]
diagonal2 = [state[self.size - 1 - i][i] for i in range(self.size)]
if oppositePlayers[player] not in diagonal1:
possibleWins += 1
if oppositePlayers[player] not in diagonal2:
possibleWins += 1
return possibleWins
if __name__ == "__main__":
tictactoe = Game(3)
print("Initial Board:\n", tictactoe.board)
print()
print("Initial Board with X's and O's:")
tictactoe.display()
validMove = False
while not(tictactoe.isTerminal(tictactoe.board)):
validMove = False
start = time.time()
aiAction = minimax(tictactoe, tictactoe.board, 1)
print("Time Taken (No Pruning):", time.time() - start)
start = time.time()
aiActionAB = alphaBeta(tictactoe, tictactoe.board, 1)
print("Time Taken (Pruning):", time.time() - start)
print(aiAction)
print(aiActionAB)
#tictactoe.board = tictactoe.result(tictactoe.board, aiAction, 1)
tictactoe.board = tictactoe.result(tictactoe.board, aiActionAB, 1)
if (tictactoe.isTerminal(tictactoe.board)):
break
print("Current Board:\n", tictactoe.board)
print()
print("Current Board:")
tictactoe.display()
print()
while not(validMove):
playerRow = int(input("Enter row:"))
playerCol = int(input("Enter col:"))
validMove = tictactoe.checkMove(playerRow, playerCol)
if (validMove == False):
print("Invalid move!")
playerMove = (playerRow, playerCol)
print("Player Move:", playerMove)
tictactoe.board = tictactoe.result(tictactoe.board, playerMove, 2)
print("Current Board:\n", tictactoe.board)
print()
print("Current Board:")
tictactoe.display()
print()
print("Final Board:\n", tictactoe.board)
print()
print("Final Board:")
tictactoe.display()