Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 76 additions & 44 deletions arcade/games/tictactoe.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Tic Tac Toe.

You are X, the computer is O. Squares are numbered 1-9 like a phone keypad:
You are X, the computer is O. Squares are numbered 1-9:

1 | 2 | 3
--+---+--
Expand All @@ -26,12 +26,12 @@
WINNING_LINES = [
(0, 1, 2),
(3, 4, 5),
(6, 7, 8), # rows
(6, 7, 8),
(0, 3, 6),
(1, 4, 7),
(2, 5, 8), # columns
(2, 5, 8),
(0, 4, 8),
(2, 4, 6), # diagonals
(2, 4, 6),
]


Expand All @@ -43,15 +43,13 @@ def new_board() -> list[str]:
def render(board: list[str]) -> str:
"""Draw the board as text.

Empty squares show their number, so the player can see what to type.

Args:
board: Nine squares, each "X", "O", or a space.

Returns:
A multi-line string ready to print.
Empty squares show their number so the player knows what to enter.
"""
cells = [board[i] if board[i] != EMPTY else str(i + 1) for i in range(9)]
cells = [
board[i] if board[i] != EMPTY else str(i + 1)
for i in range(9)
]

return (
f"\n {cells[0]} | {cells[1]} | {cells[2]}\n"
f" ---+---+---\n"
Expand All @@ -62,50 +60,41 @@ def render(board: list[str]) -> str:


def winner(board: list[str]) -> str | None:
"""Return the mark that has won, or None if nobody has yet.

Args:
board: The current board.

Returns:
"X", "O", or None.
"""
"""Return the winning mark, or None if there is no winner."""
for a, b, c in WINNING_LINES:
if board[a] != EMPTY and board[a] == board[b] == board[c]:
if (
board[a] != EMPTY
and board[a] == board[b]
and board[b] == board[c]
):
return board[a]

return None


def free_squares(board: list[str]) -> list[int]:
"""Return the indexes of every square that is still empty."""
return [i for i, cell in enumerate(board) if cell == EMPTY]
"""Return the indexes of all empty squares."""
return [
i for i, cell in enumerate(board)
if cell == EMPTY
]


def is_full(board: list[str]) -> bool:
"""Return True if there are no empty squares left."""
"""Return True if the board has no empty squares."""
return EMPTY not in board


def computer_move(board: list[str]) -> int:
"""Choose a square for the computer.

Currently picks at random from the free squares. There is an open issue to
make this cleverer if you fancy it.

Args:
board: The current board.

Returns:
The index of the square to play.
"""
"""Choose a random empty square for the computer."""
return random.choice(free_squares(board))


def play() -> int:
"""Run one game of Tic Tac Toe.

Returns:
100 points for a win, 0 otherwise.
100 points if the player wins, otherwise 0.
"""
print(art.banner("TIC TAC TOE"))
print(f"\n You are {PLAYER}. The computer is {COMPUTER}.")
Expand All @@ -114,27 +103,70 @@ def play() -> int:
result = None

while result is None and not is_full(board):

# Display current board
print(render(board))

# -----------------------------
# Player's move
# -----------------------------
while True:
choice = ask_int(" Your move (1-9):", minimum=1, maximum=9)
if board[choice - 1] == EMPTY:
board[choice - 1] = PLAYER
choice = ask_int(
" Your move (1-9): ",
minimum=1,
maximum=9
)

index = choice - 1

if board[index] == EMPTY:
board[index] = PLAYER
break
print(art.red(" That square is taken. Pick another."))

print(
art.red(
" That square is taken. Pick another."
)
)

# Check if player won
result = winner(board)
if result is not None or is_full(board):

if result is not None:
break

# Check for draw
if is_full(board):
break

# -----------------------------
# Computer's move
# -----------------------------
move = computer_move(board)
board[move] = COMPUTER
print(art.dim(f"\n Computer plays square {move + 1}."))

print(
art.dim(
f"\n Computer plays square {move + 1}."
)
)

# Check if computer won
result = winner(board)

# -----------------------------
# Game over
# -----------------------------
print(render(board))
print(f" {result} wins!\n")

if result == PLAYER:
print(" You win!\n")
return 100
return 0

elif result == COMPUTER:
print(" Computer wins!\n")
return 0

else:
print(" It's a draw!\n")
return 0
Loading