Snake is the ideal first game: the rules fit in a sentence, it's genuinely fun, and it contains a grid, a movement loop, collision detection, growth and a game-over state. Everything you learn here transfers.

1. The grid

Snake is not really about pixels. It's a grid of cells, and the snake is a list of cell coordinates. The head moves into a new cell, the tail drops the last one — unless food was eaten, in which case it doesn't, and the snake grows. That's the entire mechanic.

snake-core.txt
Build Snake in one HTML file. Canvas, no libraries.

- The board is a grid of <n>×<n> cells. Draw at a cell size constant
  I can change.
- The snake is an array of {x, y}. Moving = unshift a new head, pop
  the tail unless food was eaten.
- Food spawns on a random empty cell — never inside the snake.
- Game over on hitting a wall or itself.
- Fixed tick rate, independent of frame rate. Say what you chose.

Structure it as a `state` object, an `update()` that only changes
state, and a `draw()` that only reads it.

2. Fix the input bug

Every Snake implementation has the same bug: press up then left quickly, within one tick, and the snake reverses into itself. The fix is to queue direction changes and apply one per tick, validating each against the direction actually being travelled — not against the last key pressed.

3. Make it feel good

A brief flash when food is eaten. A short pause on death before the game-over screen, so it registers. Slight rounding on the segments. A score that counts up rather than jumping. Sound on eat and on death.

Ten minutes of this is the difference between a demo and something people replay.

4. Then extend it

Speed increasing with length. Walls you can pass through, as an option. Obstacles. A high score in localStorage. Two players on one keyboard.

Each is small, and each teaches one more thing.

Add touch controls — swipe to turn. It takes twenty lines and roughly doubles the number of people who'll actually play it.