The Pig Game — clean state, tight logic, no libraries.
A two-player dice game built as an exercise in disciplined vanilla JavaScript. State as a single object, UI as a pure render of that state — no magic, no frameworks, no surprises.

The rules
Two players take turns rolling a single die. Each roll adds to a current-round score — but roll a 1 and the whole round is lost. At any point a player can "hold" and bank their round score into their total. First to 100 wins.
Simple game, lots of state. Which is exactly what makes it a good exercise.
Design decisions
One state object, one render function
The entire game lives in a single JS object: currentPlayer, scores, currentScore, isPlaying, winner. Every user action mutates this object, then a single render() function diffs it to the DOM. No stray innerHTML writes, no orphaned event handlers.
Discipline over cleverness
I deliberately avoided reaching for classes, observers, or pub-sub patterns. Plain functions, plain state, plain DOM updates. The whole game is under 150 lines of JavaScript and fits on one screen.
Accessible from day one
Every action is a real <button>, every score has proper aria-live wiring, and the dice are announced as images with text alternatives. Keyboard-only play works identically to mouse play.
What I learned
- Keeping state in one place makes bugs obvious. Scattered state makes them invisible until ship.
- "Render from state" is a discipline, not a framework. You can do it in vanilla JS if you commit to it.
- A 150-line game is a better interview answer than a 1,500-line framework exercise.
The goal was not to make this game clever. It was to make it boring — in the good way, where every part does exactly what you'd expect.