Last active
July 19, 2022 19:04
-
-
Save PiotrJander/115c4dba96a11ccbd5bacb98ce597519 to your computer and use it in GitHub Desktop.
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
## helper functions | |
""" | |
Constructs a board from a string. | |
s: a string representation of the board | |
Returns: a parsed board | |
E.g.: | |
b("X__|_O_|__X") | |
will produce | |
X | | | |
| O | | |
| | X | |
""" | |
def b(s): | |
string_rows = s.split("|") | |
rows = [] | |
for string_row in string_rows: | |
rows.append([None if char == "_" else char for char in list(string_row)]) | |
return rows | |
""" | |
Stringifies a board. | |
board: a 3x3 array | |
Returns: a string representing the board | |
E.g. when `board` is | |
X | | | |
| O | | |
| | X | |
s(board) will produce "X__|_O_|__X" | |
""" | |
def s(board): | |
rows = [] | |
for row in board: | |
rows.append("".join(["_" if cell is None else cell for cell in row])) | |
return "|".join(rows) | |
# actual program | |
def _repr_cell(cell): | |
return " " if cell is None else cell | |
def _print_row(row): | |
print(f"{_repr_cell(row[0])} | {_repr_cell(row[1])} | {_repr_cell(row[2])}") | |
def _print_row_delimiter(): | |
print("--+---+---") | |
def print_board(board): | |
"""Print a pretty representation of the given board state. | |
board: a 3x3 array of X/O/None | |
""" | |
_print_row(board[0]) | |
_print_row_delimiter() | |
_print_row(board[1]) | |
_print_row_delimiter() | |
_print_row(board[2]) | |
def is_won(board, player): | |
"""Checks if the board is won for the given player. | |
board: a 3x3 array | |
player: X or O | |
Returns: boolean | |
>>> is_won(b('XXX|OO_|_OO'), 'X') | |
True | |
>>> is_won(b('XXX|OO_|_OO'), 'O') | |
False | |
""" | |
return (board[0][0] == board[1][1] == board[2][2] == player | |
or board[0][2] == board[1][1] == board[2][0] == player | |
or board[0][0] == board[0][1] == board[0][2] == player | |
or board[1][0] == board[1][1] == board[1][2] == player | |
or board[2][0] == board[2][1] == board[2][2] == player | |
or board[0][0] == board[1][0] == board[2][0] == player | |
or board[0][1] == board[1][1] == board[2][1] == player | |
or board[0][2] == board[1][2] == board[2][2] == player) | |
def is_draw(board): | |
for row in board: | |
for cell in row: | |
if cell is None: | |
return False | |
else: | |
return True | |
def read_coordinate(prompt): | |
"""Reads and validates a coordinate from user's input. | |
E.g. | |
`read_coordinate("X's turn. Please choose row: ")` | |
would print | |
`X's turn. Please choose row: _` | |
and then read user's input. | |
""" | |
while True: | |
coor = int(input(prompt)) | |
if coor == 0 or coor == 1 or coor == 2: | |
return coor | |
else: | |
print("The coordinate must be a number: 0 or 1 or 2") | |
def read_coordinates(player): | |
"""Reads and validates row and column coordinates from user's input. | |
E.g. | |
`read_coordinates('O')` | |
would print and read | |
`O's turn. Please choose row: _` | |
and then | |
`O's turn. Please choose column: _` | |
""" | |
x = read_coordinate(f"{player}'s turn. Please choose row: ") | |
y = read_coordinate(f"{player}'s turn. Please choose column: ") | |
return x, y | |
def play_turn(board, player): | |
"""Plays a turn. Reads a valid user input and checks whether user won | |
after the turn. | |
board: a 3x3 array of X/O/None | |
player: X or O | |
Returns: boolean, true when player won after this turn | |
""" | |
while True: | |
print_board(board) | |
x, y = read_coordinates(player) | |
if board[x][y] is None: | |
board[x][y] = player | |
break | |
else: | |
print("The cell is taken. Please choose a free cell.") | |
return is_won(board, player) | |
def play(): | |
"""Plays a game of Tic-Tac-Toe""" | |
board = [[None] * 3 for _ in range(3)] | |
while True: | |
x_won = play_turn(board, 'X') | |
if x_won: | |
print("X wins!") | |
print_board(board) | |
break | |
if is_draw(board): | |
print('Draw!') | |
break; | |
o_won = play_turn(board, 'O') | |
if o_won: | |
print("O wins!") | |
print_board(board) | |
break | |
if is_draw(board): | |
print('Draw!') | |
break; | |
if __name__ == "__main__": | |
import doctest | |
doctest.testmod() | |
play() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment