🇮🇳
🇮🇳
Republic Day Special Offer!Get 20% OFF on all courses
Enroll Now
P
Prakalpana
📚Learn
Code Your Future
System Design⏱️ 25 min read📅 Jan 1

LLD: Design Chess Game - Object-Oriented Game Design

DS
Deepak SharmaSDE2 at Google
📑 Contents (7 sections)

📌Problem Statement

Design a chess game with all pieces, movement rules, and game logic.

📌Class Design

Core Classes

public enum Color {
WHITE, BLACK
}
public class Position {
private int row;
private int col;
public Position(int row, int col) {
this.row = row;
this.col = col;
}
public boolean isValid() {
return row >= 0 && row < 8 && col >= 0 && col < 8;
}
}

Piece Hierarchy

public abstract class Piece {
protected Color color;
protected Position position;
protected boolean hasMoved;
public abstract List<Position> getValidMoves(Board board);
public abstract char getSymbol();
protected boolean canMoveTo(Position pos, Board board) {
if (!pos.isValid()) return false;
Piece target = board.getPiece(pos);
return target == null || target.getColor() != this.color;
}
}
public class King extends Piece {
public char getSymbol() { return color == Color.WHITE ? 'K' : 'k'; }
public List<Position> getValidMoves(Board board) {
List<Position> moves = new ArrayList<>();
int[] dr = {-1, -1, -1, 0, 0, 1, 1, 1};
int[] dc = {-1, 0, 1, -1, 1, -1, 0, 1};
for (int i = 0; i < 8; i++) {
Position newPos = new Position(position.getRow() + dr[i], position.getCol() + dc[i]);
if (canMoveTo(newPos, board)) {
moves.add(newPos);
}
}
if (!hasMoved) {
addCastlingMoves(moves, board);
}
return moves;
}
}
public class Queen extends Piece {
public List<Position> getValidMoves(Board board) {
List<Position> moves = new ArrayList<>();
addStraightMoves(moves, board);
addDiagonalMoves(moves, board);
return moves;
}
}
public class Rook extends Piece {
public List<Position> getValidMoves(Board board) {
List<Position> moves = new ArrayList<>();
addStraightMoves(moves, board);
return moves;
}
private void addStraightMoves(List<Position> moves, Board board) {
int[][] directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
for (int[] dir : directions) {
addMovesInDirection(moves, board, dir[0], dir[1]);
}
}
}
public class Knight extends Piece {
public List<Position> getValidMoves(Board board) {
List<Position> moves = new ArrayList<>();
int[] dr = {-2, -2, -1, -1, 1, 1, 2, 2};
int[] dc = {-1, 1, -2, 2, -2, 2, -1, 1};
for (int i = 0; i < 8; i++) {
Position newPos = new Position(position.getRow() + dr[i], position.getCol() + dc[i]);
if (canMoveTo(newPos, board)) {
moves.add(newPos);
}
}
return moves;
}
}
public class Pawn extends Piece {
public List<Position> getValidMoves(Board board) {
List<Position> moves = new ArrayList<>();
int direction = (color == Color.WHITE) ? -1 : 1;
int startRow = (color == Color.WHITE) ? 6 : 1;
Position oneStep = new Position(position.getRow() + direction, position.getCol());
if (oneStep.isValid() && board.getPiece(oneStep) == null) {
moves.add(oneStep);
if (position.getRow() == startRow) {
Position twoStep = new Position(position.getRow() + 2 * direction, position.getCol());
if (board.getPiece(twoStep) == null) {
moves.add(twoStep);
}
}
}
addDiagonalCaptures(moves, board, direction);
return moves;
}
}

Board Class

public class Board {
private Piece[][] grid;
public Board() {
grid = new Piece[8][8];
initializeBoard();
}
private void initializeBoard() {
grid[0][0] = new Rook(Color.BLACK, new Position(0, 0));
grid[0][1] = new Knight(Color.BLACK, new Position(0, 1));
grid[0][4] = new King(Color.BLACK, new Position(0, 4));
grid[7][0] = new Rook(Color.WHITE, new Position(7, 0));
grid[7][4] = new King(Color.WHITE, new Position(7, 4));
for (int i = 0; i < 8; i++) {
grid[1][i] = new Pawn(Color.BLACK, new Position(1, i));
grid[6][i] = new Pawn(Color.WHITE, new Position(6, i));
}
}
public boolean movePiece(Position from, Position to) {
Piece piece = getPiece(from);
if (piece == null) return false;
List<Position> validMoves = piece.getValidMoves(this);
if (!validMoves.contains(to)) return false;
grid[to.getRow()][to.getCol()] = piece;
grid[from.getRow()][from.getCol()] = null;
piece.setPosition(to);
piece.setHasMoved(true);
return true;
}
public boolean isInCheck(Color color) {
Position kingPos = findKing(color);
Color opponent = (color == Color.WHITE) ? Color.BLACK : Color.WHITE;
for (Piece piece : getAllPieces(opponent)) {
if (piece.getValidMoves(this).contains(kingPos)) {
return true;
}
}
return false;
}
}

Game Class

public class ChessGame {
private Board board;
private Color currentTurn;
private GameStatus status;
private List<Move> moveHistory;
public ChessGame() {
board = new Board();
currentTurn = Color.WHITE;
status = GameStatus.IN_PROGRESS;
moveHistory = new ArrayList<>();
}
public boolean makeMove(Position from, Position to) {
Piece piece = board.getPiece(from);
if (piece == null || piece.getColor() != currentTurn) {
return false;
}
if (board.movePiece(from, to)) {
moveHistory.add(new Move(from, to, piece));
Color opponent = (currentTurn == Color.WHITE) ? Color.BLACK : Color.WHITE;
if (isCheckmate(opponent)) {
status = (currentTurn == Color.WHITE) ? GameStatus.WHITE_WINS : GameStatus.BLACK_WINS;
} else if (isStalemate(opponent)) {
status = GameStatus.DRAW;
}
currentTurn = opponent;
return true;
}
return false;
}
private boolean isCheckmate(Color color) {
if (!board.isInCheck(color)) return false;
return !hasAnyValidMove(color);
}
}

📌Design Patterns

  • 1Template Method: Piece movement logic
  • 2Strategy: Different piece movement strategies
  • 3Memento: Undo move functionality
  • Asked at Google, Amazon, and Microsoft interviews.

    DS

    Written by

    Deepak Sharma

    SDE2 at Google

    🚀 Master System Design

    Join 500+ developers

    Explore Courses →
    Chat on WhatsApp