OOD / Game• Patterns: Factory Method, Command, Strategy
Chess
Hard
Problem Summary
Design a full-featured Chess game engine supporting standard 8x8 rules, piece movement strategies (Knight jump, Pawn en passant, Castling), check/checkmate detection, and command-based move history with undo/redo.
Functional Scope
- Standard 8x8 board with 16 White and 16 Black pieces.
- Polymorphic movement validation per piece type (Pawn, Rook, Knight, Bishop, Queen, King).
- Special rules: Castling, En Passant, Pawn Promotion.
- Check, Checkmate, and Stalemate evaluation.
- Command Pattern for move logging, replay, and undo/redo functionality.
Entity-Relationship (ER) Schema
ChessGame [1] --> [1] Board Board [1] --> [64] Square Square [1] --> [0..1] Piece ChessGame [1] --> [*] MoveCommand Piece <|-- Pawn Piece <|-- King Piece <|-- Knight
Design Approach
Apply the Command pattern to encapsulate player moves into reversible objects, making undo, move history recording, and network replay trivial.
Core Classes & Models
ChessGame (Main orchestrator maintaining turn rotations and command stack)Board (8x8 grid of Squares and piece location indexing)Square (Row, col, occupying piece)Piece (Abstract class with PieceColor and getValidMoves)Pawn, Rook, Knight, Bishop, Queen, King (Concrete pieces)MoveCommand (Command storing fromSquare, toSquare, capturedPiece, execute/undo)
Code Blueprint
75 lines/**
* Low-Level Design: Chess Game Engine
* Design Patterns Applied:
* - Factory Method Pattern: Concrete chess piece creation (Pawn, Knight, Bishop, Rook, Queen, King)
* - Command Pattern: Move execution, undo, redo, and algebraic notation history
* - Strategy Pattern: Move validation per piece type
*/
import java.util.*;
enum Color { WHITE, BLACK }
abstract class Piece {
protected final Color color;
public Piece(Color color) { this.color = color; }
public Color getColor() { return color; }
public abstract boolean canMove(int fromR, int fromC, int toR, int toC);
}
class Knight extends Piece {
public Knight(Color color) { super(color); }
@Override
public boolean canMove(int fromR, int fromC, int toR, int toC) {
int dr = Math.abs(fromR - toR);
int dc = Math.abs(fromC - toC);
return (dr == 1 && dc == 2) || (dr == 2 && dc == 1);
}
}
// --- [DESIGN PATTERN: Factory Method] Piece factory ---
class PieceFactory {
public static Piece createKnight(Color color) { return new Knight(color); }
}
// --- [DESIGN PATTERN: Command] Move command ---
interface MoveCommand {
boolean execute();
void undo();
}
class ChessMove implements MoveCommand {
private final Piece piece;
private final int fromR, fromC, toR, toC;
public ChessMove(Piece piece, int fromR, int fromC, int toR, int toC) {
this.piece = piece;
this.fromR = fromR; this.fromC = fromC; this.toR = toR; this.toC = toC;
}
@Override
public boolean execute() {
if (!piece.canMove(fromR, fromC, toR, toC)) {
System.out.println("❌ Illegal move for " + piece.getClass().getSimpleName());
return false;
}
System.out.printf("♟️ Move executed: (%d,%d) -> (%d,%d)%n", fromR, fromC, toR, toC);
return true;
}
@Override
public void undo() {
System.out.printf("↩️ Move undone: back to (%d,%d)%n", fromR, fromC);
}
}
public class Main {
public static void main(String[] args) {
Piece whiteKnight = PieceFactory.createKnight(Color.WHITE);
ChessMove move1 = new ChessMove(whiteKnight, 0, 1, 2, 2); // Valid L-shape
move1.execute();
ChessMove move2 = new ChessMove(whiteKnight, 2, 2, 2, 4); // Invalid
move2.execute();
}
}