Navigate to the Notebook
Open the tic-tac-toe notebook file:
_notebooks/Foundation/F-projects/2025-08-18-tictactoe-game.ipynb
You can do this by using VSCode's file explorer
Set Up Virtual Environment
Run the virtual environment setup script:
./scripts/venv.sh
This script will:
- Create or activate your Python virtual environment
- Install necessary packages
- Prepare your environment for running Jupyter notebooks
⚠️ Important
Make sure you're in your project root directory when running this command!
Select the Correct Kernel
In VS Code or Jupyter, select your virtual environment kernel:
- Click on "Select Kernel" (usually in the top-right of the notebook)
- Choose "Python Environments"
- Select your venv kernel from the list
💡 Pro Tip
The kernel should show your venv path, not system Python!
Run the Game
Execute the code cells to start playing:
- Click the play button next to each cell
- Follow the game prompts in the output
🎉 Success!
You're ready to play! Choose positions 1-9 to make your moves.
Troubleshooting
Common Issues
If the game doesn't run, check that you've selected the correct venv kernel and that all packages are installed in your virtual environment.
class Player:
def __init__(self, name, symbol):
self.name = name
self.symbol = symbol
self.wins = 0
self.losses = 0
self.ties = 0
def add_win(self):
self.wins += 1
def add_loss(self):
self.losses += 1
def add_tie(self):
self.ties += 1
def get_stats(self):
total_games = self.wins + self.losses + self.ties
if total_games == 0:
return f"{self.name}: No games played"
win_rate = (self.wins / total_games) * 100
return f"{self.name}: {self.wins}W-{self.losses}L-{self.ties}T ({win_rate:.1f}% win rate)"
class Board:
def __init__(self, size=3):
self.size = size
self.grid = [" "] * (size * size)
def display(self):
print("\n")
for row in range(self.size):
row_str = " "
for col in range(self.size):
index = row * self.size + col
row_str += self.grid[index]
if col < self.size - 1:
row_str += " | "
print(row_str)
if row < self.size - 1:
separator = "---" + "+---" * (self.size - 1)
print(separator)
print("\n")
def display_reference(self):
print("Board positions:\n")
for row in range(self.size):
row_str = " "
for col in range(self.size):
position = row * self.size + col + 1
row_str += str(position).rjust(2)
if col < self.size - 1:
row_str += " |"
print(row_str)
if row < self.size - 1:
separator = "----" + "+----" * (self.size - 1)
print(separator)
print("\n")
def is_full(self):
return " " not in self.grid
def make_move(self, position, symbol):
index = position - 1
if index < 0 or index >= len(self.grid):
print(f"Invalid position. Choose a number between 1 and {len(self.grid)}.")
return False
if self.grid[index] != " ":
print("That spot is already taken. Try again.")
return False
self.grid[index] = symbol
return True
def check_winner(self, symbol):
# Check rows
for row in range(self.size):
if all(self.grid[row * self.size + col] == symbol for col in range(self.size)):
return True
# Check columns
for col in range(self.size):
if all(self.grid[row * self.size + col] == symbol for row in range(self.size)):
return True
# Check main diagonal (top-left to bottom-right)
if all(self.grid[i * self.size + i] == symbol for i in range(self.size)):
return True
# Check anti-diagonal (top-right to bottom-left)
if all(self.grid[i * self.size + (self.size - 1 - i)] == symbol for i in range(self.size)):
return True
return False
class TicTacToe:
def __init__(self, player1, player2, board_size=3):
self.board = Board(board_size)
self.players = [player1, player2]
self.current_player = player1
self.board_size = board_size
self.game_number = 1
def switch_player(self):
self.current_player = (
self.players[1] if self.current_player == self.players[0]
else self.players[0]
)
def display_scores(self):
print("\n" + "="*50)
print("CURRENT SCORES:")
print("="*50)
for player in self.players:
print(player.get_stats())
print("="*50 + "\n")
def reset_board(self):
self.board = Board(self.board_size)
self.current_player = self.players[0] # Reset to player 1
def play_single_game(self):
print(f"\n--- GAME {self.game_number} ---")
print(f"Welcome to {self.board_size}x{self.board_size} Tic-Tac-Toe!")
print(f"{self.players[0].name} is '{self.players[0].symbol}'")
print(f"{self.players[1].name} is '{self.players[1].symbol}'")
print(f"Players take turns choosing a position (1–{self.board_size * self.board_size}).\n")
self.board.display_reference()
self.board.display()
while True:
try:
max_position = self.board_size * self.board_size
move = int(input(f"{self.current_player.name} ({self.current_player.symbol}), enter your move (1-{max_position}): "))
except ValueError:
print(f"Invalid input. Please enter a number from 1 to {self.board_size * self.board_size}.")
continue
if not self.board.make_move(move, self.current_player.symbol):
continue
self.board.display()
if self.board.check_winner(self.current_player.symbol):
print(f"{self.current_player.name} ({self.current_player.symbol}) wins!")
# Update scores
self.current_player.add_win()
other_player = self.players[1] if self.current_player == self.players[0] else self.players[0]
other_player.add_loss()
return "win"
if self.board.is_full():
print("It's a tie!")
# Update scores for both players
for player in self.players:
player.add_tie()
return "tie"
self.switch_player()
def play(self):
print("Welcome to Enhanced Tic-Tac-Toe with Score Tracking!")
while True:
# Play a single game
result = self.play_single_game()
self.game_number += 1
# Display updated scores
self.display_scores()
# Ask if players want to continue
while True:
choice = input("Play another game? (y/n): ").lower().strip()
if choice in ['y', 'yes']:
self.reset_board()
break
elif choice in ['n', 'no']:
print("\nFinal Scores:")
self.display_scores()
print("Thanks for playing!")
return
else:
print("Please enter 'y' for yes or 'n' for no.")
def get_player_names():
print("Player Setup")
player1_name = ""
while not player1_name:
try:
player1_name = input("Enter Player 1 name (X): ").strip()
if not player1_name:
player1_name = "Player 1"
except:
player1_name = "Player 1"
player2_name = ""
while not player2_name:
try:
player2_name = input("Enter Player 2 name (O): ").strip()
if not player2_name:
player2_name = "Player 2"
except:
player2_name = "Player 2"
return player1_name, player2_name
def get_board_size():
while True:
try:
user_input = input("Enter board size (3 for 3x3, 4 for 4x4, etc.): ")
user_input = user_input.strip()
# Skip if empty input
if not user_input:
print("Please enter a number.")
continue
size = int(user_input)
if size < 3:
print("Board size must be at least 3x3.")
continue
if size > 10:
print("Board size too large. Maximum is 10x10.")
continue
return size
except ValueError:
print("Invalid input. Please enter a number.")
except:
print("Please enter a number.")
def show_menu():
print("\nGAME MENU")
print("1. Start new game session")
print("2. View current scores")
while True:
try:
choice = input("Choose an option (1-2): ")
choice = choice.strip()
if choice == "1" or choice == "2":
return choice
elif not choice:
print("Please enter 1 or 2.")
continue
else:
print("Invalid option. Please choose 1-2.")
except:
print("Please enter 1 or 2.")
if __name__ == "__main__":
print("Enhanced Tic-Tac-Toe with Score Tracking!\n")
# Get player names
player1_name, player2_name = get_player_names()
player1 = Player(player1_name, "X")
player2 = Player(player2_name, "O")
# Get board size
board_size = get_board_size()
# Create game instance
game = TicTacToe(player1, player2, board_size)
choice = show_menu()
if choice == "1":
game.play()
elif choice == "2":
game.display_scores()
Enhanced Tic-Tac-Toe with Score Tracking!
Player Setup
GAME MENU
1. Start new game session
2. View current scores
Welcome to Enhanced Tic-Tac-Toe with Score Tracking!
--- GAME 1 ---
Welcome to 3x3 Tic-Tac-Toe!
bob is 'X'
ross is 'O'
Players take turns choosing a position (1–9).
Board positions:
1 | 2 | 3
----+----+----
4 | 5 | 6
----+----+----
7 | 8 | 9
| |
---+---+---
| |
---+---+---
| |
X | |
---+---+---
| |
---+---+---
| |
X | O |
---+---+---
| |
---+---+---
| |
X | O |
---+---+---
X | |
---+---+---
| |
X | O |
---+---+---
X | O |
---+---+---
| |
X | O |
---+---+---
X | O |
---+---+---
X | |
bob (X) wins!
==================================================
CURRENT SCORES:
==================================================
bob: 1W-0L-0T (100.0% win rate)
ross: 0W-1L-0T (0.0% win rate)
==================================================
Final Scores:
==================================================
CURRENT SCORES:
==================================================
bob: 1W-0L-0T (100.0% win rate)
ross: 0W-1L-0T (0.0% win rate)
==================================================
Thanks for playing!