Sorting Swap Puzzle Game — Free HTML CSS JS Snippet

Sorting Swap Puzzle Game · Games · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Provable minimum swap count computed by permutation cycle decomposition (n minus the number of cycles)
Live inversion count showing the other standard measure of array disorder
Optimal auto-solver that places at least one value per swap, so it can never exceed the minimum
Stepped solver animation that makes each permutation cycle visible as a run of consecutive swaps
Bars already in their final position marked, giving progress feedback without revealing the next move
Arbitrary pair swapping with a two-click select-and-swap flow and a cancel on re-click
Distinct generated values, so the permutation logic never has to break ties between equal elements
Freshly generated puzzles reshuffled if they come out already sorted

About this UI Snippet

Sorting Swap Puzzle Game — Cycle-Decomposition Par, Live Inversion Count & An Optimal Auto-Solver

Screenshot of the Sorting Swap Puzzle Game snippet rendered live

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:

text
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

  1. 1
    Read 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.
  2. 2
    Click a bar to pick it upThe selected bar lifts and turns amber. Clicking it again cancels the selection, so a misclick costs nothing.
  3. 3
    Click 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.
  4. 4
    Watch 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.
  5. 5
    Compare 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.
  6. 6
    Watch 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

Teaching sorting, permutations and lower bounds
Most sorting lessons cover procedures; this one covers the structure of the problem — cycles, inversions, and why a lower bound exists at all. It pairs naturally with a stack and queue visualizer or a binary search tree visualizer in an algorithms teaching sequence.
Algorithm interview preparation
Minimum swaps via cycle decomposition is a recurring interview question, and playing the puzzle a dozen times builds the intuition far faster than reading the solution — the cycles become something you can see rather than derive.
Daily puzzle feature or waiting-screen distraction
A round lasts under a minute and has a natural score to beat (the minimum), which makes it a good fit for a daily-puzzle slot or a loading-screen diversion that happens to teach something.
Bar-chart interaction pattern with derived rendering
Heights derived from values relative to the maximum, a settled state per bar, and a full re-render from one array on every change make this a compact reference for any interactive chart where the data is edited in place.
Reference implementation of cycle decomposition
The seen-array walk in minSwaps() is the canonical way to decompose a permutation, and it appears well beyond sorting — in scheduling, in matching problems, and anywhere a set of items must be rearranged with a minimum number of moves.
Reordering UI with an optimality score
Products that let users reorder a list — playlists, priority queues, seating plans — can borrow the idea of scoring a rearrangement against its theoretical minimum, turning a mundane drag-and-drop into something with feedback.

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.