DEV Community

Devanshu Biswas
Devanshu Biswas

Posted on

How a Match-3 game is really just one 8x8 grid of numbers

Match-3 games look busy. Gems sparkle, lines explode, whole columns rain down and combos stack up while a number in the corner sprints upward. For years I assumed there was something genuinely complicated hiding behind all that motion. Then I sat down to build one for day 26 of my build-a-game-a-day run, and the whole thing collapsed into something almost embarrassingly small: an 8x8 grid of little integers and about seven short functions that read and rewrite them. Everything else is animation.

Here is the core idea. A gem is not a picture. A gem is a number. Red is 0, orange is 1, and so on up to five. The board is a two-dimensional array of those numbers, and the pretty tiles you tap are just how the numbers get drawn on screen. Once that clicks, every rule in the game turns into a tiny operation over the array, and none of them are hard on their own.

Start with the only thing the player ever does: swap two gems that share an edge. That is three lines of code to exchange two array values, plus a check that the two cells are exactly one step apart so you cannot swap across the board or on a diagonal. Tap a gem to pick it up, tap a neighbour to swap. That is the entire interaction. Everything dramatic that follows is a consequence the game computes, not an action the player takes.

The rule that defines the whole genre is that a swap is only allowed if it lines up three or more of the same colour. The clean way to enforce that, without a pile of special cases, is a trick I liked a lot: do the swap first, then run your ordinary match detector on the result. If it finds a run, the swap was legal, so you keep it. If it finds nothing, you swap the two gems straight back and the move is refused. The validator and the detector are literally the same code.

So what is match detection? It is a run-length scan, the same one you would write to compress a line. Walk along a row counting how many equal colours you have seen in a row; the moment the colour changes, if the run reached three or more, flag every cell it covered. Do that across every row, then down every column, recording hits in a boolean grid. Because both passes write into the same grid, an L-shape or a plus where a horizontal run overlaps a vertical one just works, no extra logic required. Clearing the flagged cells is then trivial: write a sentinel value like -1 into each one to mark it empty. That is also the natural moment to score, because the number of cells you emptied is the size of the combo.

Now gravity. Clearing leaves holes, and gems above them should fall. Handled one column at a time, this is lovely: read the column from the bottom up, collect every gem that is not a hole into a list, then write that list back starting from the bottom row. The survivors settle as low as they can, in order, and every remaining slot at the top gets a fresh random gem. Fall and refill are the same pass.

The refill is where the game comes alive, because the new gems might accidentally line up matches nobody planned. So resolving a move is not one step, it is a loop: find matches, clear, apply gravity, and scan again. Each turn of that loop is one link in a cascade, and a single well-placed swap can topple three or four clears in a row. To make it pay off, I multiply the points per gem by the current cascade level, so the second clear is worth double, the third triple. That rising multiplier is the entire reward loop of the genre in one line.

The last piece is fairness. Eventually a board can reach a state where no swap makes any match at all, a dead board. Rather than trapping the player, I brute-force probe every possible swap, check, and undo. If none of them produce a match, I reshuffle the existing gems and test again, repeating until the new layout both has at least one legal move and contains no free matches sitting there. Always a move, never a freebie.

That is the whole thing. No engine, no framework, no assets, just vanilla JavaScript running offline in the browser. You can play it, step through the concept, and read every function here: https://dev48v.infy.uk/game/day26-match-3.html

Tomorrow: Tower of Hanoi, and the recursion that solves it in one line.

Top comments (0)