-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
462 lines (385 loc) · 15.2 KB
/
main.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
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
# Scripts:
from board import *
from score_db import *
from constants import *
# Modules:
import secrets
import time
av_options = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
g_op = ["", "", "", "", "", "", "", "", ""]
turn = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
ai_choice = ""
def start():
create_table()
print("\n"
"Welcome to Tic Tac Toe game!\n"
"")
rules = input("If you already know the rules press any key to continue, otherwise type 'help'. ")
if rules in ['help', 'HELP', 'Help']:
print("\n"
"1. The game is played on a grid that's 3 squares by 3 squares.\n"
"2. You can choose 'X' or 'O' and the other person or AI uses the remaining option.\n"
"3. Players take turns putting their marks in empty squares. Squares are identified with numbers:\n"
f"{example_board}"
"4. The first player to get 3 of her marks in a row (up, down, across, or diagonally) is the winner.\n"
"5. When all 9 squares are full, the game is over. "
"If no player has 3 marks in a row, the game ends in a tie.")
select_name("1")
def select_name(n_player):
if n_player == "1":
global name_p1
name_p1 = input("\n"
"Player 1 please enter your name: ")
if name_p1 == "":
name_p1 = "Mysterious Guy"
else:
insert_player_name(name_p1)
print(f"\n"
f"Hello {name_p1}!")
global dictionary
dictionary = {"1": name_p1}
select_game_mode()
else:
global name_p2
name_p2 = input("\n"
"Player 2 please enter your name: ")
if name_p2 == "":
name_p2 = "Mysterious Guy's partner"
else:
insert_player_name(name_p2)
print(f"\n"
f"Hello {name_p2}!")
dictionary.update({"2": name_p2})
select_mark()
def select_game_mode():
global game_mode
game_mode = input("\n"
"Please select the game mode:\n"
"1- Easy\n"
"2- Medium\n"
"3- Hard\n"
"4- PVP\n"
"")
if game_mode not in ["1", "2", "3", "4"]:
print("Please select a valid option ")
select_game_mode()
elif game_mode == "4":
select_name("2")
select_mark()
def select_mark():
global p_mark
global ai_mark
p_mark = input("\n"
f"{name_p1} choose 'X' or 'O' (remember 'X' moves first)\n"
"")
x_choice = ["x", "X", "1"]
o_choice = ["o", "O", "0", "2"]
if p_mark not in x_choice + o_choice:
print("Please select a valid option ")
select_mark()
if p_mark in x_choice:
p_mark = "X"
ai_mark = "O"
dictionary.update({"1": [name_p1, p_mark]})
if game_mode == "4":
dictionary.update({"2": [name_p2, ai_mark]})
play_player("1")
else:
play_player("1")
else:
p_mark = "O"
ai_mark = "X"
dictionary.update({"1": [name_p1, p_mark]})
if game_mode == "4":
dictionary.update({"2": [name_p2, ai_mark]})
play_player("2")
else:
play_ai(game_mode)
def play_player(n_player):
if len(av_options) == 9:
print("\n"
f" » {dictionary[n_player][0]}'s Turn")
print(board.format(*g_op))
else:
print(f" {dictionary[n_player][0]}'s Turn")
p_choice = input("\n"
f"Choose an empty square from the list {av_options}: ")
if p_choice in av_options:
av_options.remove(p_choice)
g_op.pop(int(p_choice) - 1)
g_op.insert(int(p_choice) - 1, dictionary[n_player][1])
else:
print("Please select a valid option ")
play_player(n_player)
time.sleep(0.4)
print(board.format(*g_op))
check_win(n_player)
turn.pop(0)
if game_mode == "4":
if n_player == "1":
play_player("2")
else:
play_player("1")
else:
play_ai(game_mode)
def play_ai(game_mode):
print(" » AI's Turn")
if game_mode == "1": # 65% AI Hard
ai_choice = secrets.choice(set_conditional_choice(65, play_ai_hard(turn[0])))
elif game_mode == "2": # 88% AI Hard
ai_choice = secrets.choice(set_conditional_choice(88, play_ai_hard(turn[0])))
else: # AI Hard
ai_choice = play_ai_hard(turn[0])
av_options.remove(ai_choice)
g_op.pop(int(ai_choice) - 1)
g_op.insert(int(ai_choice) - 1, ai_mark)
time.sleep(0.4)
print(board.format(*g_op))
check_win("1")
turn.pop(0)
play_player("1")
def set_conditional_choice(probability, ai_hard_choice):
prob_list = []
while probability > (prob_list + av_options).count(ai_hard_choice) * 100 / len(prob_list + av_options):
prob_list.append(ai_hard_choice)
return av_options + prob_list
def play_ai_hard(n_turn):
if n_turn == "1":
return secrets.choice(CORNERS + CENTER)
if n_turn == "2":
if g_op[4] == "":
return AI_LIST[4]
else:
return secrets.choice(CORNERS)
else:
choice_list = [check_win_or_block(ai_mark), check_win_or_block(p_mark), check_forks(ai_mark),
check_forks(p_mark), check_other_moves(ai_mark), check_other_moves(p_mark),
check_final_moves(ai_mark), check_final_moves(p_mark)]
for i in choice_list:
if i in av_options:
return i
def check_win_or_block(mark):
# Win Moves, Forks / Block Moves, Forks
r1 = [g_op[0], g_op[1], g_op[2]]
r2 = [g_op[3], g_op[4], g_op[5]]
r3 = [g_op[6], g_op[7], g_op[8]]
c1 = [g_op[0], g_op[3], g_op[6]]
c2 = [g_op[1], g_op[4], g_op[7]]
c3 = [g_op[2], g_op[5], g_op[8]]
d1 = [g_op[0], g_op[4], g_op[8]]
d2 = [g_op[2], g_op[4], g_op[6]]
all_op = [r1, r2, r3, c1, c2, c3, d1, d2]
for i in range(len(all_op)):
if (all_op[i][0], all_op[i][1]) == (mark, mark) and all_op[i][2] == "":
return ALL_OP[i][2]
elif (all_op[i][0], all_op[i][2]) == (mark, mark) and all_op[i][1] == "":
return ALL_OP[i][1]
elif (all_op[i][1], all_op[i][2]) == (mark, mark) and all_op[i][0] == "":
return ALL_OP[i][0]
def check_forks(mark):
# Others Win Forks / Block Forks
if (g_op[1], g_op[3]) == (mark, mark) and (g_op[0], g_op[2], g_op[6]) == ("", "", ""):
return AI_LIST[0]
elif (g_op[1], g_op[6]) == (mark, mark) and (g_op[0], g_op[2], g_op[3]) == ("", "", ""):
return AI_LIST[0]
elif (g_op[2], g_op[3]) == (mark, mark) and (g_op[0], g_op[1], g_op[6]) == ("", "", ""):
return AI_LIST[0]
elif (g_op[1], g_op[5]) == (mark, mark) and (g_op[0], g_op[2], g_op[8]) == ("", "", ""):
return AI_LIST[2]
elif (g_op[0], g_op[5]) == (mark, mark) and (g_op[1], g_op[2], g_op[8]) == ("", "", ""):
return AI_LIST[2]
elif (g_op[1], g_op[8]) == (mark, mark) and (g_op[0], g_op[2], g_op[5]) == ("", "", ""):
return AI_LIST[2]
elif (g_op[3], g_op[7]) == (mark, mark) and (g_op[0], g_op[6], g_op[8]) == ("", "", ""):
return AI_LIST[6]
elif (g_op[0], g_op[7]) == (mark, mark) and (g_op[3], g_op[6], g_op[8]) == ("", "", ""):
return AI_LIST[6]
elif (g_op[3], g_op[8]) == (mark, mark) and (g_op[0], g_op[6], g_op[7]) == ("", "", ""):
return AI_LIST[6]
elif (g_op[5], g_op[7]) == (mark, mark) and (g_op[2], g_op[6], g_op[8]) == ("", "", ""):
return AI_LIST[8]
elif (g_op[2], g_op[7]) == (mark, mark) and (g_op[5], g_op[6], g_op[8]) == ("", "", ""):
return AI_LIST[8]
elif (g_op[5], g_op[6]) == (mark, mark) and (g_op[2], g_op[7], g_op[8]) == ("", "", ""):
return AI_LIST[8]
elif (g_op[0], g_op[8]) == (mark, mark) and (g_op[1], g_op[2], g_op[3], g_op[5], g_op[6], g_op[7]) == (
"", "", "", "", "", ""):
return secrets.choice(EDGES)
elif (g_op[2], g_op[6]) == (mark, mark) and (g_op[0], g_op[1], g_op[3], g_op[5], g_op[7], g_op[8]) == (
"", "", "", "", "", ""):
return secrets.choice(EDGES)
def check_other_moves(mark):
# Search Forks or Win Condition
if g_op[0] not in ("", mark):
if (g_op[1], g_op[2]) == ("", ""):
return AI_LIST[2]
elif (g_op[4], g_op[8]) == ("", ""):
return AI_LIST[4]
elif (g_op[3], g_op[6]) == ("", ""):
return AI_LIST[6]
elif g_op[1] not in ("", mark) and (g_op[4], g_op[7]) == ("", ""):
return AI_LIST[7]
elif g_op[2] not in ("", mark):
if (g_op[0], g_op[1]) == ("", ""):
return AI_LIST[0]
elif (g_op[4], g_op[6]) == ("", ""):
return AI_LIST[4]
elif (g_op[5], g_op[8]) == ("", ""):
return AI_LIST[8]
elif g_op[3] not in ("", mark) and (g_op[4], g_op[5]) == ("", ""):
return AI_LIST[5]
elif g_op[5] not in ("", mark) and (g_op[3], g_op[4]) == ("", ""):
return AI_LIST[3]
elif g_op[6] not in ("", mark):
if (g_op[0], g_op[3]) == ("", ""):
return AI_LIST[0]
elif (g_op[2], g_op[4]) == ("", ""):
return AI_LIST[4]
elif (g_op[7], g_op[8]) == ("", ""):
return AI_LIST[8]
elif g_op[7] not in ("", mark) and (g_op[1], g_op[4]) == ("", ""):
return AI_LIST[1]
elif g_op[8] not in ("", mark):
if (g_op[2], g_op[5]) == ("", ""):
return AI_LIST[2]
elif (g_op[0], g_op[4]) == ("", ""):
return AI_LIST[4]
elif (g_op[6], g_op[7]) == ("", ""):
return AI_LIST[6]
elif g_op[4] not in ("", mark) and (g_op[0], g_op[8]) == ("", ""):
return secrets.choice([AI_LIST[0], AI_LIST[8]])
elif g_op[4] not in ("", mark) and (g_op[1], g_op[7]) == ("", ""):
return secrets.choice([AI_LIST[1], AI_LIST[7]])
elif g_op[4] not in ("", mark) and (g_op[2], g_op[6]) == ("", ""):
return secrets.choice([AI_LIST[2], AI_LIST[6]])
elif g_op[4] not in ("", mark) and (g_op[3], g_op[5]) == ("", ""):
return secrets.choice([AI_LIST[3], AI_LIST[5]])
def check_final_moves(mark):
corners = [g_op[0], g_op[2], g_op[6], g_op[8]]
edges = [g_op[1], g_op[3], g_op[5], g_op[7]]
# Last Empty Slots
if (g_op[1], g_op[7]) == ("", "") and g_op[4] == mark:
return secrets.choice([AI_LIST[1], AI_LIST[7]])
elif (g_op[3], g_op[5]) == ("", "") and g_op[4] == mark:
return secrets.choice([AI_LIST[3], AI_LIST[5]])
else:
# Opposite Corner
for i in range(len(corners)):
if corners[i] not in ("", mark) and list(reversed(corners))[i] == "":
return list(reversed(CORNERS))[i]
# Corner
for i in range(len(corners)):
if corners[i] == "":
return CORNERS[i]
# Edge
for i in range(len(edges)):
if edges[i] == "":
return EDGES[i]
def check_win(n_player):
r1 = [g_op[0], g_op[1], g_op[2]]
r2 = [g_op[3], g_op[4], g_op[5]]
r3 = [g_op[6], g_op[7], g_op[8]]
c1 = [g_op[0], g_op[3], g_op[6]]
c2 = [g_op[1], g_op[4], g_op[7]]
c3 = [g_op[2], g_op[5], g_op[8]]
d1 = [g_op[0], g_op[4], g_op[8]]
d2 = [g_op[2], g_op[4], g_op[6]]
all_op = [r1, r2, r3, c1, c2, c3, d1, d2]
if len(av_options) <= 4:
for i in all_op:
if i[0] == i[1] and i[0] == i[2] and (i[0], i[1], i[2]) != ("", "", ""):
win_message(n_player)
if len(av_options) == 0:
tie_message()
def win_message(n_player):
player_win = f"Congratulations {dictionary[n_player][0]}!, you won the game in {turn[0]} turns"
ai_win = f"AI won the game in {turn[0]} turns, better luck next time pal!"
if g_op.count("X") > g_op.count("O") and p_mark == "X":
print(player_win)
if game_mode == "4":
update_player_score(dictionary["1"][0], game_mode, 0)
update_player_score(dictionary["2"][0], game_mode, 1)
else:
update_player_score(dictionary["1"][0], game_mode, 0)
elif g_op.count("X") > g_op.count("O") and ai_mark == "X":
if game_mode == "4":
print(player_win)
update_player_score(dictionary["1"][0], game_mode, 1)
update_player_score(dictionary["2"][0], game_mode, 0)
else:
print(ai_win)
update_player_score(dictionary[n_player][0], game_mode, 1)
elif g_op.count("O") == g_op.count("X") and p_mark == "O":
print(player_win)
if game_mode == "4":
update_player_score(dictionary["1"][0], game_mode, 0)
update_player_score(dictionary["2"][0], game_mode, 1)
else:
update_player_score(dictionary["1"][0], game_mode, 0)
elif g_op.count("O") == g_op.count("X") and ai_mark == "O":
if game_mode == "4":
print(player_win)
update_player_score(dictionary["2"][0], game_mode, 0)
update_player_score(dictionary["1"][0], game_mode, 1)
else:
print(ai_win)
update_player_score(dictionary[n_player][0], game_mode, 1)
play_again()
def tie_message():
print(" Tie! ")
if game_mode == "4":
update_player_score(dictionary["1"][0], game_mode, 2)
update_player_score(dictionary["2"][0], game_mode, 2)
else:
update_player_score(dictionary["1"][0], game_mode, 2)
play_again()
def play_again():
av_options.clear()
g_op.clear()
turn.clear()
av_options.extend(["1", "2", "3", "4", "5", "6", "7", "8", "9"])
g_op.extend(["", "", "", "", "", "", "", "", ""])
turn.extend(["1", "2", "3", "4", "5", "6", "7", "8", "9"])
final_choice = input("\n"
"Do you want yo play again?\n"
"1- Yes, same game mode\n"
"2- Yes, but change game mode\n"
"3- No, thanks!\n"
"4- Show my score\n"
"")
if final_choice == "4":
if game_mode == "4":
if name_p1 != "Mysterious Guy" and name_p2 != "Mysterious Guy's partner":
show_data(name_p1)
show_data(name_p2)
play_again()
elif name_p1 == "Mysterious Guy" and name_p2 == "Mysterious Guy's partner":
print("\n"
"If you are playing nameless, you have no stats! ")
play_again()
elif name_p1 != "Mysterious Guy" and name_p2 == "Mysterious Guy's partner":
show_data(name_p1)
play_again()
elif name_p1 == "Mysterious Guy" and name_p2 != "Mysterious Guy's partner":
show_data(name_p2)
play_again()
else:
if name_p1 != "Mysterious Guy":
show_data(name_p1)
play_again()
elif name_p1 == "Mysterious Guy":
print("\n"
"If you are playing nameless, you have no stats! ")
play_again()
elif final_choice == "1":
select_mark()
elif final_choice == "2":
select_game_mode()
elif final_choice == "3":
exit()
else:
print("\n"
"Please select a valid option ")
play_again()
if __name__ == "__main__":
start()