-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathttt.py
279 lines (191 loc) · 5.28 KB
/
ttt.py
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# Dimension of Board #
SIZE = 3
# Board Symbols #
NA = "?"
Xs = "X"
Os = "O"
# Utilities for Minimax Algorithm #
POSITIVE_INFINITY = 1e500
NEGATIVE_INFINITY = -1e500
def generateKey (i, j):
return str(i) + "," + str(j)
def showBoard (board):
printable = ""
for i in range (SIZE):
for j in range (SIZE):
key = generateKey(i, j)
printable += " " + board[key] + " "
if (j < (SIZE - 1)):
printable += "|"
if (i < (SIZE - 1)):
printable += "\n---|---|---\n"
print ("\nBoard:\n\n" + printable + "\n")
def setBoard ():
board = {}
for i in range (SIZE):
for j in range (SIZE):
key = generateKey(i, j)
board[key] = NA
return board
def winningConditions ():
conditions = []
"""
The game of tic-tac-toe is won, when a player procures all of the squares in:
- Any of the rows, OR
- Any of the columns, OR
- The left diagonal, OR
- The right diagonal.
"""
lDiag = []
rDiag = []
for i in range(SIZE):
row = []
col = []
lDiag.append(generateKey(i, i))
rDiag.append(generateKey(i, (SIZE - (i + 1))))
for j in range(SIZE):
row.append(generateKey(i, j))
col.append(generateKey(j, i))
conditions.append(row)
conditions.append(col)
conditions.append(lDiag)
conditions.append(rDiag)
return conditions
def wonBy (board, symbol):
WINNING_CONDITIONS = winningConditions()
for winningCondition in WINNING_CONDITIONS:
won = True
for square in winningCondition:
if (board[square] != symbol):
won = False
break
if (won):
return True
return False
def availableMoves (board):
moves = []
for i in range(SIZE):
for j in range(SIZE):
key = generateKey(i, j)
if (board[key] == NA):
moves.append(key)
return moves
def minimax (board, maximize, alpha, beta, player, computer):
moves = availableMoves(board)
if (wonBy(board, computer)):
return {
'mv': 1,
'mb': board
}
elif (wonBy(board, player)):
return {
'mv': -1,
'mb': board
}
elif (len(moves) == 0):
return {
'mv': 0,
'mb': board
}
if (maximize):
maxValue = NEGATIVE_INFINITY
maximizedBoard = None
for move in moves:
next = dict.copy(board)
next[move] = computer
maxi = minimax (next, False, alpha, beta, player, computer)
if (maxi['mv'] > maxValue):
maxValue = maxi['mv']
maximizedBoard = next
alpha = max(alpha, maxValue)
if beta <= alpha:
break
return {
'mv': maxValue,
'mb': maximizedBoard
}
else:
minValue = POSITIVE_INFINITY
minimizedBoard = None
for move in moves:
next = dict.copy(board)
next[move] = player
mini = minimax (next, True, alpha, beta, player, computer)
if (mini['mv'] < minValue):
minValue = mini['mv']
minimizedBoard = next
beta = min( beta, minValue)
if beta <= alpha:
break
return {
'mv': minValue,
'mb': minimizedBoard
}
def playersMove (board, player):
validInput = False
statement = ""
while not(validInput):
statement = input("\nPlayer's Move: ")
if (statement in board.keys() and board[statement] == NA):
validInput = True
else:
print("\nInvalid input; please try again.\nReminder: enter an input in the form of 'row,column' (in base 0)\n")
board[statement] = player
return board
def ticTacToe (board, player, computer):
WIN_CONDITIONS = winningConditions()
MAX_TURNS = SIZE * SIZE
showBoard(board)
turn = 0
order = [Xs, Os]
while (turn < MAX_TURNS):
print("Turn #", (turn + 1))
if (order[turn % 2] == player):
board = playersMove(board, player)
showBoard(board)
if (wonBy(board, player)):
print("Victory.")
return +1
else:
board = minimax(board, True, NEGATIVE_INFINITY, POSITIVE_INFINITY, player, computer)['mb']
showBoard(board)
if (wonBy(board, computer)):
print("Defeat.")
return -1
turn += 1
print("Draw.")
return 0
def main ():
print ("Tic-Tac-Toe")
score = 0
terminate = False
while not(terminate):
board = setBoard()
player = None
computer = None
validInput = False
while not(validInput):
symbol = input("\nXs or Os? ")
if (symbol == "Xs"):
player = Xs
computer = Os
validInput = True
elif (symbol == "Os"):
player = Os
computer = Xs
validInput = True
else:
print("\nInvalid input. Reminder: enter either 'Xs' or 'Ys'.")
score += ticTacToe(board, player, computer)
validInput = False
while not(validInput):
again = input("\nPlay Again (Y or N)? ")
if (again == "Y"):
validInput = True
elif (again == "N"):
print("\nFinal score:", score)
return
else:
print("\nInvalid input. Reminder: enter either 'Y' or 'N'.")
if (__name__ == "__main__"):
main()