You Might Also Like
Sorting Swap Puzzle Game — Free HTML CSS JS Snippet
Sorting Swap Puzzle Game · Games · Plain HTML, CSS & JS · Live preview
What's included
Features
About this UI Snippet
Sorting Swap Puzzle Game — Cycle-Decomposition Par, Live Inversion Count & An Optimal Auto-Solver

Sorting is the first algorithm everyone learns and the last one most people actually understand, because a lecture on bubble sort teaches the procedure without ever explaining what makes one arrangement harder than another. This snippet is a playable sorting puzzle that puts the two real measures of disorder on screen: the minimum number of swaps the current arrangement can possibly need, computed by decomposing the permutation into cycles, and the live inversion count, which is the quantity every adjacent-swap sort exists to drive to zero.
The minimum-swaps par is computed, not guessed
minSwaps() treats the bar arrangement as a permutation and decomposes it into cycles. Every element belongs to exactly one cycle — the chain formed by asking "where does this value belong?", moving there, and repeating until you arrive back where you started — and a cycle of length k always needs exactly k - 1 swaps to resolve. The minimum for the whole array is therefore n minus the number of cycles, which the function accumulates as it walks each unvisited position with a seen array. This is a genuine, provable lower bound rather than a hand-tuned difficulty number, and it is what makes "you sorted it in seven swaps, the minimum was five" a meaningful piece of feedback.
Inversions as the other measure of disorder
The header also shows the live inversion count: the number of pairs in the wrong relative order, counted by the straightforward O(n²) double loop. Watching it fall as you play makes a fact visible that bubble sort's proof depends on — a swap of adjacent elements removes exactly one inversion, so an array with 20 inversions cannot be sorted by fewer than 20 adjacent swaps no matter how cleverly you choose them. Seeing the two numbers side by side (minimum swaps and inversions) is the clearest possible demonstration that "how sorted is this" has more than one answer, and that the answer depends on which operations you are allowed.
An auto-solver that is optimal by construction
The Auto-solve button runs the placement algorithm rather than a textbook sort: find the first position holding the wrong value, look up where that value belongs, and swap it there. Because every such swap puts at least one value into its final position permanently, the algorithm can never exceed the cycle-decomposition minimum — and watching it step through at 420ms per swap makes the cycle structure visible, since each cycle resolves as a run of consecutive swaps before the solver moves on to the next.
Feedback baked into the rendering
render() rebuilds the bars from the values array on every change, deriving each bar's height from its value relative to the maximum, and marks any bar already standing in its final position with a settled class. That single visual cue converts an abstract goal into a concrete one — the player can see which bars are done — without giving away which swap to make next. Because everything on screen is derived from one array on each render, the display cannot disagree with the model.
Two-click swapping with a cancel
Selecting a bar lifts it and stores its index; selecting a second swaps them and clears the selection; selecting the same bar again cancels. Values are generated as distinct numbers so the permutation logic never has to break a tie between equal elements, and a freshly generated puzzle is reshuffled if it happens to come out already sorted.
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 an adjacent-swaps-only mode where the par becomes the inversion count instead of the cycle bound — playing the same board under both rule sets is the clearest possible demonstration of why the allowed operation determines the lower bound. Other extensions worth requesting: highlight the cycle a selected bar belongs to so the structure is visible before you solve it, add a race mode where a bubble sort and the optimal solver animate side by side with live swap counters, add a move-limited challenge that only accepts a minimum-swap solution, or extend the auto-solver into a step-through mode with a written explanation of each swap.
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 sorting puzzle game in plain HTML, CSS, and JavaScript — no frameworks or libraries.
Requirements:
- Render a row of bars from an array of distinct random values, with each bar's height derived from its value relative to the array maximum, and the whole row re-rendered from the array on every change.
- Let the player swap ANY two bars with a two-click select-then-swap flow, where clicking the selected bar again cancels the selection. Count the swaps.
- Compute and display the provable minimum number of swaps for the current arrangement using permutation cycle decomposition: walk each unvisited position following "where does this value belong" until the cycle closes, count the cycle length k, and add k - 1. The total is n minus the number of cycles.
- Also display a live inversion count (pairs in the wrong relative order) and explain in the UI copy that it is the minimum number of ADJACENT swaps — a different bound under different allowed operations.
- Mark any bar already standing in its final position with a distinct colour, so progress is visible without revealing the next move.
- Include an auto-solve button that runs an optimal algorithm: find the first position holding the wrong value, swap that value directly to its destination index, repeat. Animate it one swap at a time on an interval so each permutation cycle is visible as a run of consecutive swaps.
- On completion, report the player's swap count against the computed minimum. Generate distinct values so the destination lookup is unambiguous, and reshuffle if a new puzzle happens to be generated already sorted.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 two numbers in the headerMinimum is the provable fewest swaps this arrangement can be sorted in, computed by cycle decomposition. Inversions counts the pairs currently in the wrong relative order — a different measure of the same disorder.
- 2Click a bar to pick it upThe selected bar lifts and turns amber. Clicking it again cancels the selection, so a misclick costs nothing.
- 3Click a second bar to swapAny two bars can be swapped, not just adjacent ones, and the swap counter increments. Bars already standing in their final position are shown in green so you can see what is already done.
- 4Watch the inversion count fallThe status line reports the remaining inversions after every swap. A single adjacent swap can only ever remove one inversion, which is exactly why bubble sort needs so many passes.
- 5Compare your total against the minimumFinishing reports whether you hit the provable minimum or how far over it you landed. Matching the minimum consistently means you are recognising cycles rather than sorting by feel.
- 6Watch the optimal solverAuto-solve repeatedly sends the first misplaced value to where it belongs. Each swap permanently places at least one bar, so it always finishes at the minimum — and each run of consecutive swaps is one cycle resolving.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
By decomposing the arrangement into permutation cycles. Starting from each unvisited position, the code follows "where does this value belong" until it returns to the start, counting the cycle length; a cycle of length k needs exactly k - 1 swaps. Summing that across all cycles gives n minus the number of cycles, which is the provable minimum for arbitrary (non-adjacent) swaps.
Because they measure disorder under different rules. The minimum swap count assumes you can swap any two elements; the inversion count is the minimum number of ADJACENT swaps required, since one adjacent swap removes exactly one inversion. Seeing both makes it obvious that the difficulty of sorting depends on which operations are permitted — the insight behind why bubble sort is quadratic.
Yes, by construction. It finds the first position holding the wrong value and swaps that value directly to its destination, which places at least one element permanently on every swap. An algorithm that never wastes a swap and finishes cannot exceed the cycle-decomposition bound — and watching it run makes the cycles visible, since each one resolves as a run of consecutive swaps.
Because cycle decomposition needs an unambiguous "where does this value belong" lookup. Duplicate values would make the destination index ambiguous, so the generator produces distinct values (spaced tens with a small random offset) and the puzzle is reshuffled if it happens to generate an already-sorted arrangement.
Yes, and it ports cleanly because minSwaps(), inversions() and the solver step are pure functions of the array. Hold the values array, swap count and picked index in component state, derive the bar heights, the settled flags and both header numbers during render, and update with an immutable copy of the array rather than mutating in place. The auto-solve interval belongs in an effect with a cleanup (useEffect return, onUnmounted, ngOnDestroy) so it stops if the component unmounts mid-solve.