01 / Context
Why this project exists
Solitaire is visually familiar but programmatically rich. Cards have identity, order, visibility, location, and legal moves; a single user action can affect several piles and reveal new state.
The project used a constrained game to practice turning written rules into explicit program behavior and connecting that behavior to a two-dimensional interface.
02 / Approach
How the problem was framed
A clean implementation separates the underlying game state from what is drawn on screen. Moves can then be checked against rules before the display updates, reducing the chance that visual state and logical state drift apart.
Core concerns include deck creation and shuffling, pile representation, face-up and face-down cards, legal movement, win detection, and input selection. Even a small version benefits from treating each transition as a testable operation.
03 / Result
What exists now
A complete, playable game - embedded above and hosted on its own page. A single rules engine (no DOM, fully unit-tested) powers Klondike, FreeCell and Spider; a separate renderer reflects state to the screen and never decides legality itself.
Deals are deterministic and shareable by number, moves are reversible deltas giving unlimited undo/redo, and the same move generator drives hints and a bounded winnability check. Around it sits a settings panel covering variant rules, assists, controls, table look, motion, sound and per-variant statistics - all persisted.
- Three variants on one engine; drag, click and full keyboard play.
- Deterministic deals, undo/redo, hints, safe auto-play and an auto-finish.
- Drafting-styled felt table with a swappable card-back layer.
04 / Reflection
Lessons and next steps
Keeping the engine free of the DOM paid for itself immediately: because rules could be exercised in isolation, the tricky parts - FreeCell supermove capacity, Spider run retirement, undo that restores exact state - were provable rather than eyeballed. Games make hidden-state bugs visible, and a test that deals a fixed seed and asserts the layout catches drift the moment it appears.
Modelling moves as reversible deltas turned undo, redo and hint generation into the same mechanism instead of three. The honest limit is the winnability solver: it is a bounded search, certain when it says yes and only "not within budget" when it says no, and it is deliberately switched off for Spider rather than faked.