-
Notifications
You must be signed in to change notification settings - Fork 0
/
board.py
96 lines (81 loc) · 2.93 KB
/
board.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
# BOARD CONSTANTS
WIDTH = 3
PADDING = WIDTH - 1
PADDED_WIDTH = WIDTH + 2 * PADDING
COL_MAP = {'A': 0, 'B': 1, 'C': 2}
class Board:
def __init__(self):
# 3x3 grid w/ 2 cells of padding each side
# padding prevents the has_win routine from having to check for out
# of bounds pieces
self.board = []
for row in range(PADDED_WIDTH):
self.board.append([" "] * PADDED_WIDTH)
self.marks = set()
def valid_input(self, row, col):
""" Returns True if row and col are valid values"""
return ((row, col) not in self.marks and
row <= WIDTH and row > 0 and
col in COL_MAP)
def mark(self, row, col, piece):
"""
Place a piece on the board at position ROW-COL
raises a ValueError if row or column is invalid
"""
if self.valid_input(row, col):
self.marks.add((row, col))
self.place_at(row - 1, COL_MAP[col], piece)
else:
raise ValueError("invalid row and column supplied: row={}, col={}"
.format(row, col))
def piece_at(self, row, col):
"""Get the piece at the zero indexed row and column"""
return self.board[row + PADDING][col + PADDING]
def place_at(self, row, col, piece):
"""Place the piece at the zero indexed row and column"""
self.board[row + PADDING][col + PADDING] = piece
def has_win(self, r, c, mark):
"""
Check if the last mark added at (r,c) creates a winning state
"""
row = r - 1
col = COL_MAP[c]
cnt = 0
board_range = xrange(-1 * PADDING, PADDING + 1)
# check vertical
for dr in board_range:
cnt = cnt + 1 if self.piece_at(row + dr, col) == mark else cnt
if cnt == WIDTH:
return True
else:
cnt = 0
# check horizontal
for dc in board_range:
cnt = cnt + 1 if self.piece_at(row, col + dc) == mark else cnt
if cnt == WIDTH:
return True
else:
cnt = 0
# check diagonal rightdown
for dd in board_range:
cnt = cnt + 1 if self.piece_at(row + dd, col + dd) == mark else cnt
if cnt == WIDTH:
return True
else:
cnt = 0
# check diagonal rightup
for dd in board_range:
cnt = cnt + 1 if self.piece_at(row - dd, col + dd) == mark else cnt
if cnt == WIDTH:
return True
return False
def show(self):
"""Print the board"""
print " A B C"
for row in xrange(0, WIDTH):
print "{} {}|{}|{}".format(row + 1, self.piece_at(row, 0),
self.piece_at(row, 1),
self.piece_at(row, 2))
def tie_exists(self):
"""Returns true if a tie exists on this board"""
return len(self.marks) == 9