Course 08 · Lesson 4 of 11
Build a Snake Game
A complete canvas-based arcade game built in one Claude Code session
Snake is the perfect second game to build. It introduces the HTML canvas, a moving game object with state, grid-based collision detection, and speed that increases over time. Once you can build Snake you can build almost any arcade game.
This lesson gives you the complete production-ready prompt.
Why Snake Is a Great Learning Game
Memory Match taught you DOM-based games where HTML elements are moved and styled with CSS. Snake teaches you canvas-based games where everything is drawn programmatically in JavaScript.
The two patterns together cover the vast majority of browser games. Every other game in this course is a variation of one or the other.
How Snake Works Technically
The snake is a list of grid coordinates. Each segment is one cell on a grid. Every game tick the snake moves by adding a new head position in the current direction and removing the last tail segment. When the snake eats food, the tail is not removed that tick so the snake grows by one segment.
Collision with the wall means the new head position is outside the grid bounds. Collision with itself means the new head position matches any existing segment coordinate. Both end the game.
Food is placed at a random empty grid cell. Empty means not currently occupied by any snake segment.
Speed increases by reducing the time between game ticks as the score grows.
The Complete Snake Prompt
Copy this prompt, fill in your design values, and send it.
Build me a complete Snake browser game. Follow all design rules in @CLAUDE.md.
FILES:
Three files only: index.html, style.css, main.js.
No external libraries. No npm. No build tools.
All JavaScript in main.js. All CSS in style.css. Zero inline styles.
GAME TYPE: Snake WHAT THE PLAYER DOES:
The player controls a snake moving continuously around a grid. The snake must
eat food to grow longer and score points. The game ends when the snake hits
a wall or runs into itself. The goal is to get the highest score possible.
GAME RULES:
- The snake starts at 3 segments long in the centre of the grid moving right
- The snake moves automatically one grid cell per tick
- Arrow keys or WASD change direction
- The snake cannot reverse direction — pressing the opposite direction is ignored
- The snake cannot queue more than one direction change per tick
- Eating food increases the snake length by 1 and increases the score by 10
- The snake dies if the head moves outside the grid bounds
- The snake dies if the head position matches any body segment position
- Speed increases every 50 points — starting at one tick per 150ms and decreasing
by 10ms per 50-point interval down to a minimum of 60ms per tick
CONTROLS:
Desktop: Arrow keys or WASD to change direction. Space to pause and unpause.
Mobile: Swipe in any of the four directions to change direction. Tap anywhere to pause.
Add four on-screen arrow buttons below the canvas for mobile players who prefer buttons.
GAME ELEMENTS:
- Grid: 20 columns by 20 rows. Canvas size: 400px by 400px so each cell is 20px by 20px.
- Snake head: filled square in the accent colour with a 2px darker border
- Snake body: filled squares in the primary colour slightly darker than the head
- Food: a filled circle centred in its grid cell in a contrasting highlight colour
- Score: displayed above the canvas as "Score: X" and "Best: X" on the same line
- Speed indicator: display the current level such as "Speed: 1" increasing with score
SCORING:
10 points per food eaten.
High score saved to localStorage with key "snake-highscore".
Display current score and best score above the canvas during play.
GAME STATES:
- Start screen: game title "Snake", best score displayed, a Start button, and brief
controls reminder — Arrow keys to move, Space to pause
- Playing: canvas with snake moving, score and best displayed above
- Paused: dim the canvas with a semi-transparent overlay and show "PAUSED" centred.
Show "Press Space to continue" below.
- Game over: semi-transparent overlay on the canvas showing "Game Over",
final score, whether a new best was set, and a Play Again button
SOUND:
Use the Web Audio API with no audio files.
- Eating food: a short bright tone at 660hz for 60ms
- Direction change: a very subtle soft click at 220hz for 30ms — keep this quiet
- Game over: a descending two-tone sequence at 330hz then 220hz each for 150ms
- New high score: an ascending three-tone sequence at 523hz, 659hz, and 784hz
Add a mute toggle button in the top right corner of the game area.
The mute state should be saved to localStorage so it persists between sessions.
HIGH SCORE:
localStorage key: "snake-highscore"
Check if the game over score beats the saved high score.
If it does, save it and show "New Best!" on the game over screen.
Read and display the saved high score on the start screen and during play.
DESIGN:
Follow all rules in @CLAUDE.md
Game container: max 480px wide and centred on the page
Canvas size: exactly 400px by 400px
Background behind canvas: [BACKGROUND HEX]
Canvas background: [SLIGHTLY LIGHTER THAN BACKGROUND HEX — e.g. #111111 on a #0a0a0a page]
Snake head colour: [ACCENT HEX]
Snake body colour: [PRIMARY HEX — slightly darker than accent]
Food colour: [HIGHLIGHT HEX — contrasting with both snake colours]
Grid lines: optional — if included use rgba(255,255,255,0.03) so they are barely visible
Font: [FONT NAME] from Google Fonts for all UI text above and below the canvas Score text colour: [TEXT HEX] TECHNICAL:
Game loop: use requestAnimationFrame with a timestamp-based tick system.
Only update game logic when the elapsed time since the last tick exceeds the current
tick interval. Render every frame for smooth display.
State: store all game state in a single gameState object containing:
- snake (array of {x, y} objects), direction, nextDirection, food {x, y},
- score, gameStatus (start, playing, paused, gameover), tickInterval, lastTickTime
- Input: add keydown listener for Arrow keys, WASD, and Space.
- Block the default scroll behaviour for arrow keys using preventDefault.
- Touch: implement swipe detection using touchstart and touchend events.
- Calculate delta X and delta Y. The larger absolute value determines the axis.
- Map each axis and direction to the corresponding snake direction change.
- Mobile canvas scaling: if the viewport is narrower than 420px scale the canvas
- down proportionally using CSS transform: scale() to fit within the screen width.
SELF-CHECK BEFORE DELIVERING:
- Start screen appears with title, best score, and Start button
- Clicking Start begins the game with a 3-segment snake moving right
- Pressing the left arrow key while moving right is correctly ignored
- Eating food increases the snake length and score by 10
- The snake correctly dies when it hits the right wall moving right
- The snake correctly dies when it hits its own body
- Game over screen shows the correct final score and Play Again button
- High score saves correctly and shows on the next start screen
- Space bar pauses and unpauses correctly
- The game is playable by swiping on a 375px mobile screen
Customising After the First Build
Once Claude builds the base Snake game you can extend it with focused follow-up prompts.
To add a growing difficulty curve with level display:
- After every 5 foods eaten add a level up event.
- Show "Level Up!" as a brief overlay on the canvas for 1 second.
- Display the current level in the score area as "Level: X".
- Each level increases the snake speed more aggressively than the base speed curve.
To add a wrap-around mode where the snake passes through walls:
- Add a game mode toggle on the start screen: "Normal" and "Wrap Mode".
- In Wrap Mode, when the snake head goes past the right wall it reappears at the
left wall. Same for top and bottom. The snake only dies from hitting itself.
Save the selected mode preference to localStorage.
To add a coloured trail effect:
- Make the snake body segments change colour gradually from the head to the tail.
- The head uses the accent colour. Each segment transitions toward a darker or more
- muted version of the same hue. The tail segment is the most faded.
- Implement using HSL colour values adjusted per segment index.
What to Do If Snake Breaks
If the snake moves in the wrong direction after a key press, the direction-change logic is not blocking opposite directions. Send Claude this:
- The snake can reverse direction when I press the opposite arrow key.
- Add a guard that prevents setting nextDirection to the exact opposite of the
- current direction. Opposite pairs are: left and right, up and down.
If the game loop runs too fast or too slow, the tick interval calculation is off. Send Claude this:
The snake is moving too fast or at inconsistent speed. Fix the timestamp-based
tick system so the snake moves exactly once per [TARGET MS]ms regardless of
the monitor refresh rate. Use performance.now() for the timestamp comparison.
If the canvas is too large on mobile, send Claude this:
On a 375px wide screen the 400px canvas overflows the screen horizontally.
Scale the canvas down on screens narrower than 420px using:
canvas { max-width: 100%; height: auto; }Or use CSS transform: scale() to fit it within the viewport without changing
the internal canvas coordinate system.
Do it with other builders
Post your homework. Get unstuck.
Every course ends with homework. Post yours in Claude Codex Mastery, the community this course comes from, and get feedback from Yar and 400+ people building the same way.
Join the community · $29/mo