Free preview

Why this matters: in the implementation act the interviewer goes quiet and watches one thing — whether your code matches your words. You promised two layers, candidates-then-legality, king safety in one place. Here is what keeping that promise looks like on the page.

The data model

java
enum Color { WHITE, BLACK } enum PieceType { KING, QUEEN, ROOK, BISHOP, KNIGHT, PAWN } class Piece { PieceType type; Color color; } class Square { int file; int rank; } // 0..7, 0..7 class Move { Square from; Square to; } // a value object; no logic class Position { Piece[][] board = new Piece[8][8]; // null = empty Color toMove; Position copy() { /* deep-copy board, same toMove */ } void apply(Move m) { board[m.to] = board[m.from]; board[m.from] = null; } }

Position.copy() is the simulation workhorse. At interactive rates a 64-cell copy per validation is nothing — say that, don't apologize for it.

Movement rules: one interface, six small implementations

java
interface MovementRules { // Ignoring king safety: could this piece make this move here? boolean canMove(Position p, Move m); }

The sliding pieces — rook, bishop, queen — share one helper, which is the only clever code in the file:

java
// Walk from 'from' toward 'to' one step at a time along (df, dr). // True iff 'to' is reached with every intermediate square empty. boolean rayClear(Position p, Move m, int df, int dr) { int f = m.from.file + df, r = m.from.rank + dr; while (f != m.to.file || r != m.to.rank) { if (p.board[f][r] != null) return false; // blocker f += df; r += dr; } return true; }

The rook accepts a move if it is on-file or on-rank and rayClear; the bishop the diagonal version; the queen is rook-or-bishop. The knight is a lookup against its eight offsets — no ray, jumps over everything. The king moves one square any direction. The pawn earns its reputation: forward one (two from its start rank) onto empty squares only, capture diagonally only — direction depending on color. Every rule also rejects landing on a friendly piece; that check lives in one shared guard, not six copies.

Attack detection: the reuse payoff

java
boolean isSquareAttacked(Position p, Square target, Color by) { for (Square s : allSquares()) { Piece pc = p.board[s.file][s.rank]; if (pc == null || pc.color != by) continue; if (rulesFor(pc.type).canMove(p, new Move(s, target))) return true; } return false; }

No new chess knowledge — the movement rules ARE the attack rules. (One honest wrinkle to name if asked: the pawn attacks diagonally even when it couldn't move there, so the pawn's rule treats a diagonal onto an enemy-or-target square as a capture pattern. Naming the wrinkle unprompted reads as mastery.)

The legality layer: four steps, verbatim from the design

java
boolean isLegal(Position p, Move m) { Piece pc = p.board[m.from.file][m.from.rank]; if (pc == null || pc.color != p.toMove) return false; // 1. turn if (!rulesFor(pc.type).canMove(p, m)) return false; // 2. candidate Position scratch = p.copy(); // 3. simulate scratch.apply(m); Square king = findKing(scratch, p.toMove); return !isSquareAttacked(scratch, king, opposite(p.toMove)); // 4. king safe }

Ten lines, and the pin comes for free: slide a pinned bishop sideways, the scratch position exposes the king, step 4 says no. No pin-specific code exists anywhere — that absence is the design working, and it is worth pointing at during the round.

If the interviewer presses on the copy, show the alternative shape without switching to it: apply returns the captured piece, revert puts both pieces back — a disciplined pair, faster, one more way to write a bug. Copy first, measure, then earn the optimization.

Where validation lives — and doesn't

The UI calls isLegal and nothing else. Movement rules are package-private; nobody outside the module can ask a rook its opinion and mistake it for a verdict. That boundary is the module's contract: one entry point, one meaning of "legal."

Key takeaway

The implementation keeps the design's promise line by line: six small movement rules sharing one ray-walker, attack detection that reuses those same rules, and a four-step isLegal whose simulation makes pins and checks fall out of a single code path. The most senior thing on the page is what's absent — no pin logic, no per-piece king checks, no second definition of legality anywhere.

Enjoying the preview?

Create a free account to unlock the rest of this course, the in-browser judge, and live AI mock interviews.

Sign up free to continue