AgentGames

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

🧩 Guide

How to make a puzzle game with AI

A randomly generated puzzle board has no solution often enough to ruin the game, and the player cannot tell it apart from a difficult one. Write the levels out as text and that whole class of bug disappears.

Updated 5 October 2026 8 min read By the Agent Games team
Jump to a section
  1. Four steps to a puzzle that always has an answer
  2. Why random levels wreck a puzzle game
  3. A level is a few lines of text
  4. If you must generate, work backwards
  5. Undo, and why only a puzzle needs it
  6. Count moves, not seconds
  7. Common questions
  8. Where to go next

Hand the model the levels. Write them yourself as short strings, one character per tile, and pass them in as an array. The grid code around them is ordinary and any of the three big models will write it. The levels are the actual game, and a board invented at random is the one thing that will spoil it.

A random board is not a hard board

Scatter walls and blocks into a grid and some of what comes out has no solution. From the player's chair those boards look identical to the brutal ones. So they push at it, get nowhere, and quietly conclude the fault is theirs. An authored level cannot fail that way, because you solved it before anyone else saw it.

Four steps to a puzzle that always has an answer#

Draw five levels before you write a line of code

Each one is a handful of text rows. Sketch them, solve each by hand, and keep the solutions. Those strings are what you paste into the prompt.

Send the prompt below with your own levels inside it

The model fills in the grid, the pushing rules and the win check. That part is not where puzzle games go wrong.

Play every level through once

You already know the answer, so you are testing the rules rather than the puzzle. Watch for a push that should be blocked and a win that fires early.

Get undo working before anything else

Without it a stuck player restarts, loses ten correct moves, and leaves. Undo is cheap now and awkward to retrofit later.

PromptCopy this, paste it, send it
Build a grid based block pushing puzzle as ONE self-contained .html
file. Canvas only, no frameworks and no images.

LEVELS: a LEVELS array. Each level is an array of strings, one
character per tile: # wall, . floor, * target, o block, @ player.
Use exactly the levels I paste below and nothing else. Do NOT write a
level generator and do NOT fill any grid from a random number.

[paste your own levels here]

RULES: arrow keys and WASD move the player one tile. Walking into a
block pushes it one tile when the tile past it is clear floor,
otherwise nothing at all moves. Two blocks in a row never move.

WIN: the level is finished when every target tile is covered by a
block. Show a short line of text and a key to go to the next level.

UNDO: keep a stack holding a copy of the board and the move count for
every move made. Z pops one off and restores it. R clears the stack and
reloads the level. Both keys must still work after the level is won.

HUD: level number and moves taken. No clock and no countdown anywhere.

PHONE: a swipe in a direction moves the player one tile. Put
canvas { touch-action: none; } in the CSS so swiping cannot scroll the
page underneath.

Drive any tile to tile slide animation from the number of seconds that
passed since the previous frame, and clamp that number to a maximum of
0.05 so a tab coming back from the background cannot skip a move.
Collect every value worth tuning, tile size, palette, slide duration,
into one CONFIG object at the top of the file.

Swap the LEVELS block for your own strings and leave the rest alone. The two lines refusing a generator are doing real work. Without them, a model asked for a puzzle game will often add one, because a generator looks like the more impressive answer.

Why random levels wreck a puzzle game#

Randomness is fine in an arcade game. A wave of enemies that arrives in a different order each run is variety. A puzzle has no such slack, because a puzzle is a promise that an answer exists. Break that promise once and every later level is suspect.

