AgentGames

Search titles, descriptions, models and tags. Press Enter to see results.

🐍 Guide

How to make a snake game with AI

Snake is a list of cells and a timer. Almost every first build dies to a turn the player never actually made, and the fix is a two entry queue.

Updated 5 October 2026 7 min read By the Agent Games team
Jump to a section
  1. Four steps to a snake that turns when asked
  2. The two turn death, and the queue that ends it
  3. Ticks are the speed, frames are the picture
  4. Growth is a tail you choose not to remove
  5. Food on a free cell, chosen rather than guessed
  6. Common questions
  7. Where to go next

Ask for a grid, a list of cells for the body, and a timer that moves the head one cell at a time. Then ask for turns to arrive through a queue rather than straight into the direction. That one instruction removes the death that makes a first snake build feel broken.

The death nobody can see coming

The snake is going right. The player taps up, then left, quickly, meaning to round a corner. Both presses land before the next tick. The second one is tested against up, where left is a legal turn, so it is accepted. The snake was still going right, and left is the reverse of right. It eats itself, and nothing on screen explains why.

Four steps to a snake that turns when asked#

Paste the prompt below and open what it writes

The grid, the body list, the food and the tick loop all arrive in one pass. There is very little maths in this genre.

Round a corner as fast as your fingers go

Two presses, as close together as you can manage. If the snake dies, the direction is being written on the key press rather than queued.

Hold a key down and watch the queue

A queue with no cap banks turns and the snake keeps turning after you stop. Two entries is the right size.

Play until the snake is long, then judge the speed

A tick length that felt right at three cells is often wrong at thirty. Tune it long, not short.

PromptCopy this, paste it, send it
Build a grid based snake game as ONE self-contained .html file. No
frameworks, no images, no audio files.

BOARD: a grid of 20 by 20 cells on a canvas, with faint cell lines so
the grid is readable. The snake starts three cells long in the middle,
heading right.

TICKS: the snake moves on a timer, not once per frame. Hold a running
total of elapsed seconds. Each time it reaches TICK_SECONDS, advance the
snake exactly one cell and take TICK_SECONDS back off the total. Redraw
on every animation frame regardless, so the board never looks frozen
between moves.

TURNING. Treat this section as the point of the build. An arrow key does
not set the direction. It pushes a direction onto a short queue. On each
tick, take at most one entry off that queue. Discard any entry that is
the exact opposite of the direction the snake last actually moved,
comparing against that last real move and never against the most recent
press. Cap the queue at two entries, so a held key cannot bank a long
run of turns.

GROWING: keep the body as a list of cells, head first. Each tick, add
the new head cell to the front of the list, then remove the final cell.
On a tick where food was eaten, skip that removal. Never append a
segment by hand and never calculate where a new tail belongs.

FOOD: to place food, build the list of cells that no part of the snake
occupies, then pick one of those at random. Do not pick a random cell
and retry until it happens to be free. If that list is empty, the player
has filled the board and won.

DEATH: the snake dies when the new head cell is outside the grid or is
already part of its body. Show the score, offer a restart key, and keep
the best score in localStorage between sessions.

SPEED: shorten TICK_SECONDS slightly on every food eaten, down to a
floor value, so a long snake is faster than a short one.

PHONE: swipes up, down, left and right queue a turn in exactly the way
the arrow keys do. Include canvas { touch-action: none; } in the CSS
so a swipe cannot scroll the page.

TIMING: measure the seconds that passed since the previous frame, clamp
that figure to 0.05, and add it to the running total.

CONFIG: one object at the top of the script holding GRID, CELL,
TICK_SECONDS, TICK_FLOOR, QUEUE_MAX, START_LENGTH and SPEEDUP_PER_FOOD,
each with a one line comment. Begin with TICK_SECONDS at 0.12 and
QUEUE_MAX at 2.

TICK_SECONDS and SPEEDUP_PER_FOOD are the difficulty of the whole game and want testing on a long snake. Leave the queue rule exactly as written. If you raise QUEUE_MAX above two or three, held keys start storing turns and the snake carries on rounding corners after you have let go.

The two turn death, and the queue that ends it#

A grid game has a coarse clock. The snake occupies whole cells and changes cell a few times a second. Keyboard events do not wait for that clock. A quick corner sends two presses into the same gap between moves, and a model that writes the direction on each event applies both.

Two presses inside one tick Up, then left, both arriving before the snake has moved a cell. Direction written on each press onKey: dir = pressedUp lands, then left landsLeft was checked against upThe head turns into its own neck One turn per tick, from a queue onKey: queue.push(pressed)A tick spends one entry at mostA reverse of the last move is binnedUp happens now, left waits a tick Compare the turn against the move the snake made, not the key before it.
The bug is not the reversal check. It is what the check compares against. Up has already overwritten right, so left looks perfectly legal.

The queue fixes three things at once. Presses stop racing the clock, because they sit in a list until a tick asks for one. Only one turn can ever apply per move, so the snake cannot pivot twice in a cell. And the reversal check finally has the right thing to compare against, which is the move the snake made, not the key before it.

Cap the queue at two. One entry loses the second press of a fast corner, which is the behaviour you were trying to fix. Five entries means a held key fills the list, and the snake keeps turning for half a second after you stop touching the keyboard. Two is enough to hold a corner and short enough to feel immediate.

