1What 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.

Raw Cell 1 - Frontmatter (Metadata)
--- 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.

Markdown Cell 2 - Documentation

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.

Python Cell 3 - Code
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.

2How 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:

# 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!

3Understanding 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:

4From 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:

# 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

5The Complete Workflow

👨‍💻 Developer Workflow:

  1. Create notebook: Write your tic-tac-toe game in Jupyter
  2. Add frontmatter: Include metadata in a raw cell
  3. Run nbconvert: Convert notebook to HTML
  4. Website displays: Your game appears at /games/tictactoe

Key Takeaways

Remember these important concepts:

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()