Random board against authored board The same puzzle, generated once and written out by hand once. Generated grid[y][x] = wall if random is lowsome boards have no solution at allthe player cannot tell which is whichso they decide they are bad at it Authored LEVELS = [ #####, #@o*.#, ##### ]you solved every one before shippinghard is hard and broken is impossibleand editing a level means editing a line A generator that cannot prove a board is solvable has not saved you any work.
The failure is not that random boards are bad. It is that the player has no way to tell a bad one from a good one, so a single unsolvable board poisons the rest.

Consider what an unsolvable board does to the person playing it. They try the obvious route and it fails. They try a second. By the fourth they are no longer solving a puzzle, they are deciding whether to trust you. Most people decide no, and the ones who stay feel stupid for a reason that was never their fault.

It also hides from you. You test the first few boards, they happen to work, and you ship. The generator keeps producing. Somebody reaches a dead board on their sixth attempt and you never hear about it, because the complaint a player makes is that the game got too hard.

  • Difficulty you cannot aim. A generator gives you noise, not a curve. Your opening board can be harder than your last one, and the reader meets the wall before they have learned the rules.
  • Bugs you cannot reproduce. When a board only exists for one run, a report of odd behaviour on it is a report about nothing. Numbered levels mean you can open the one that broke.
  • No shared experience. Two people cannot argue about a level that neither of them can show the other. Fixed levels are the thing people send each other.

A level is a few lines of text#

One character per tile is the whole trick. The level reads as a picture in your editor, so you can see the shape of the problem while you type it. Adding a wall is typing a hash. Moving a target is moving one character sideways.

jsPush right, then push up, and both targets are covered. You knew that before the model wrote a line, which is exactly the property a generator cannot give you.
// # wall    . floor    * target    o block    @ player
const LEVELS = [
  [
    "########",
    "#..*...#",
    "#..o...#",
    "#.@o*..#",
    "#......#",
    "########",
  ],
  // next level goes here
];

Keep a strict rule about the characters. Every level is the same width, padded with walls, and the parser rejects anything it does not recognise instead of guessing. A silent fallback to floor turns a typo into a level that is subtly wrong, and those take an hour to find.

Order them deliberately. Your first board should teach one rule with no way to fail, the second should combine two, and the one after that should be the first that needs a moment of thought. That sequence is authoring, and it is the part of a puzzle game no model can do for you, because it depends on what the player has already seen.

If you must generate, work backwards#

There is a legitimate way to generate boards, and it is the opposite of the obvious one. Start from the finish. Place every block on a target, drop the player next to one, and then undo moves instead of making them.

In a pushing puzzle the reverse of a push is a pull. The player stands next to a block and steps away from it, dragging it along. Walk a random sequence of those pulls and you reach a scrambled board. That board is guaranteed to have an answer, because you just walked the answer in reverse.

  1. Build the solved state by hand: walls where you want them, blocks sitting on targets.
  2. Pick a random legal reverse move and apply it. Repeat for as many steps as you want.
  3. Throw the result away if the blocks are still on their targets, or if the board never changed.
  4. Store the board that survives as a plain array of strings, next to your hand written ones.

The catch is that the length of your reverse walk is not the difficulty. A walk can wander away and amble back, leaving a board that takes two moves to finish. If you want a difficulty dial you need to measure the shortest solution with a search, and at that point you are writing a solver. Worth it for a daily board, not worth it for a game with a handful of levels.

The same shape of argument applies to any genre where content has to be valid rather than merely varied. A maze built by carving paths is always connected. A word game built on a list you checked is always fair, which is the subject of the word game guide.

Undo, and why only a puzzle needs it#

An arcade game does not want undo. The mistake is the content there, and taking it back takes the game with it. A puzzle is the reverse. The player is thinking, and thinking means trying a line, seeing it fail, and backing out. Without undo they cannot think, so they guess.

What a single undo has to put back Undo is the one thing a puzzle game cannot ship without. 1 Player position The tile the player stood on before the move. 2 Every block that moved A push moves two things. Restoring one is a bug. 3 Move count It goes down by one. Players notice when it does not. 4 Solved state Undoing out of a finished board has to unfinish it. 5 The whole small grid Copy the board per move. Do not store a difference. Restart is free once undo works properly: it is undo, all the way back.
A half finished undo is worse than none, because the player trusts it and loses a position they cannot rebuild. Restore the whole board or do not offer the key.

Boards are tiny, so do not be clever. Copy the entire grid onto a stack before each move and pop it on undo. A list of inverse moves sounds tidier and is where the bugs live, since every rule you add later needs its own inverse. Copying costs nothing you can measure on a grid this size.

Two details get missed often enough to be worth naming. Undo has to work after the win banner appears, or a player who stumbles into a solution cannot go back and find the clean one. And the move counter has to go down, because a counter that keeps climbing turns undo into a punishment.

Count moves, not seconds#

A clock on a puzzle changes what the game is about. It asks the player to hurry, and hurrying is the opposite of the activity. Worse, a clock rewards the person who has already seen the level, so it quietly turns a thinking game into a memory test.

The HUD showsWhat the player doesWhat it does to the game
A countdownRushes, then stops thinkingPressure takes the place of the puzzle
Elapsed timeWatches the clock, not the boardA clock asks to be beaten rather than solved
Move countLooks for the shorter routeThe second attempt becomes the real game
Moves and a par scoreReplays a level already finishedMastery gets somewhere to go
Nothing at allFinishes it and wanders offNo second run, because nothing can improve

A move counter and a par figure per level is the smallest thing that gives a solved puzzle a reason to be played again.

Par is easy to set once levels are fixed. Solve your own board well, write that number next to the level, and show it in the corner. Players will beat it, and the ones who beat it by a long way have found something you did not, which is the best bug report a puzzle game gets.

🧩Puzzle games written by AI

Common questions#

Can AI make a puzzle game?

Yes, and it writes the mechanical half well. Grid, movement, pushing, win check, undo stack: all of that comes out in one pass. What it cannot do is decide which boards are interesting, so supply the levels yourself and let the model build the machine that runs them.

Why should I not let the AI generate puzzle levels?

Because a generated board is sometimes unsolvable and the player has no way to know. They read a broken board as a hard one, blame themselves, and stop trusting every later level. A fixed list of authored levels removes the whole failure mode for the cost of some typing.

How do I generate levels safely if I really want to?

Generate backwards. Start from a solved board and apply legal moves in reverse, which for a pushing puzzle means pulling blocks off their targets. Any board you reach has a solution by construction, because the route you walked to get there is the answer, reversed.

How do I store a level so I can edit it by hand?

As an array of strings, one character per tile, padded to the same width. It renders as a picture in your editor, so you can read the board while you write it. Have the parser reject unknown characters rather than treating them as floor.

Does a puzzle game need undo?

Yes. A puzzle is solved by trying a line and backing out of it, and a player who cannot back out guesses instead. Copy the whole board onto a stack before each move, restore it on undo, and make sure the move count goes down and the win state clears.

Should I add a timer to my puzzle game?

Not by default. A clock asks the player to hurry, which is the opposite of what a puzzle is for, and it rewards memory over thought on a replay. A move counter with a par score per level gives the same reason to come back without pushing anybody to rush.

Where to go next#

Once your five levels hold up, publish it. The page it gets records which model wrote the code and the prompt behind it, so somebody can read how the thing was made before they play it. Levels six onwards are the easiest work you will ever do on it, because adding one is adding a few lines of text.

The general method, and how to report faults back to a model without starting over, is in how to make a game with AI. For a puzzle made of language rather than a grid, read the word game guide. For one where difficulty has to track the player, read the math game guide. Ready made prompts sit in the prompt guide, and the puzzle games here are worth a few minutes first.