THN Interview Prep

Design Tic-Tac-Toe (LLD)

1. Requirements

  • Functional

    • NxN grid (classic 3x3) with two marks alternating; win by line of length matching rule set.
    • Reject illegal moves (occupied cell, play after terminal state).
    • Expose current player and game outcome: win, draw, in progress.
  • Non-Functional

    • O(1) move application; optional O(n) win check on small boards acceptable.
    • Extensible to M,N,K generalized tic-tac-toe.
  • Assumptions / Out of Scope

    • No AI in core domain; AI via separate player agent.

2. Core Entities

EntityResponsibilityKey Attributes
GameControls flowgrid, currentMark, status
BoardCell storagerows, columns, cells
MoveRow and column choicerowIndex, columnIndex
WinCheckerEvaluates lineswinLength
MarkSide enumerationcross, nought

3. Class Diagram

Loading diagram…

4. State / Sequence Diagram (where relevant)

Loading diagram…

5. Design Patterns Applied

  • State — Game lifecycle (InProgress, Won, Draw). State pattern.
  • Null Object — Empty cell representation vs optional pointers. See the design patterns index; Null Object is not a standalone note here.

6. Implementation

Go

package tictactoe

type Mark int

type Board struct {
    Rows, Columns int
    Cells         [][]Mark
}

type Move struct {
    RowIndex, ColumnIndex int
}

type Game struct {
    Board      Board
    Current    Mark
    Status     string
    WinLength  int
}

func (game *Game) PlayMove(move Move) error { /* bounds, occupancy, terminal */ }

JavaScript

const Mark = { Empty: 0, Cross: 1, Nought: 2 };

class Board {
  constructor({ rows, columns }) {
    this.rows = rows;
    this.columns = columns;
    this.cells = Array.from({ length: rows }, () =>
      Array(columns).fill(Mark.Empty)
    );
  }
}

class Game {
  constructor({ rows, columns, winLength }) {
    this.board = new Board({ rows, columns });
    this.winLength = winLength;
    this.currentMark = Mark.Cross;
    this.status = 'inProgress';
  }
  playMove({ rowIndex, columnIndex }) { /* ... */ }
}

7. Concurrency / Thread Safety

  • Collisions: Two clicks submitting move simultaneously on web UI.
  • Granularity: Debounce in UI; server uses per-game lock or actor mailbox.
  • Go: sync.Mutex on Game if referenced by multiple handlers.

8. Extensibility & Followups

  • Bitmask board for fast win masks on 3x3.
  • Generalized K-in-a-row on larger grids with directional sweep from last move only.
  • Undo stack via small command list.
  • Edge cases: mis-sized winLength greater than board dimensions.

Last updated on

Spotted something unclear or wrong on this page?

On this page