Keep the old direction stored separately from the queued one. The snake needs to know what it did last, and that value may only change on a tick. Reading it from the input handler is how the bug comes back later in a different shape.

Ticks are the speed, frames are the picture#

Snake has two clocks and a first build usually has one. The drawing clock should run as fast as the browser allows, so the board is always on screen and a restart responds at once. The movement clock should be slow and even, because the game is its pace.

Tie movement to frames and the difficulty becomes a property of the monitor. On a high refresh screen the snake sprints and the player cannot react. On a loaded machine it crawls. Neither is a choice anybody made, and no score from one machine means anything on another.

Tick lengthHow it playsWhat to watch
0.2 seconds a cellSlow and forgivingDull once the snake is long
0.12 seconds a cellBrisk, a fair defaultJudge it at thirty cells, not three
0.06 seconds a cellFast, the queue earns its placeCorners need to be planned early
Under 0.04 secondsFaster than most people planOnly reachable through the speed ramp

These are starting points and depend on the grid. The same tick length feels quicker on a small board, because a wall arrives sooner.

A speed ramp is worth adding early. Shorten the tick slightly on each food, with a floor so it cannot reach nothing. It gives a run a shape, and the ramp is also what makes the turn queue matter rather than being a detail.

Growth is a tail you choose not to remove#

Movement and growth are the same operation here, which is the detail worth knowing. On a normal tick, put the new head cell at the front of the list and drop the last cell. The snake has moved and the length has not changed.

On a tick where food was eaten, do everything the same except the drop. The head advances, nothing leaves the back, and the body is one cell longer. No position needs to be worked out, because the extra cell is simply the one that would have gone.

The alternative is where first builds go wrong. Adding a segment means deciding where it goes, and behind the tail is a cell the snake has already left. Do it while the snake is turning and the new piece sits off the body. Models produce this version fairly often, so rule it out in the prompt.

Food on a free cell, chosen rather than guessed#

The usual way to place food is to pick a random cell, check whether the snake is on it, and try again if so. It works, and it works less well the longer the game goes. Near the end, with the board almost full, the loop can spin for a long time hunting the last gap.

Five rules behind a grid game that plays fair All five are cheap. All five are missing from a first build. 1 One turn per tick Queue the presses, spend at most one each tick. 2 Never the exact reverse Compare with the last move, not the last press. 3 Grow by keeping the tail Skip the removal when food was eaten this tick. 4 Food from free cells Choose from the empty list, never guess and retry. 5 Speed is the tick rate Draw every frame, move on a timer. Two clocks. The first two are fairness. The last three are plain correctness.
Five rules, none of them more than a few lines. The first two are what players notice, and the last three are what breaks quietly.

Build the list instead. Walk the grid once, collect every cell the body does not occupy, and take one at random. The cost is fixed and tiny. It also tells you something the retry loop cannot. When that list comes back empty, the board is full and the player has won.

  • A win condition, free of charge. An empty free list is the only honest end to a snake game. Without it, a perfect run ends in a loop that never returns.
  • No food under the head. Place food after the move, from the body's current cells, or it can appear on the square the snake is about to enter.
  • Keep the grid small to begin with. A twenty cell square fills quickly, which means you reach the late game faults in one sitting.
  • Draw the grid lines faintly. On a grid the player is counting cells to plan a turn, and invisible cell boundaries make that guesswork.

🐍Snake games written by AI

Common questions#

Why does my snake die when I turn a corner quickly?

Two presses are landing between moves and both are being applied. The second is tested against the first, not against the direction the snake really travelled, so a reverse slips through. Queue the presses and spend one per tick, and the death goes away.

How do I stop the snake reversing into itself?

Refuse any direction that is the exact opposite of the last move the snake made. The important word is made. Comparing against the most recently pressed key is the version that fails, because that key may not have been acted on yet.

How big should the turn queue be?

Two entries. One throws away the second press of a fast corner, which is the problem you set out to solve. Anything much larger lets a held key bank turns, and the snake carries on rounding corners after you have taken your hand off.

How should the snake grow when it eats?

Add the new head cell and skip removing the final cell on that tick. The body is one longer and nothing has to be positioned. Adding a segment by hand means choosing a cell behind the tail, which is often a cell the snake has already left.

How do I place food so it never lands on the snake?

Collect every cell the body does not occupy into a list, then choose one of those at random. Guessing a cell and retrying also works, but slows down badly once the board is nearly full. The list also gives you a win condition when it is empty.

Why is my snake faster on one computer than another?

It is moving once per frame instead of once per tick. Draw on every frame and move on a timer, so the pace is a number in your config rather than a property of the screen. Then a score means the same thing everywhere.

Where to go next#

Once a long snake is still readable at speed, publish it. The page it gets keeps the model and the prompt beside it, and a leaderboard gives people a reason to come back. Playing a few of the snake builds here first is the quickest way to feel which tick lengths work.

The general method is in how to make a game with AI. For another arcade game where one number decides whether it is fun, see the breakout guide. Prompts you can paste when something breaks are in the prompt guide, and the two player guide covers putting a second snake on the same board.