Chaturmind
LearnDSASystem DesignDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight

Behavioral Design Patterns

  • Strategy Pattern
  • Observer Pattern
  • Command Pattern
  • Template Method
  • State Pattern
  • Chain of Responsibility
  • Iterator & Mediator
  • Visitor Pattern

Machine Coding Exercises

  • Parking Lot — Requirements & Class Design
  • Parking Lot — Implementation
  • Elevator System — Requirements & Class Design
  • Elevator System — Implementation & Scheduling
  • Library Management System
  • Tic-Tac-Toe / Board Game Design
  • Chess Engine Design
  • Vending Machine Design
  • ATM System Design
  • In-Memory Rate Limiter
  • Thread-Safe LRU Cache
  • Connection Pool Design
  • Producer-Consumer Class Design
  • Movie Ticket Booking System
  • Hotel Reservation System
  • Airline Booking / Seat Selection System
  • Splitwise / Expense Sharing System
  • Design a Logging Framework
  • Design a Notification/Observer-Based Pub-Sub
  • Design a Cache with Pluggable Eviction Policy
  • Design Snake and Ladder
  • Design a Card Game Framework
  • Design an Inventory Management System
  • Restaurant Management System
  • Food Delivery Order Matching
  • Design a Shopping Cart & Checkout Flow
  • Design a Recommendation Engine
  • Design a Job Scheduler
  • Design a Circuit Breaker
  • Design a Distributed ID Generator
  • Design a Pub-Sub Message Broker
  • Design Twitter/X
  • Multi-Pattern Problem: Design a Ride Booking Class Model
  • Multi-Pattern Problem: Design a Food Ordering Class Model
  • Design an Authentication/Authorization Module
  • Design a Form/Survey Builder
  • Design a Meeting Room / Calendar Booking System
  • Design a Search/Filter Engine for an E-Commerce Catalog
  • Design a Voting/Polling System
  • Design a Retry Mechanism with Backoff
  • Design a Health Check Aggregator
  • Design a Feature Flag System
  • Design a Config Management Client
  • Design a Leader Election Algorithm
  • Design a Distributed Counter
  • Design a Bloom Filter
  • Design a Consistent Hashing Ring
  • Design a Distributed Tracing Library
  • Design a Metrics Collection Library
  • Design an Audit Logging Framework
  • Design a Plugin/Extension System
  • Design a Workflow Engine
  • Multi-Pattern Capstone: Design a Food Delivery App
Chaturmind
← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight

Behavioral Design Patterns

  • Strategy Pattern
  • Observer Pattern
  • Command Pattern
  • Template Method
  • State Pattern
  • Chain of Responsibility
  • Iterator & Mediator
  • Visitor Pattern

Machine Coding Exercises

  • Parking Lot — Requirements & Class Design
  • Parking Lot — Implementation
  • Elevator System — Requirements & Class Design
  • Elevator System — Implementation & Scheduling
  • Library Management System
  • Tic-Tac-Toe / Board Game Design
  • Chess Engine Design
  • Vending Machine Design
  • ATM System Design
  • In-Memory Rate Limiter
  • Thread-Safe LRU Cache
  • Connection Pool Design
  • Producer-Consumer Class Design
  • Movie Ticket Booking System
  • Hotel Reservation System
  • Airline Booking / Seat Selection System
  • Splitwise / Expense Sharing System
  • Design a Logging Framework
  • Design a Notification/Observer-Based Pub-Sub
  • Design a Cache with Pluggable Eviction Policy
  • Design Snake and Ladder
  • Design a Card Game Framework
  • Design an Inventory Management System
  • Restaurant Management System
  • Food Delivery Order Matching
  • Design a Shopping Cart & Checkout Flow
  • Design a Recommendation Engine
  • Design a Job Scheduler
  • Design a Circuit Breaker
  • Design a Distributed ID Generator
  • Design a Pub-Sub Message Broker
  • Design Twitter/X
  • Multi-Pattern Problem: Design a Ride Booking Class Model
  • Multi-Pattern Problem: Design a Food Ordering Class Model
  • Design an Authentication/Authorization Module
  • Design a Form/Survey Builder
  • Design a Meeting Room / Calendar Booking System
  • Design a Search/Filter Engine for an E-Commerce Catalog
  • Design a Voting/Polling System
  • Design a Retry Mechanism with Backoff
  • Design a Health Check Aggregator
  • Design a Feature Flag System
  • Design a Config Management Client
  • Design a Leader Election Algorithm
  • Design a Distributed Counter
  • Design a Bloom Filter
  • Design a Consistent Hashing Ring
  • Design a Distributed Tracing Library
  • Design a Metrics Collection Library
  • Design an Audit Logging Framework
  • Design a Plugin/Extension System
  • Design a Workflow Engine
  • Multi-Pattern Capstone: Design a Food Delivery App
HomeLearnSystem DesignLow-Level Design & Design PatternsMachine Coding Exercises
✓ FreeAdvanced· 9 min read

Chess Engine Design

Polymorphic move validation per piece instead of a giant switch, check/checkmate as a separate concern, turn management with move history, and which edge cases to discuss rather than fully implement.

Published September 23, 2026


Chess Engine Design

The most structurally demanding machine-coding prompt in this course — chess has real complexity (per-piece movement rules, check/checkmate, special moves) that rewards correct separation of concerns far more than tic-tac-toe or a parking lot do.

Core classes

