Skip to content

Instantly share code, notes, and snippets.

@trotha01
Last active November 13, 2016 00:12
Show Gist options
  • Save trotha01/81a56d6cadd2b167831bdb1167001575 to your computer and use it in GitHub Desktop.
Save trotha01/81a56d6cadd2b167831bdb1167001575 to your computer and use it in GitHub Desktop.
A fun python implementation of tic tac toe
"""
A fun answer to the question:
How would you determine if someone has won a game of tic-tac-toe on a board of any size?
Reference:
(https://www.glassdoor.com/Interview/How-would-you-determine-if-someone-has-won-a-game-of-tic-tac-toe-on-a-board-of-any-size-QTN_1104.htm)
This scales in a few ways
1. We can change the size of the board, we're not limited to 3x3
2. We can parallelize the computations
3. We can add players, we're not limited to X and O, just use a power of two
for the representation of each player on the board. However, we are limited
to 32/64/etc. players, depending on the machine in use.
Compiler
Since no conditionals are needed to find the winner, the compiler no longer
needs to do branch prediction. (Still need to run benchmarks)
"""
import operator
class tic_tac_toe(object):
def __init__(self, size=3):
self.size = size
self.reset()
self.positions_groups = (
[[(x, y) for y in range(size)] for x in range(size)] + # horizontals
[[(x, y) for x in range(size)] for y in range(size)] + # verticals
[[(d, d) for d in range(size)]] + # diagonal from top-left to bottom-right
[[(size-1-d, d) for d in range(size)]] # diagonal from top-right to bottom-left
)
def reset(self):
self.board = [[0]*self.size for _ in range(self.size)]
def play_x(self, x, y):
self.board[x][y] = 1
def play_o(self, x, y):
self.board[x][y] = 2
def check_win(self):
"""
check_win returns:
0 if no winners
1 if x won
2 if y won
"""
winner = 0
for positions in self.positions_groups:
values = [self.board[x][y] for (x, y) in positions]
winner |= reduce(operator.__and__, values, -1)
return winner
def view(self):
for row in self.board:
print row
# Testing check_win
#
# We just covering the basics, not full coverage
# since there are (p+1)^(n*n) possible end states (not accounting for symmetry),
# where p is the number of players, and n is the board_size
board_size = 4
no_win = 0
x_win = 1
y_win = 2
game = tictactoe(board_size)
# Test Empty
print game.check_win() == no_win
# Test Horizontals
for x in range(board_size):
game.reset()
[game.play_o(x,y) for y in range(board_size)]
print game.check_win() == y_win
game.reset()
[game.play_x(x,y) for y in range(board_size)]
print game.check_win() == x_win
# Test Verticals
for y in range(board_size):
game.reset()
[game.play_o(x,y) for x in range(board_size)]
print game.check_win() == y_win
game.reset()
[game.play_x(x,y) for x in range(board_size)]
print game.check_win() == x_win
# Test Diagonal top-left to bottom-right
game.reset()
[game.play_o(n,n) for n in range(board_size)]
print game.check_win() == y_win
game.reset()
[game.play_x(n,n) for n in range(board_size)]
print game.check_win() == x_win
# Test Diagonal top-right to bottom-left
game.reset()
[game.play_o(board_size-1-n,n) for n in range(board_size)]
print game.check_win() == y_win
game.reset()
[game.play_x(board_size-1-n,n) for n in range(board_size)]
print game.check_win() == x_win
# Spot Check Cats Game
game.reset()
[game.play_x(x,y) for x in range(board_size-1) for y in range(board_size-1)]
[game.play_o(n,n) for n in range(board_size)]
game.play_x(0,0)
print game.check_win() == no_win
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment