back to work
game · 2024 · ● frontend

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.

year2024
typeBrowser game
stackHTML · CSS · JS
statusShipped
Single-state objectAccessible buttonsVanilla JS render loopKeyboard-friendly logic
The Pig Game — gameplay screenshot

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.