Skip to content

Instantly share code, notes, and snippets.

@xvedejas
Created March 30, 2015 15:46
Show Gist options
  • Save xvedejas/2ed29712779b09addf63 to your computer and use it in GitHub Desktop.
Save xvedejas/2ed29712779b09addf63 to your computer and use it in GitHub Desktop.
#!/usr/bin/python3
class TicTacToeGame():
def __init__(self):
# Our game state is defined by a list of 3 lists, each containing 3
# characters, which can be either ' ' (blank), an 'X', or an 'O'.
self.state = [[' ', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']]
self.next_turn_player = 'X'
def do_move(self, index):
"""
Plays a move at the given index (beginning with 1 in the top-left).
"""
# Correct to zero-indexing
index -= 1
# Make sure the move index is not out of bounds
if index >= 9 or index < 0:
raise IndexError
# Find the row/column
row = index // 3
col = index % 3
# Make sure the position hasn't been played yet
if self.state[row][col] != ' ':
raise ValueError
# Make the move
self.state[row][col] = self.next_turn_player
# Update the player expected for next turn
self.next_turn_player = ('O' if self.next_turn_player == 'X' else 'X')
def __repr__(self):
"""
Returns the representation of the game state as a string, which looks
like this:
1 |2 |3
| |
--------
4 |\/|6
|/\|
--------
7 |/\|9
|\/|
"""
representation = []
i = 0
for row in self.state:
upper_halves = []
lower_halves = []
for item in row:
i += 1
if item == 'X':
upper_halves.append('\\/')
lower_halves.append('/\\')
elif item == 'O':
upper_halves.append('/\\')
lower_halves.append('\\/')
else:
upper_halves.append('%i ' % i)
lower_halves.append(' ')
representation += ['|'.join(upper_halves) + '\n' +
'|'.join(lower_halves) + '\n']
return '--------\n'.join(representation)
def check_game_end(self):
"""Checks the game state to see if the game is over, either by virtue of
someone winning or because all spaces are filled."""
# Assume the board is filled until contrary evidence
filled = True
for row in self.state:
if ' ' in row:
filled = False
break
# If there is a winner, then one of the following sets of indices in
# our game state will all be the same value:
wins = (# Horizontal wins:
(0, 1, 2),
(3, 4, 5),
(6, 7, 8),
# Vertical wins:
(0, 3, 6),
(1, 4, 7),
(2, 5, 8),
# Diagonal wins:
(0, 4, 8),
(2, 4, 6))
for win in wins:
i, j, k = win
a, b, c = (self.state[i // 3][i % 3],
self.state[j // 3][j % 3],
self.state[k // 3][k % 3])
if a == b and b == c and a != ' ':
return a
return filled
def play_2p_game(self):
"""
Two-Player Interactive Game
This method creates a loop which waits for input from the command line.
After each move is played, it shows the new state of the game. This
continues until the game is over.
"""
print(self)
while True:
index = input('Player %s move: ' % self.next_turn_player)
try:
self.do_move(int(index))
except TypeError:
print('Expected a position number')
except IndexError:
print('Position out of range')
except ValueError:
print('Position already played')
else:
print(self)
end_state = self.check_game_end()
if end_state == True:
print('Tied game.')
break
elif end_state:
print('Player %s wins!' % end_state)
break
def play_1p_game(self):
"""
One-Player Interactive Game
Like the two-player game, except now we play against an AI.
"""
pass
ttt = TicTacToeGame()
ttt.play_2p_game()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment