As a programming exercise, I've attempted a Tic-Tac-Toe solver which takes a finished board and determines a winner.
On top of checks for malformed input/ambiguous games (e.g. both players with winning positions), what else can I do to improve this? In particular, is the coding style acceptable and are there better ways to check for win conditions?
def tictac(b):
"""
Parses a tic-tac-toe board and returns a winner.
Input: a list of lists containing values 0 or 1.
0 corresponds to 'noughts' and 1 to 'crosses'
e.g.
>>> gameboard = [[0,0,1],[0,1,0],[1,1,0]]
>>> tictac(gameboard)
X wins
"""
# If the sum of a column/row/diagonal is 0, O wins.
# If the sum is number of rows/columns, X wins.
winner = ""
board_range = range(len(b))
# Check rows and columns.
for i in board_range:
row_sum = sum(b[i])
col_sum = sum([x[i] for x in b])
if row_sum == 0 or col_sum == 0:
winner = "O wins"
elif row_sum == len(b) or col_sum == len(b):
winner = "X wins"
# Check the diagonals.
fwd_diag_sum = sum([b[i][i] for i in board_range])
bck_diag_sum = sum([b[i][len(b)-i-1] for i in board_range])
if fwd_diag_sum == 0 or bck_diag_sum == 0:
winner = "O wins"
if fwd_diag_sum == len(b) or bck_diag_sum == len(b):
winner = "X wins"
if winner:
print winner
else:
print "Game is a tie!"
For convenience, here's a little test function too:
def test_tic_tac():
def pretty_print(b):
for row in b:
print row
gameboard = [[0,0,1],[0,1,0],[1,1,0]]
pretty_print(gameboard)
tictac(gameboard)
gameboard = [[0,1,1],[0,0,0],[1,1,0]]
pretty_print(gameboard)
tictac(gameboard)
gameboard = [[1,0,1],[0,0,1],[0,1,0]]
pretty_print(gameboard)
tictac(gameboard)
gameboard = [[0,0,1,0],[1,1,0,1],[0,1,1,1],[0,1,0,1]]
pretty_print(gameboard)
tictac(gameboard)