Created
February 5, 2018 17:46
-
-
Save andychu/e9f9d55b5d34b70a68bf38701ea24a9b to your computer and use it in GitHub Desktop.
Tic Tac Toe
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
from __future__ import print_function | |
""" | |
tictactoe.py | |
""" | |
import sys | |
def DrawBoard(board, f=sys.stdout): | |
"""Draw a tic-tac-toe board as ASCII art.""" | |
for x in range(3): | |
f.write('%d|' % x) | |
for y in range(3): | |
char = board[x, y] | |
f.write(char) | |
f.write('|') | |
f.write('\n') | |
print(' A B C') # to show the row | |
# Translate from user input to an integer index. | |
Y_COORD = {'A': 0, 'B': 1, 'C': 2} | |
def GetMove(board, name): | |
"""Prompt for and validate a 2-character move like '0A'.""" | |
while True: | |
move = raw_input('Player %s, enter a move (XY, e.g. 0A or 2C): ' % name) | |
move = move.strip() | |
if len(move) != 2: | |
print('Invalid move %r' % move) | |
continue | |
x_str = move[0] | |
y_str = move[1].upper() | |
if x_str not in '012' or y_str not in 'ABC': | |
print('Invalid move %r' % move) | |
continue | |
x = int(x_str) | |
y = Y_COORD[y_str] | |
if board[x, y] != ' ': | |
print("Position %r isn't empty" % move) | |
continue | |
return x, y | |
def CheckForWin(board, name): | |
"""Returns a string that describes the win, or None if no win.""" | |
for x in range(3): | |
if all(board[x, y] == name for y in range(3)): | |
return 'Player %s won in row %d!' % (name, x) | |
for y in range(3): | |
if all(board[x, y] == name for x in range(3)): | |
return 'Player %s won in column %d!' % (name, y) | |
if all(board[i, i] == name for i in range(3)): | |
return 'Player %s won on the left diagonal!' % name | |
if (board[0, 2] == name and | |
board[1, 1] == name and | |
board[2, 0] == name): | |
return 'Player %s won on the right diagonal!' % name | |
return None | |
def NewBoard(): | |
"""Initialize the board.""" | |
board = {} | |
for x in range(3): | |
for y in range(3): | |
board[x, y] = ' ' # empty | |
return board | |
def main(argv): | |
# Test() | |
# return | |
board = NewBoard() | |
while True: | |
# Player X | |
DrawBoard(board) | |
x, y = GetMove(board, 'x') | |
board[x, y] = 'x' | |
msg = CheckForWin(board, 'x') | |
if msg: | |
DrawBoard(board) | |
print(msg) | |
break | |
# Player O | |
DrawBoard(board) | |
x, y = GetMove(board, 'o') | |
board[x, y] = 'o' | |
msg = CheckForWin(board, 'o') | |
if msg: | |
DrawBoard(board) | |
print(msg) | |
break | |
print('GAME OVER') | |
def Test(): | |
board = NewBoard() | |
board[0, 0] = 'x' | |
board[0, 1] = 'x' | |
assert not CheckForWin(board, 'o') | |
assert not CheckForWin(board, 'x') | |
board[0, 2] = 'x' | |
DrawBoard(board) | |
assert CheckForWin(board, 'x') | |
board = NewBoard() | |
board[0, 1] = 'o' | |
board[1, 1] = 'o' | |
assert not CheckForWin(board, 'o') | |
assert not CheckForWin(board, 'x') | |
board[2, 1] = 'o' | |
DrawBoard(board) | |
assert CheckForWin(board, 'o') | |
board = NewBoard() | |
board[0, 0] = 'o' | |
board[1, 1] = 'o' | |
assert not CheckForWin(board, 'o') | |
assert not CheckForWin(board, 'x') | |
board[2, 2] = 'o' | |
DrawBoard(board) | |
assert CheckForWin(board, 'o') | |
board = NewBoard() | |
board[2, 0] = 'o' | |
board[1, 1] = 'o' | |
assert not CheckForWin(board, 'o') | |
assert not CheckForWin(board, 'x') | |
board[0, 2] = 'o' | |
DrawBoard(board) | |
assert CheckForWin(board, 'o') | |
if __name__ == '__main__': | |
main(sys.argv) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment