-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
157 lines (136 loc) · 4.75 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
from pyweb import pydom
class TicTacToe:
def __init__(self):
self.board = pydom["table#board"]
self.status = pydom["h2#status"]
self.console = pydom["script#console"][0]
self.init_cells()
self.init_winning_combos()
self.new_game(...)
def set_status(self, text):
self.status.html = text
def init_cells(self):
self.cells = []
for i in (0, 1, 2):
row = []
for j in (0, 1, 2):
cell = pydom[f"div#cell{i}{j}"][0]
assert cell
row.append(cell)
self.cells.append(row)
def init_winning_combos(self):
self.winning_combos = []
# winning columns
for i in (0, 1, 2):
combo = []
for j in (0, 1, 2):
combo.append((i, j))
self.winning_combos.append(combo)
# winning rows
for j in (0, 1, 2):
combo = []
for i in (0, 1, 2):
combo.append((i, j))
self.winning_combos.append(combo)
# winning diagonals
self.winning_combos.append([(0, 0), (1, 1), (2, 2)])
self.winning_combos.append([(0, 2), (1, 1), (2, 0)])
def new_game(self, event):
self.clear_terminal()
print('=================')
print('NEW GAME STARTING')
print()
for i in (0, 1, 2):
for j in (0, 1, 2):
self.set_cell(i, j, "")
self.current_player = "x"
self.set_status(f'{self.current_player} playing...')
def next_turn(self):
winner = self.check_winner()
if winner == "tie":
self.set_status("It's a tie!")
self.current_player = "" # i.e., game ended
return
elif winner is not None:
self.set_status(f'{winner} wins')
self.current_player = "" # i.e., game ended
return
if self.current_player == "x":
self.current_player = "o"
else:
self.current_player = "x"
self.set_status(f'{self.current_player} playing...')
def check_winner(self):
"""
Check whether the game as any winner.
Return "x", "o", "tie" or None. None means that the game is still playing.
"""
# check whether we have a winner
for combo in self.winning_combos:
winner = self.get_winner(combo)
if winner:
# highlight the winning cells
for i, j in combo:
self.cells[i][j].add_class("win")
return winner
# check whether it's a tie
for i in (0, 1, 2):
for j in (0, 1, 2):
if self.get_cell(i, j) == "":
# there is at least an empty cell, it's not a tie
return None # game still playing
return "tie"
def get_winner(self, combo):
"""
If all the cells at the given points have the same value, return it.
Else return "".
Each point is a tuple of (i, j) coordinates.
Example:
self.get_winner([(0, 0), (1, 1), (2, 2)])
"""
assert len(combo) == 3
values = [self.get_cell(i, j) for i, j in combo]
if values[0] == values[1] == values[2] and values[0] != "":
return values[0]
return ""
def set_cell(self, i, j, value):
assert value in ("", "x", "o")
cell = self.cells[i][j]
cell.html = value
if "x" in cell.classes:
cell.remove_class("x")
if "o" in cell.classes:
cell.remove_class("o")
if "win" in cell.classes:
cell.remove_class("win")
if value != "":
cell.add_class(value)
def get_cell(self, i, j):
cell = self.cells[i][j]
value = cell.html
assert value in ("", "x", "o")
return value
def click(self, event):
i = int(event.target.getAttribute('data-x'))
j = int(event.target.getAttribute('data-y'))
print(f'Cell {i}, {j} clicked: ', end='')
if self.current_player == "":
print('game ended, nothing to do')
return
#
value = self.get_cell(i, j)
if value == "":
print('cell empty, setting it')
self.set_cell(i, j, self.current_player)
self.next_turn()
else:
print(f'cell already full, cannot set it')
def clear_terminal(self):
self.console._js.terminal.clear()
def toggle_terminal(self, event):
hidden = self.console.parent._js.getAttribute("hidden")
if hidden:
self.console.parent._js.removeAttribute("hidden")
else:
self.console.parent._js.setAttribute("hidden", "hidden")
GAME = TicTacToe()