System Design
Object-Oriented Design
Chess Game

Design Example: Chess Game

Chess is a landmark OOD challenge due to its complex inheritance hierarchy, variety of move rules (castling, en-passant), and game state tracking (check, checkmate).


Step 1: Requirements Gathering

Core Use Cases:

  • Two players (Black and White).
  • 16 pieces per player (King, Queen, Rook, Bishop, Knight, Pawn).
  • Movement rules differ for each piece.
  • Check and checkmate detection.
  • Game states: Active, Finished, Forfeit.

Advanced Features:

  • Support for PGN (Portable Game Notation) export.
  • Undo/redo move logs.

Step 2: Identify Core Objects

  • Piece: Abstract base class for all pieces.
  • Board: An 8x8 grid composed of Cell objects.
  • Cell: Represents a position (row, col) and the piece occupying it.
  • Move: Captures the start and end cell, and the piece moved.
  • Game: Manages players, turn switching, and game state.

Step 3: Design Class Diagram


Step 4: Implementation in TypeScript

abstract class Piece {
  private killed: boolean = false;
  private isWhite: boolean = false;
 
  constructor(isWhite: boolean) { this.isWhite = isWhite; }
  
  public abstract canMove(board: Board, start: Cell, end: Cell): boolean;
  
  public setKilled(killed: boolean) { this.killed = killed; }
}
 
class King extends Piece {
  public canMove(board: Board, start: Cell, end: Cell): boolean {
    const x = Math.abs(start.getX() - end.getX());
    const y = Math.abs(start.getY() - end.getY());
    return x + y <= 2 && x <= 1 && y <= 1;
  }
}
 
class Cell {
  private piece: Piece | null = null;
  constructor(private x: number, private y: number) {}
}
 
class Board {
  private boxes: Cell[][] = [];
 
  constructor() {
    this.resetBoard();
  }
 
  public resetBoard() {
    // initialize white pieces, black pieces, and empty cells
  }
}

Deep Dive: Factory Pattern for Pieces

Since pieces have different initialization logic but share a common interface, a Factory Pattern can be used to populate the board.

class PieceFactory {
  public static createPiece(type: string, isWhite: boolean): Piece {
    switch (type) {
      case 'KING': return new King(isWhite);
      case 'QUEEN': return new Queen(isWhite);
      // ...
      default: throw new Error("Invalid piece type");
    }
  }
}

Wrap Up

A Chess System is a test of your Rule Engine design. By encapsulating move logic inside each piece class and using a central Game class to manage rules like "check", you ensure that adding new pieces (like a "Prince" in a variant) is easy and modular.

[!IMPORTANT] To optimize, calculate all possible moves for a piece only once per turn rather than recalculating multiple times during "check" detection.