-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathboardHelpers.py
More file actions
120 lines (96 loc) · 3.27 KB
/
boardHelpers.py
File metadata and controls
120 lines (96 loc) · 3.27 KB
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
from collections import defaultdict
from io import StringIO
def isInBounds(board, colIdx, rowIdx):
numCols = len(board)
numRows = len(board[0])
return 0 <= colIdx < numCols and 0 <= rowIdx < numRows
def getStartsHowManyInARow(board, colIdx, rowIdx, allowBlanks=False):
symbol = board[colIdx][rowIdx]
if symbol is None:
return 0
bestInARow = 0
directions = [(1, 0), (1, -1), (0, -1), (-1, -1)]
for colStep, rowStep in directions:
colCursor = colIdx
rowCursor = rowIdx
numInARowSoFar = 0
while isInBounds(board, colCursor, rowCursor) and (
board[colCursor][rowCursor] == symbol
or (allowBlanks and board[colCursor][rowCursor] is None)
):
if board[colCursor][rowCursor] == symbol:
numInARowSoFar += 1
rowCursor = rowCursor + rowStep
colCursor = colCursor + colStep
if numInARowSoFar > bestInARow:
bestInARow = numInARowSoFar
return bestInARow
def isStartsFourInARow(board, colIdx, rowIdx):
return getStartsHowManyInARow(board, colIdx, rowIdx) >= 4
def applyMoveToNewBoard(board, colIdx, symbol):
column = board[colIdx]
rowIdx = 0
while rowIdx < len(column):
if column[rowIdx] is None:
break
rowIdx += 1
newBoard = [
[
symbol if r == rowIdx and c == colIdx else existingSymbol
for r, existingSymbol in enumerate(column)
]
for c, column in enumerate(board)
]
return newBoard
def getAvailableColumns(board):
availableCols = []
for idx, column in enumerate(board):
if not all(column):
availableCols.append(idx)
return availableCols
def getWinner(board):
numCols = len(board)
numRows = len(board[0])
for colIdx in range(numCols):
for rowIdx in range(numRows):
if isStartsFourInARow(board, colIdx, rowIdx):
symbol = board[colIdx][rowIdx]
return symbol
return False
def isFull(board):
return all(all(column) for column in board)
# Heauristic Helpers
def getCenteringMetric(board, symbol):
middleCol = (len(board) - 1) / 2.0
dists = [
abs(colIdx - middleCol)
for colIdx, column in enumerate(board)
for s in column
if s == symbol
]
avgDist = sum(dists) / float(len(dists)) if dists else None
return avgDist
def getInARowMetric(board, symbol, allowBlanks=False):
inARowCounts = defaultdict(int)
for colIdx, column in enumerate(board):
for rowIdx, _ in enumerate(column):
if board[colIdx][rowIdx] == symbol:
inARow = getStartsHowManyInARow(board, colIdx, rowIdx, allowBlanks)
inARowCounts[inARow] += 1
if len(inARowCounts.keys()) == 0:
return None, None
mostInARow = max(inARowCounts.keys())
mostInARowFreq = inARowCounts[mostInARow]
return mostInARow, mostInARowFreq
# Printing
def boardStr(board):
numCols = len(board)
numRows = len(board[0])
sio = StringIO()
for rowIdx in reversed(range(numRows)):
for colIdx in range(numCols):
symbol = board[colIdx][rowIdx] or "-"
sio.write(" %s" % symbol)
sio.write("\n")
result = sio.getvalue()
return result