Skip to content

Instantly share code, notes, and snippets.

@lwiecek
Created September 12, 2014 19:57
Show Gist options
  • Save lwiecek/af4b9e2d2584e429b7de to your computer and use it in GitHub Desktop.
Save lwiecek/af4b9e2d2584e429b7de to your computer and use it in GitHub Desktop.
import random
class Game(object):
N = 3
def __init__(self, ai=None):
self.board = []
for i in range(Game.N):
self.board.append([' '] * Game.N)
self.current_player = 'X'
self.ai = ai
self.moves = 0
self.game_over = None
self.show_board()
self.check_ai_move()
def show_board(self):
human = ('(human)' if self.is_current_player_human() else '')
print 'current player:', self.current_player, human
for row in range(Game.N):
for col in range(Game.N):
print '[' + self.board[row][col] + ']',
print
def move_is_allowed(self, row, col, player):
return (
(not self.game_over) and
(row >= 0 and col >= 0 and row < Game.N and col < Game.N) and
(self.board[row][col] == ' ') and (self.current_player == player)
)
def play(self, row, col, player):
self.moves += 1
if not self.move_is_allowed(row, col, player):
print player, 'move ( row: ', row, ', col', col, ') is not allowed.'
return
self.board[row][col] = player.upper()
self.show_board()
game_over = self.check_game_over()
if game_over:
print 'game over:', game_over
self.game_over = game_over
return
self.switch_player()
self.check_ai_move()
def switch_player(self):
self.current_player = 'O' if self.current_player == 'X' else 'X'
def is_current_player_human(self):
return (not self.ai) or (self.current_player not in self.ai)
def check_ai_move(self):
if self.is_current_player_human():
return
while True:
row, col = random.randint(0, Game.N - 1), random.randint(0, Game.N - 1)
if self.move_is_allowed(row, col, self.current_player):
self.play(row, col, self.current_player)
break
def check_game_over(self):
checks = []
for row in range(Game.N):
checks.append((row * Game.N, 1))
for col in range(Game.N):
checks.append((col, Game.N))
checks.append((0, Game.N + 1)) # diag left-top -> right-bottom
checks.append((Game.N - 1, Game.N - 1)) # diag right-top -> left-bottom
for start, offset in checks:
winner = self.check_line(start, offset)
if winner:
return winner + ' won'
if self.moves == Game.N * Game.N:
return 'draw'
return None
# row: offset = 1, col: offset = N, diag: offset = N + 1, offset = N - 1
def check_line(self, start, offset):
pos = start
count_x = 0
count_o = 0
for i in range(Game.N):
row = pos / Game.N
col = pos % Game.N
pos += offset
count_x += int(self.board[row][col] == 'X')
count_o += int(self.board[row][col] == 'O')
if count_x == Game.N:
return 'X'
if count_o == Game.N:
return 'O'
return None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment