Python Tic Tac Toe Jupyter Notebook Lesson
Jupyter Notebook Guide
1. What is a Jupyter Notebook?
A Jupyter notebook is an interactive document that combines code, text, and output in a single file. It’s made up of cells that can contain different types of content.
Cell Types Example:
Cell 1 - Frontmatter (Metadata) [Raw Cell]
---
title: Python Tic Tac Toe Game
comments: false
layout: post
permalink: /games/tictactoe
author: Mihir Bapat, Yash Parikh, Ansh Kumar
---
Raw cells contain plain text that isn’t processed as code or markdown. Here, it contains frontmatter - special metadata that tells our website generator how to display this page.
Cell 2 - Documentation [Markdown Cell]
Markdown cells let you write formatted text, like this explanation. You can include headings, lists, links, and more!
This is where you’d typically explain what your code does.
Cell 3 - Code [Python Cell]
def print_board(board):
print("\n")
print(" " + board[0] + " | " + board[1] + " | " + board[2])
print("---+---+---")
print(" " + board[3] + " | " + board[4] + " | " + board[5])
print("---+---+---")
print(" " + board[6] + " | " + board[7] + " | " + board[8])
print("\n")
# This is your actual tic-tac-toe game code!
Code cells contain executable Python code. When you run these cells, the output appears below them.
2. How to Run the Code Cells
Before we can execute our tic-tac-toe code, we need to set up our environment properly. We’ll be doing a live demo of this process!
Environment Setup Steps:
- Virtual Environment (venv): You must be working inside a Python virtual environment that has all your required packages installed
- Kernel Selection: In VS Code, select your venv kernel from the kernel picker in the top-right of the notebook
- Module Availability: Modules like
nbconvert
must be installed in your selected venv to work properly - Running Cells: Use Shift+Enter or the play button to execute code cells
# Check if you're in the right environment
import sys
print(f"Python path: {sys.executable}")
# This should show your venv path, not system Python!
⚠️ Common Issue
If your code cells aren’t running or modules aren’t found, check that you’ve selected the correct kernel that matches your virtual environment!
3. Understanding Frontmatter
Frontmatter is metadata written in YAML format at the top of your notebook. It tells your website how to process and display the content.
What each frontmatter field means:
- title: The page title that appears in browsers and search results
- comments: Whether to enable comments on the webpage (true/false)
- layout: Which HTML template to use for styling the page
- permalink: The custom URL path where the page will be accessible
- author: Who created this content
4. From Notebook to Website
Here’s how your Jupyter notebook becomes a live webpage using the nbconvert module:
📓 Jupyter Notebook (Your .ipynb file with cells) → 🔄 nbconvert (Processes and converts) → 🌐 Web Page (HTML in _posts directory)
What nbconvert does:
- Reads your notebook: Parses the .ipynb file structure
- Processes frontmatter: Extracts metadata for website generation
- Converts cells: Turns code/markdown cells into HTML
- Applies styling: Uses CSS to make it look good on the web
- Saves to _posts: Places the HTML file where your website can find it
# Basic nbconvert command
jupyter nbconvert --to html your_notebook.ipynb
# With custom template for your website
jupyter nbconvert --to html --template=custom your_notebook.ipynb
5. The Complete Workflow
👨💻 Developer Workflow:
- Create notebook: Write your tic-tac-toe game in Jupyter
- Add frontmatter: Include metadata in a raw cell
- Run nbconvert: Convert notebook to HTML
- Website displays: Your game appears at /games/tictactoe
✨ Key Takeaways
Remember these important concepts:
- Jupyter notebooks combine code, documentation, and output in one file
- Frontmatter provides metadata that controls how your page appears on the web
- nbconvert is the bridge between notebooks and websites
- Cell types (Raw, Markdown, Code) serve different purposes
- The _posts directory is where your converted HTML files live
class Player:
def __init__(self, name, symbol):
self.name = name
self.symbol = symbol
class Board:
def __init__(self):
self.grid = [" "] * 9
def display(self):
print("\n")
print(" " + self.grid[0] + " | " + self.grid[1] + " | " + self.grid[2])
print("---+---+---")
print(" " + self.grid[3] + " | " + self.grid[4] + " | " + self.grid[5])
print("---+---+---")
print(" " + self.grid[6] + " | " + self.grid[7] + " | " + self.grid[8])
print("\n")
def display_reference(self):
reference = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
print("Board positions:\n")
print("\n")
print(" " + reference[0] + " | " + reference[1] + " | " + reference[2])
print("---+---+---")
print(" " + reference[3] + " | " + reference[4] + " | " + reference[5])
print("---+---+---")
print(" " + reference[6] + " | " + reference[7] + " | " + reference[8])
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 > 8:
print("Invalid position. Choose a number between 1 and 9.")
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):
win_combinations = [
[0, 1, 2], [3, 4, 5], [6, 7, 8], # Rows
[0, 3, 6], [1, 4, 7], [2, 5, 8], # Columns
[0, 4, 8], [2, 4, 6] # Diagonals
]
for combo in win_combinations:
if (self.grid[combo[0]] == symbol and
self.grid[combo[1]] == symbol and
self.grid[combo[2]] == symbol):
return True
return False
class TicTacToe:
def __init__(self, player1, player2):
self.board = Board()
self.players = [player1, player2]
self.current_player = player1
def switch_player(self):
self.current_player = (
self.players[1] if self.current_player == self.players[0] else self.players[0]
)
def play(self):
print("Welcome to 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("Players take turns choosing a position (1–9).\n")
self.board.display_reference()
self.board.display()
while True:
try:
move = int(input(f"{self.current_player.name} ({self.current_player.symbol}), enter your move (1-9): "))
except ValueError:
print("Invalid input. Please enter a number from 1 to 9.")
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!")
break
if self.board.is_full():
print("It's a tie!")
break
self.switch_player()
if __name__ == "__main__":
player1 = Player("Player 1", "X")
player2 = Player("Player 2", "O")
game = TicTacToe(player1, player2)
game.play()
🗂️ Flashcards
What is a Jupyter Notebook?
Answer:
An interactive document that combines code, text, and output in a single file, made up of cells that can contain different types of content
🖥️ Try It Yourself
📝 Quick Check
What did you learn?