abstract class Piece {
    protected final Color color;
    protected Position position;
    Piece(Color color, Position position) { this.color = color; this.position = position; }
    abstract List<Position> getValidMoves(Board board); // polymorphism — no piece-type switch anywhere else
}

class King extends Piece {
    List<Position> getValidMoves(Board board) { /* one square any direction */ return List.of(); }
}
class Rook extends Piece {
    List<Position> getValidMoves(Board board) { /* straight lines until blocked */ return List.of(); }
}
class Bishop extends Piece {
    List<Position> getValidMoves(Board board) { /* diagonals until blocked */ return List.of(); }
}
// Queen, Knight, Pawn follow the same shape

class Move {
    final Position from, to;
    final Piece movedPiece;
    final Piece capturedPiece; // null if no capture
}

class Player {
    final Color color;
    final String name;
}

Move validation via polymorphism, not a giant switch

class ChessGame {
    boolean isValidMove(Piece piece, Position target) {
        return piece.getValidMoves(board).contains(target); // delegates entirely — no if/else on piece type here
    }
}

The alternative — one method containing if (piece instanceof Rook) { ... } else if (piece instanceof Bishop) { ... } for all six piece types — is exactly the OCP violation Single Responsibility & Open/Closed warns about: adding a new piece type (a custom variant piece, say) would mean editing this central method. With getValidMoves() as an abstract method each Piece subclass implements, adding a new piece type means writing one new subclass, touching nothing else.

Check/checkmate as a separate concern from move validation

class CheckDetector {
    boolean isInCheck(Board board, Color kingColor) {
        Position kingPos = board.findKing(kingColor);
        return board.getAllPieces(oppositeColor(kingColor)).stream()
            .anyMatch(p -> p.getValidMoves(board).contains(kingPos));
    }

    boolean isCheckmate(Board board, Color kingColor) {
        if (!isInCheck(board, kingColor)) return false;
        // checkmate = in check AND no legal move exists that escapes check
        return board.getAllPieces(kingColor).stream()
            .allMatch(p -> p.getValidMoves(board).stream()
                .noneMatch(move -> moveEscapesCheck(board, p, move, kingColor)));
    }
}

Keeping this in a separate CheckDetector rather than folding it into Piece.getValidMoves() matters for a subtle correctness reason: a piece's raw movement pattern ("a rook moves in straight lines") is a different question from "is this specific move legal right now" (a move that would leave your own king in check is illegal, even if it matches the piece's raw movement pattern) — conflating the two inside each piece class would mean every piece needs to know about check detection, a much larger coupling than piece-movement logic should have.

Turn management and move history

class ChessGame {
    private final Deque<Move> moveHistory = new ArrayDeque<>();
    private Player currentPlayer;

    void makeMove(Position from, Position to) {
        Piece piece = board.getPieceAt(from);
        Move move = new Move(from, to, piece, board.getPieceAt(to));
        board.applyMove(move);
        moveHistory.push(move); // enables undo AND is exactly the Command Pattern's command-history idea
        currentPlayer = getOpponent(currentPlayer);
    }

    void undoLastMove() {
        Move last = moveHistory.pop();
        board.reverseMove(last); // uses captured piece info from the Move object to restore it
        currentPlayer = getOpponent(currentPlayer);
    }
}

Storing each Move as its own object (not just mutating board state and discarding the record) is precisely the Command Pattern's shape — undo works because each Move carries enough information (capturedPiece, in particular) to reverse itself, the same principle as InsertCommand.undo() in Command Pattern.

Special moves and multiplayer: discuss, don't fully implement

Castling, en passant, and pawn promotion are legitimate edge cases worth naming explicitly in an interview (showing awareness they exist and roughly how they'd fit — e.g. castling needs to track whether the king/rook have ever moved, since that affects legality) rather than fully implementing under interview time pressure. Similarly, extending to online multiplayer is explicitly an HLD concern (network synchronization, move broadcasting, reconnection handling) layered on top of this LLD design, not a change to the class structure itself — naming that distinction clearly is itself a signal of architectural maturity.

Follow-up questions this topic invites — and their answers

Q: Why does getValidMoves() take the board as a parameter instead of the Piece holding a board reference? A: Passing the board explicitly keeps Piece subclasses stateless with respect to the game (they hold only their own color/position), making them easier to test in isolation and avoiding a piece needing to be told about board changes it doesn't directly cause.

Q: How would you detect stalemate, distinct from checkmate? A: Nearly identical logic to isCheckmate(), with one flipped condition — stalemate is 'no legal move exists' while NOT in check (checkmate requires being in check). Both share the 'does any legal move exist' computation; only the check-status precondition differs.

Q: Where would castling's legality state (has the king/rook moved) actually live? A: Most naturally as boolean flags on the King and Rook pieces themselves (hasMoved), checked by a CastlingRule (or an extension to getValidMoves() specifically for King) — this is exactly why 'discuss, don't implement' is the right call under time pressure: the state genuinely belongs somewhere non-obvious, and getting it right takes real design thought.

Q: Isn't storing capturedPiece on every Move wasteful when most moves don't capture anything? A: A null capturedPiece field costs essentially nothing (a single reference, unset) — this is a non-issue in practice, and the alternative (a separate capture-tracking structure) would add complexity without a real performance benefit at the scale a single chess game operates at.

Previous

Tic-Tac-Toe / Board Game Design

Next

Vending Machine Design

AI Tutor

Lesson: Chess Engine Design

Quick actions

AI responses can be inaccurate. Verify critical information.