You Might Also Like
Robot Loop Programmer Game — Free HTML CSS JS Snippet
Robot Loop Programmer Game · Games · Plain HTML, CSS & JS · Live preview
What's included
Features
About this UI Snippet
Robot Loop Programmer Game — Block Programs With Repeat Counts, Stepped Interpretation & Crash Reporting

Sequencing, loops, and debugging are the first three ideas in programming, and all three are far easier to feel than to read about. This snippet is a small visual programming game built around exactly those ideas: the player assembles a program from Forward, Turn-left and Turn-right blocks, raises the repeat count on any block, presses Run, and watches a robot execute the program one step at a time across a grid of walls toward a flag. When the robot crashes, the block that was executing is highlighted — which is the whole debugging loop in miniature.
Repeat counts instead of a repeat block
Rather than a nested loop construct, each block carries a times count that the player raises by clicking it. F ×4 is a loop, expressed in the way beginners meet loops first: "do this thing four times". It also creates a genuine optimisation pressure, because every level shows a par block count — solving a spiral with eight separate Forward blocks works but misses par, while four blocks with counts clears it. That gap between "it works" and "it is concise" is the loop lesson, made visible without any syntax to learn.
Expansion, then interpretation
expand() flattens the block list into a list of single steps, each remembering the index of the block it came from. The interpreter then walks that flat list on a setInterval, applying one step per tick — which is what makes the execution watchable rather than instantaneous, and is also how a real stepping debugger works. Because each step retains its source block index, the UI can highlight the currently executing block and, on a crash, mark the exact block that failed. Separating expansion from execution keeps both halves simple: the interpreter never has to think about repeat counts, and the expander never has to think about walls.
Direction as modular arithmetic
Heading is stored as an integer 0-3 indexed into a DIRS table of row/column deltas. Turning right is (dir + 1) % 4 and turning left is (dir + 3) % 4 — adding three rather than subtracting one, which avoids the negative-modulo trap where (0 - 1) % 4 evaluates to -1 in JavaScript rather than 3. The robot's on-screen rotation comes from the same integer via rotate(dir * 90deg), so the sprite can never point somewhere the model disagrees with.
Failure that names the cause and the culprit
applyStep() returns a result object rather than a boolean: { ok: false, why: 'Hit a wall' } or 'Drove off the edge'. The runner stops the interval immediately on a failure, adds a crash class to the robot, marks the offending block red, and prints both the reason and the block number. Distinguishing the two failure modes matters pedagogically — driving off the edge means the program went too far, hitting a wall means it turned too late, and those are different fixes.
A step ceiling as a runaway guard
Because repeat counts can reach nine per block, a program can easily describe hundreds of steps. MAX_STEPS rejects any program whose expanded length exceeds the ceiling before execution begins, which is both a practical guard against a several-minute animation and an honest introduction to the idea that a loop needs a bound. Levels are plain ASCII maps — . floor, # wall, S start, G goal — parsed at load, so adding a level means drawing one, not writing coordinates.
Build with AI
Build, Understand, Optimize, and Extend It With AI
Paste this snippet into an AI assistant like Claude and ask it to add a step-through debugger — a Step button that advances the interpreter one instruction at a time with the robot state visible between steps — which turns the game into a genuine introduction to how debugging works. Other natural extensions: add a nested repeat block that wraps a sub-sequence so the loop concept generalises beyond a per-block count, add collectibles the program must gather in order before reaching the flag, add a "function" block that stores a reusable sub-program to introduce procedures, or add an undo stack for program edits. The expansion-then-interpretation split makes each of these easier than it sounds.
Prompt to recreate it
Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:
Build a playable block-programming robot game in plain HTML, CSS, and JavaScript — no frameworks or libraries.
Requirements:
- Levels authored as plain ASCII maps (an array of equal-length strings using . for floor, # for wall, S for start, G for goal), parsed at load time so start and goal coordinates are never written by hand. Each level also carries a plain-English goal and a par block count.
- A palette of Forward, Turn-left and Turn-right blocks that append to a program strip. Clicking a block in the program cycles its repeat count from 1 to 9 and back; right-clicking removes it.
- Two-phase execution: first expand the blocks into a flat list of single steps where each step remembers the index of the block it came from, then interpret that list one step per interval tick so the run is watchable.
- Highlight the currently executing block during the run, and on a crash stop immediately, mark the failing block, and report a distinct reason for hitting a wall versus driving off the edge.
- Store the robot's heading as an integer 0-3 indexed into a table of row/column deltas. Turn right with (dir + 1) % 4 and turn left with (dir + 3) % 4 — never (dir - 1) % 4, which returns a negative index in JavaScript. Drive the on-screen rotation from the same integer.
- Reject programs whose expanded step count exceeds a MAX_STEPS ceiling before execution begins, as a runaway guard.
- On finishing, win only if the robot is standing on the goal cell, and report the block count against the level's par so players are pushed toward repeat counts rather than repetition. Include at least five levels, with the later ones only reaching par if counts are used.Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.
Step by step
How to Use
- 1Read the level and find the flagThe purple-bordered line describes the challenge and the board shows walls in grey, the flag in purple, and the robot as an arrow pointing in its current heading — it always starts facing right.
- 2Add blocks from the paletteForward, Turn ↺ and Turn ↻ append a block to your program. The program strip below shows the sequence you have built and the block count against the level's par.
- 3Click a block to raise its repeat countClicking a block in the program cycles its count from 1 up to 9 and back around, so F ×4 replaces four separate Forward blocks. Right-clicking a block removes it.
- 4Press Run and watch it executeThe program is flattened into single steps and executed one every 300ms, with the currently running block highlighted — the same stepped execution a debugger gives you, which is what makes a mistake visible rather than mysterious.
- 5Read the crash reportIf the robot hits a wall or drives off the edge, execution stops immediately, the robot turns red, and the block that was executing is marked — along with whether the cause was a wall or the edge, which point to different fixes.
- 6Beat par to advance wellReaching the flag clears the level and reports your block count against par. Levels four and five are built so that solving at par genuinely requires repeat counts rather than repetition.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
A count on a block is how beginners first meet iteration — "do this four times" — and it needs no nesting UI, no drag targets, and no block-scope rules. It still creates the real lesson: every level has a par block count, and the later levels only reach par if you use counts instead of repeating blocks, which is exactly the trade a loop exists to make.
expand() flattens the blocks into a flat list of single steps, and each step stores the index of the block it came from. The interpreter walks that list one step per tick, so when applyStep() returns a failure the runner already knows which block produced the failing step and can mark it red while reporting the reason.
Because JavaScript's % operator returns a negative result for negative operands: (0 - 1) % 4 is -1, not 3, which would index outside the direction table. Adding 3 is congruent to subtracting 1 modulo 4 and always stays non-negative, so the heading integer remains a valid index without any extra branching.
Push an object onto LEVELS with a goal string, a par block count, and a map: an array of equal-length strings where . is floor, # is a wall, S is the start and G is the flag. parseMap() reads the start and goal positions out of the characters at load time, so no coordinates need to be written by hand and the grid size is derived from the map length.
Yes. Keep LEVELS, DIRS, expand() and applyStep() in a plain module — they are all pure data and pure functions. Hold the program array, robot position and running flag in component state, and render the grid, program strip and robot position from that state. The one thing to get right is the interval: start it in an effect when running turns true and clear it in the cleanup (useEffect return, onUnmounted, ngOnDestroy) so a level change or unmount cannot leave the interpreter ticking.