-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtris.py
192 lines (163 loc) · 5.81 KB
/
tris.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
#This file is in python 2.7
#class for tris architecture
from utils import DEBUG
class Tris:
EMPTY = 0
X = 1
O = 2
DRAW = 0
def __init__(self):
self.board = [
[Tris.EMPTY, Tris.EMPTY, Tris.EMPTY,],
[Tris.EMPTY, Tris.EMPTY, Tris.EMPTY,],
[Tris.EMPTY, Tris.EMPTY, Tris.EMPTY,],
]
#X starts first
self.current_player = Tris.X
def reset(self):
self.board = [
[Tris.EMPTY, Tris.EMPTY, Tris.EMPTY,],
[Tris.EMPTY, Tris.EMPTY, Tris.EMPTY,],
[Tris.EMPTY, Tris.EMPTY, Tris.EMPTY,],
]
#X starts first
self.current_player = Tris.X
# get current player
def get_current_player(self):
return self.current_player
# check if a space is empty
def is_empty(self, row, col):
return self.board[row][col] == Tris.EMPTY
# get a copy of the board
def get_board(self):
return [row[:] for row in self.board]
#make move
def move(self, row, col):
if DEBUG: print row
if DEBUG: print col
if self.board[row][col] != Tris.EMPTY:
return False
self.board[row][col] = self.current_player
self.current_player = Tris.O if self.current_player == Tris.X else Tris.X
return True
#check if game is over
def get_game_over_and_winner(self):
return get_game_over_and_winner(self.board) # w/o `self.` it refers to the global method outside
# highlights tiles in a tris to show on the tablet
def get_tris_highlights_for_tablet(self):
return get_tris_highlights_for_tablet(self.board) # w/o `self.` it refers to the global method outside
#check if a player may win next move
def player_is_threatening(self, player):
return player_is_threatening(self.board, player) # w/o `self.` it refers to the global method outside
#print class in pretty way
def __str__(self):
s = ''
for row in self.board:
for cell in row:
s += ' ' + ('X' if cell == Tris.X else 'O' if cell == Tris.O else ' ')
s += '\n'
return s
def get_board_for_tablet(self):
s = ''
for row in self.board:
for cell in row:
s += ('X' if cell == Tris.X else 'O' if cell == Tris.O else '.')
return s
#check if game is over
def get_game_over_and_winner(board):
# check rows
for row in board:
if row[0] != Tris.EMPTY and row[0] == row[1] == row[2]:
return True, row[0]
# check columns
for col in range(3):
if board[0][col] != Tris.EMPTY and board[0][col] == board[1][col] == board[2][col]:
return True, board[0][col]
# check diagonals
if board[0][0] != Tris.EMPTY and board[0][0] == board[1][1] == board[2][2]:
return True, board[0][0]
if board[0][2] != Tris.EMPTY and board[0][2] == board[1][1] == board[2][0]:
return True, board[0][2]
#no one wins yet
for row in board:
for cell in row:
if cell == Tris.EMPTY:
return False, None
#there is a draw
return True, Tris.DRAW
# highlight tris
def get_tris_highlights_for_tablet(board):
hl_matrix = [
[False, False, False],
[False, False, False],
[False, False, False],
]
# check rows
for row in range(3):
if board[row][0] != Tris.EMPTY and board[row][0] == board[row][1] == board[row][2]:
hl_matrix[row][0] = True
hl_matrix[row][1] = True
hl_matrix[row][2] = True
# check columns
for col in range(3):
if board[0][col] != Tris.EMPTY and board[0][col] == board[1][col] == board[2][col]:
hl_matrix[0][col] = True
hl_matrix[1][col] = True
hl_matrix[2][col] = True
# check diagonals
if board[0][0] != Tris.EMPTY and board[0][0] == board[1][1] == board[2][2]:
hl_matrix[0][0] = True
hl_matrix[1][1] = True
hl_matrix[2][2] = True
if board[0][2] != Tris.EMPTY and board[0][2] == board[1][1] == board[2][0]:
hl_matrix[0][2] = True
hl_matrix[1][1] = True
hl_matrix[2][0] = True
# generate tablet string
s = ''
for row in hl_matrix:
for cell in row:
s += ('H' if cell else '.')
return s
# a player threatens a win if there is a row, col or diag where two spaces have its symbol and the third is empty.
# first an aux
def set_is_threatened(tile1, tile2, tile3, player):
return (tile1 == tile2 == player and tile3 == Tris.EMPTY) or \
(tile2 == tile3 == player and tile1 == Tris.EMPTY) or \
(tile3 == tile1 == player and tile2 == Tris.EMPTY)
# then the real thing
def player_is_threatening(board, player):
# check rows
for row in board:
if set_is_threatened(row[0], row[1], row[2], player):
return True
# check columns
for col in range(3):
if set_is_threatened(board[0][col], board[1][col], board[2][col], player):
return True
# check diagonals
if set_is_threatened(board[0][0], board[1][1], board[2][2], player):
return True
if set_is_threatened(board[0][2], board[1][1], board[2][0], player):
return True
# no threats detected here
return False
#test
if __name__ == "__main__":
tris = Tris()
print "Playing a match"
#play a match
while True:
print tris
row = int(input('row: '))
col = int(input('col: '))
if not tris.move(row, col):
print 'invalid move'
game_over, winner = tris.get_game_over_and_winner()
if game_over:
if winner == Tris.DRAW:
print 'draw'
else:
print 'winner: ' + ('X' if winner == Tris.X else 'O')
break
print tris