Skip to content
Low Level Design Mastery Logo
LowLevelDesign Mastery

Designing a Tic Tac Toe Game

Design a Tic Tac Toe game that allows two players to play on a 3x3 grid.

Design a Tic Tac Toe game that allows two players to play on a 3x3 grid. Players take turns placing their symbols (X or O) in empty cells. The game should detect wins (three in a row horizontally, vertically, or diagonally) and handle draws when all cells are filled.

In this problem, you’ll design a system that manages player turns, validates moves on a shared board, and identifies the exact moment a player wins or the game ends in a draw.


Design a two-player game played on a 3x3 grid where players alternate placing their symbols (X and O) until one wins or the board is full.

Functional Requirements:

  • Standard Grid: Play on a classic 3x3 board.
  • Two Players: Support two players taking turns with ‘X’ and ‘O’ symbols.
  • Win Detection: Identify when a player has three symbols in a row (horizontal, vertical, or diagonal).
  • Draw Handling: Detect when all cells are filled without a winner.
  • Move Validation: Reject invalid moves (e.g., occupied cells) and notify the player.
  • Scoreboard: Keep track of scores/wins across multiple games.
  • Demo Mode: Support predefined moves for flow demonstration.

Non-Functional Requirements:

  • Object-Oriented Design: Clear separation between Game, Board, Cell, and Player.
  • Modularity: Easy to extend for larger boards (N x N) or AI opponents.
  • Testability: Core game logic should be easy to understand and unit test.
  • Readable Output: Display the current state of the board clearly after each move.

The system coordinates between the Game controller, the Board, and the Players.

Diagram
classDiagram
    class Game {
        -Board board
        -Player[] players
        -int turn
        -GameStatus status
        +makeMove(row, col)
        +checkWinner()
    }
    
    class Board {
        -Cell[][] grid
        -int size
        +isFull()
        +setCellValue(row, col, symbol)
    }
    
    class Player {
        -String name
        -Symbol symbol
    }

    Game --> Board
    Game o-- Player
    Board *-- Cell

Diagram

Checking every row, column, and diagonal after every move (using nested loops) is $O(N^2)$. While fine for 3x3, it’s inefficient for 1000x1000.

Solution: Use Counter-based tracking. Maintain arrays rows[] and cols[] and two variables for diagonals. When a player moves at (r, c), increment the count for that row and column. If the count reaches $N$, you have a winner. This reduces detection to $O(1)$.

The game logic should not be tied to a fixed 3x3 array.

Solution: Encapsulate the grid in a Board class. Provide methods like isValidMove(r, c) and setCellValue(r, c, val). This allows you to change the underlying storage (e.g., from a 2D array to a Map for sparse boards) without affecting the Game controller.

Hardcoding ‘X’ and ‘O’ in the logic makes it hard to support more players or custom symbols.

Solution: Use an Enum or a Player Class. The game logic should check if player.getSymbol() matches across a row, rather than checking specifically for the character ‘X’.


By solving this problem, you’ll master:

  • State Management - Handling game lifecycles and transitions.
  • Algorithmic Optimization - Turning $O(N^2)$ checks into $O(1)$ updates.
  • Grid Logic - Modeling and traversing 2D spatial structures.
  • Clean Code - Separating rule enforcement from data representation.

Ready to see the full implementation? Open the interactive playground to access:

  • 🎯 Step-by-step guidance through the 8-step LLD approach
  • 📊 Interactive UML builder to visualize your design
  • 💻 Complete Code Solutions in Python, Java, C++, TypeScript, JavaScript, C#
  • 🤖 AI-powered review of your design and code

After mastering Tic Tac Toe, try these similar problems: