Skip to content

Instantly share code, notes, and snippets.

@SteveDaulton
Last active April 2, 2024 15:35
Show Gist options
  • Save SteveDaulton/db4c67b82d5ed1db36b93398cc57f9d1 to your computer and use it in GitHub Desktop.
Save SteveDaulton/db4c67b82d5ed1db36b93398cc57f9d1 to your computer and use it in GitHub Desktop.
Tic-Tac-Toe
"""Tic-Tac-Toe
A simple implementation in (mostly) procedural style.
"""
import sys
from random import choice
from typing import TypeAlias
Board: TypeAlias = list[list[str]]
def display_board(grid: Board) -> None:
"""Display the board."""
print(" 1 2 3")
for row_num, row in enumerate(grid):
print(row_num + 1, end='')
for cell in row:
print(f"[{cell}]", end='')
print()
print()
def get_empty_cells(grid: Board) -> list[tuple[int, int]]:
"""Return list of empty cell coordinates."""
return [(r_idx, c_idx) for r_idx, row in enumerate(grid)
for c_idx, char in enumerate(row)
if char == '_']
def player_turn(grid: Board, char: str) -> None:
"""Add player's move to the board."""
empty_cells = get_empty_cells(grid)
input_requested = False
while True:
if input_requested:
print("Invalid choice.")
print("Enter row and column as numbers in range 1 to 3.")
coords = input("row column: ").strip()
input_requested = True
if len(coords) == 2: # No space
try:
row = int(coords[0]) - 1
col = int(coords[1]) - 1
except ValueError:
continue
else:
try:
row, col = [int(val) - 1 for val in coords.split()]
except ValueError:
continue
if (row, col) in empty_cells:
grid[row][col] = char
return
def pc_turn(grid: Board, char: str) -> None:
"""Add computer's move to the board."""
row, col = choice(get_empty_cells(grid))
grid[row][col] = char.upper()
def is_winner(grid: Board, char: str) -> bool:
"""Return True if 'char' (O or X) has won, else False."""
cols = [[row[col] for row in grid] for col in range(3)]
diag1 = [[grid[i][i] for i in range(3)]]
diag2 = [[grid[i][2 - i] for i in range(3)]]
all_lines = grid + cols + diag1 + diag2
return [char, char, char] in all_lines
def main() -> None:
"""Main game loop."""
board = [['_' for _ in range(3)] for _ in range(3)]
players = ('O', 'X')
player = choice(players)
pc = 'X' if player == 'O' else 'O'
print("Let's play Tic-Tac-Toe.")
print(f"You are {player}'s")
print("\nSelect your position as \"row column\", where")
print("row and column are numbers 1 to 3.\n")
while get_empty_cells(board):
pc_turn(board, pc)
display_board(board)
if is_winner(board, pc):
print("You lost")
return
if not get_empty_cells(board):
break
player_turn(board, player)
display_board(board)
if is_winner(board, player):
print("You won")
return
print("Draw")
if __name__ == '__main__':
try:
main()
except (KeyboardInterrupt, EOFError):
sys.exit("Bye")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment