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
Cellobjects. - 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.