There is a little handheld game from the 90s where a 5x5 grid of lights stares back at you, some on, some off, and your only job is to switch them all off. It sounds trivial until you press your first button. You tap a lit tile expecting it to go dark, and instead it flips itself and its four neighbours: up, down, left, right. The one you wanted off might go off, but now three others just came on. That single rule turns a childish premise into something that has fascinated mathematicians for decades. Today I rebuilt it from scratch as Day 24 of GameFromZero, and it turned out to be one of the most satisfying small projects I have shipped.
You can play it here: https://dev48v.infy.uk/game/day24-lights-out.html
Let me walk through how it comes together, because the whole thing is shorter than you would guess.
The board is nothing more than a grid of ones and zeros. One means on, zero means off. Because there are only two states, flipping a light is just XOR with one, and that tiny fact does a lot of heavy lifting later. A press walks a fixed "plus" shape, the tile you clicked plus its four orthogonal neighbours, and XORs each of them; anything off the edge is skipped, so a corner press touches three tiles and an edge press four. The win check is the most boring function in the codebase: scan the grid, and if no ones are left, you win. That is the entire game loop.
The first thing that trips people up is generating a puzzle. The naive instinct is to fill the grid with random bits. Do not do this. On a 5x5 board only about a quarter of all random patterns can ever be turned off, so three times out of four you hand the player an impossible puzzle and they never know whether they are stuck or the game is broken. The fix is to work backwards: start from a fully solved, all-off board and apply a handful of random presses. Since every press is a legal move, pressing those same tiles again would undo them, so a solution is guaranteed to exist by construction. It is the same trick used to scramble a solvable Rubik's cube: never build the mess directly, always build it out of legal moves.
Now the fun part. Two facts make solving Lights Out feel like a magic trick once you see them. First, the order you press tiles in does not matter at all. This falls straight out of XOR being commutative and self-inverse. Pressing A then B lands you in the same place as B then A, and pressing the same tile twice cancels out completely. So a solution is not a sequence of moves, it is simply a set of tiles, each pressed once or not at all. Second, because of that, there is a mechanical way to solve almost the whole board called light chasing. You sweep from the second row downward, and whenever the tile directly above you is still lit, you press your current tile to switch it off. Once you have passed a row, nothing below can ever light it up again, so after one top-to-bottom pass every row except the very top is guaranteed dark, and you never had to make a single decision.
That leaves only the top row, and here is where I originally tripped. The classic trick is a lookup table that maps the leftover top row to the tiles you should have pressed first. I hardcoded a small version of that table, and my Node verification harness immediately caught that it only cleared about a quarter of boards. The table was incomplete and, frankly, fiddly to get right. The cleaner solution is to realise the top row is your only free choice. On a five-wide board that is just thirty-two possible combinations, so I try every one: press that combination, chase down, and keep whichever leaves the board completely dark. It is guaranteed to find the answer for any solvable board, and it works for the 3x3 mode too without a second table. Sometimes the general approach is genuinely simpler than the clever one.
Underneath all of this is a single beautiful idea: Lights Out is a system of linear equations over GF(2), the field with only zero and one where addition is XOR. Each tile gives you one equation about the parity of presses that touch it, and solving the puzzle is solving a matrix equation with ordinary Gaussian elimination, swapping every plus for an XOR. That is why order never matters and why a solution is a set. On a 5x5 the press-matrix is invertible, so every board is solvable and its solution is unique. On other sizes the matrix can be singular, which is exactly why some boards become impossible and others have many solutions.
The demo has three tabs. LOOK is the playable puzzle with New, Reset, Solve and a 5x5 / 3x3 toggle. UNDERSTAND breaks the whole thing into ten steps with the reasoning behind each. BUILD walks you through writing it yourself in about ninety lines of vanilla JavaScript, no frameworks and no build step.
Tomorrow is Day 25: Nonogram, the picture-logic puzzle. If you have never noticed how much real mathematics hides inside a toy, Lights Out is a lovely place to start.
Top comments (0)