TicTacToe: Full Class Diagram Explained

Every class, relationship, and design pattern (Builder, Strategy, Factory) in the TicTacToe system explained from scratch.

April 27, 20263 min read4 / 9

A class diagram is the first real design artifact in a machine coding interview. Get it right, and the implementation flows naturally. Here is the complete TicTacToe diagram, built one decision at a time, incorporating all our requirements.

The Essentials

  1. Entities reflect the domain: Board, Cell, Player, Symbol, Move, and Game.
  2. Strategy Pattern for winning logic: Decouples the game from its winning conditions, making it extensible.
  3. Builder Pattern for Game: Handles complex validation (distinct symbols, N-1 players) before construction.
  4. Composition for Board and Cells: A board creates its own cells; they cannot exist without it.
  5. Polymorphism for Players: The game asks a Player to make a move, whether they are a human or a bot.

The Visual Map

TicTacToe Class Diagram ExpandTicTacToe Class Diagram

The Core Hierarchy: Board, Cell, and Symbol

Starting from the inside out:

  • Cell: Represents a single slot. It has a row, a col, and a CellStatus enum. If filled, it holds a reference to a Player.
  • Board: Composes a 2D list of Cell objects. It has a size.
  • Symbol: A wrapper around a character. Decoupling this from the player allows for future flexibility (like colored icons).

The Player Hierarchy: Human vs Bot

We use our abstract Player class as the base.

  • Human: A concrete subclass. Its makeMove will read from the console.
  • Bot: A concrete subclass. It has a BotPlayingStrategy (Association).
  • BotPlayingStrategy (Interface): Defines the move algorithm. A BotPlayingStrategyFactory returns the correct implementation based on a DifficultyLevel enum.

The Game Class: The Orchestrator

The Game class brings everything together. It coordinates the board, players, and winning logic.

  • Attributes: Board, List<Player>, currentPlayerIndex, List<Move>, List<WinningStrategy>, and GameStatus.
  • GameStatus: Tracks if the game is IN_PROGRESS, ENDED (Winner), or DRAW.

Pattern 1: The Strategy Pattern for Winners

One of our requirements was configurable winning conditions. If we put the winner-detection logic inside the Game class, we would have to modify it every time we added a new rule (like a corner win).

Instead, we use the Strategy Pattern:

  • Define a WinningStrategy interface with a checkWinner(Board, Move) method.
  • Implement specific strategies: RowWinningStrategy, ColumnWinningStrategy, DiagonalWinningStrategy.
  • The Game class holds a list of these interfaces. To check for a winner, it simply loops through them.

Pattern 2: The Builder Pattern for Validation

Creating a game requires validating several rules (e.g., uniqueness of symbols). Putting this in the Game constructor makes it messy. We use a Static Inner Builder:

  1. The builder gathers attributes.
  2. It runs a validate() method.
  3. If valid, it calls the private Game constructor.

This ensures that no invalid Game object ever exists.

Relationships in the Diagram

  • Game HAS-A Board: Composition (filled diamond).
  • Board HAS-A Cell: Composition (filled diamond).
  • Game HAS-A Player: Aggregation (empty diamond), because players exist outside the game.
  • Bot ISA Player: Inheritance (arrow).
  • Bot HAS-A BotPlayingStrategy: Association.

Translating the Diagram to Code

Here is how we translate the Player hierarchy and the Strategy interface into working code:

// Player Hierarchy abstract class Player { name: string; symbol: Symbol; abstract makeMove(board: Board): Move; } class Bot extends Player { difficulty: Difficulty; playingStrategy: BotPlayingStrategy; makeMove(board: Board): Move { return this.playingStrategy.makeMove(board); } } // Strategy Interface interface WinningStrategy { checkWin(board: Board, move: Move): boolean; }

The class diagram is our map. In the next post, we will look at how to implement the logic for undoing moves.

Further Reading and Watching

Practice what you just read.

TicTacToe Entities & Patterns
1 exercise