How to Build a Times Table Game With No Instructions
Here’s how to build a times table game that needs no instructions. What I asked for was “mash up all the classic games.” What I ended up with was falling multiplication. In between, the design got thrown out three times. This is the second experiment after the trot vending machine, and you can play the result at Times Table Drop.
Attempt 1: cramming five games into one board
Sudoku, minesweeper, times tables, Tetris, and memory match, fused into a single rule set. You drop Tetris pieces onto a sudoku board. Mines hide underneath it. Step on one and a multiplication question decides whether you defuse it. The mine positions flash for a few seconds at the start and then vanish, so you have to remember them.
On paper it held together. The five games weren’t bolted on next to each other — they actually fed into one another. The problem was the cost of understanding it. The rules panel needed a scrollbar. I had built a game you have to study before you can play.
The verdict came back in four words: this is too complicated.
Attempt 2: down to three games, still all luck
Memory match, with times tables and minesweeper layered on. Flip cards to pair 4×6 with 24, and lose a heart when you flip a bomb. This one genuinely needed no explanation. Show anyone a grid of face-down cards and they’ll start pairing. Show them a bomb and they’ll know it’s bad.
But it wasn’t fun. Four bombs, three hearts — and because a flipped bomb turned back over, the same bomb could kill you three times. You died from pure luck in the early game, when you had no information at all.
My first fix was more hearts and leaving triggered bombs face-up. That stopped the repeat deaths. The verdict didn’t change: too luck-based.
The real problem: I imported the punishment and left the fun behind
That’s when I realized I’d been diagnosing it wrong. This was never a numbers problem.
Minesweeper isn’t about mines. It’s about the number clues. Deducing which squares are safe from “two mines nearby” is the entire game — after the first click it’s essentially a logic puzzle. You win by reasoning, not by luck.
What I had imported was the bomb and the lost life. The punishment, and nothing else. I threw away every clue you’d reason with. Of course all that remained was luck. Adding hearts was a bandage over that.
Attempt 3: a structure luck can’t get into
So I removed hidden information entirely.
A falling block reads 6×7. Along the bottom sit five answers, one of which is 42. Tap a column to slide the block there; land it on the right one and it clears. Land it wrong and it stacks. Stack to the ceiling and you’re done.
Luck is designed out:
- Every piece of information is on screen from the start. Nothing is hidden
- The falling expression’s answer is always one of the five labels. There is no unanswerable question
- The starting column is never the correct one, so there are no free points for doing nothing
I also gave mistakes a way back. A wrong stack shrinks by one block every time you answer that column correctly. One mistake isn’t a death sentence — the way back stays open. That’s the exact opposite of what the bombs did in attempt 2.
Then came one more note: if the answers never change, you stop doing mental math and start pattern-matching positions. So now hitting the same number twice swaps it for a new one. The two hits arrive as 4×9 and 9×4, the commutative pair. A small dot appears under a number you’ve hit once, which tells you it’s one hit from changing without a single word of explanation.
Debugging story 1: one variable name killed the whole script
I added the number-swapping feature, reloaded, and the game did nothing at all. The browser console printed zero errors.
Poking at variables in the console, every function came back undefined, and labels resolved to a DOM element instead of an array. That was the giveaway. Elements with an id land on the global object, which meant my script had never run at all.
The cause: a new variable named f collided with the existing const f = $('#faller'). It was a syntax error, so the script failed to load — which is exactly why nothing showed up at runtime. A silent console doesn’t mean things are fine.
Pulling the script out and running node --check caught it instantly.
SyntaxError: Identifier 'f' has already been declared
Debugging story 2: I left my own debug value behind
While testing left/right movement, the block kept falling and getting in the way, so I set its speed to zero from the console. Then I never set it back.
A moment later: “why doesn’t it fall anymore?” The file was fine. My debug value was just still sitting in the live page — and the preview pane was holding onto that document, so reloading didn’t clear it either.
If you change state to verify something, change it back. Otherwise you hand someone a working build and let them think it’s broken.
Porting it into the site
I built the game as a standalone HTML file first and moved it into the site afterward. Two things needed rework.
Styles, first. Astro scopes a component’s <style> automatically — but this game builds its answer labels and stacked blocks in JavaScript. Elements created later never get the scoping attribute, so the CSS simply doesn’t apply to them. I moved the game’s internal styles to global and scoped them by hand with a .tt prefix on every selector.
Buttons, second. They were wired as onclick="move(-1)", which only works if the function is global. I wrapped the whole game in an IIFE so it owns no globals, and rewired the buttons with addEventListener. Not one game variable leaks into the page now.
The result
It’s live at Times Table Drop. There are no instructions anywhere on the page. A purple multiplication falls, five teal numbers sit at the bottom, and that’s enough.
It speeds up every ten clears. Arrow keys on a desktop; on a phone, just tap the column with the answer.
What I took from it
The lesson was that knowing what to cut is much harder than knowing what to add.
The five-game version was the most intricate thing I designed — all five mechanics genuinely interlocked. It was also a game nobody wanted to play. The current version has a one-line rule, and because of that, people actually play it.
The other lesson: when someone says it isn’t fun, don’t reach for the numbers first. Four bombs against three hearts was never the problem. Having nothing to reason with was. Diagnose it wrong and you can tune forever without moving.