How the Meowdoku Solver Reads a Board From a Screenshot
The Meowdoku solver takes an unusual input: a picture of a puzzle rather than the puzzle itself. Before it can solve anything it has to work out where the board is in your screenshot, how many cells it is divided into, and which cells share a color. This is how each of those is decided, and where it still gets them wrong.
The hard part is not reading the colors
A Meowdoku screenshot is mostly not the board. There is a header, a row of rule chips, a timer, and usually a system status bar with somebody’s battery percentage in it. The board is a square block somewhere in the middle, at a position and size that depend on the phone it came from, and nothing in the picture is labelled.
Three unknowns have to be pinned down before a single color is worth reading, and missing any one of them does not make the answer slightly wrong. It makes it a different puzzle, confidently solved.
Everything runs in your browser
The screenshot is never uploaded. The image is drawn onto a canvas, the pixels are read back out of it, and every step below runs on that array of numbers inside your own tab. No server sees the picture, and no copy of it exists anywhere but on your device.
A picture you never send is one nobody has to store or promise you they deleted, and a pipeline with no network hop in it returns a board in well under a second.
The first thing it does is shrink the image so its longer side is at most 900 pixels. Nothing downstream wants more detail than that, since the goal is one representative color per cell rather than a sharp picture, and the per-pixel work falls with the square of the scale.
Step 1: find the board
The solver starts by guessing the page background. It samples the 7% strip around all four edges of the picture and takes the median of each color channel, dropping vivid pixels from the sample first so that a brightly colored banner clipping into a corner cannot drag the estimate off the real background.
Every pixel is then labelled background or not-background by its distance from that estimate, and the not-background pixels are counted row by row. That gives a density profile down the image: near zero through empty margins, high through the board, somewhere between through a header. Runs of high-density rows become candidates. The thin dips that cell boundaries carve into the profile get bridged, because a one-pixel grid line is not a gap, while the genuine space above the board does not, which keeps the rule chips out of the candidate.
Then comes the test that does the real work: squareness. Each candidate is scanned along the other axis for a left and right edge, and only those whose width and height land within about a third of each other, covering at least 3% of the frame, survive. Banners, chip rows and status bars are all wide and short. On a Meowdoku screenshot, the board is the one thing that is square.
When nothing square stands out, the solver assumes you already cropped to the board and uses the whole frame. That is a good failure to have: the picture it cannot localize is usually the picture that needed no localizing.
Step 2: count the grid
Knowing where the board is does not say whether it is a 7×7 or a 9×9. To settle that, the solver walks across the board box in 400 steps and measures at each step how much the color changed from the previous one, averaged over 48 parallel lines spanning the other axis so a single dark cat cannot pass for a boundary. Cell edges surface as regular peaks.
Rather than measure the spacing between peaks, it tests hypotheses. For every N from 4 to 12 it works out where that grid’s N−1 interior boundaries would fall, looks for a peak near each position, and scores the hypothesis on how well its boundaries are matched on average. The N that best explains the profile wins.
Both axes are measured independently and then reconciled, because a real board is square. If the horizontal pass says 8 and the vertical says 7, one of them missed a faint line, so the larger count is the one to believe.
Step 3: sample each cell on a ring, not at its center
This is the step that is not obvious. With the board located and the grid counted, the solver needs one color per cell, and the natural move is to read the pixel at the middle of the cell.
That is precisely the wrong pixel. The middle of the cell is where the cat sits, and where the ✕ sits on a cell you have ruled out. On a board that is partly solved, which is to say any board you would actually want help with, center sampling reads a large share of cells as cat-colored and invents regions that appear nowhere on your screen.
So each cell is sampled on three concentric rings instead, at 28%, 36% and 43% of the way out from its center, at sixteen angles each: forty-eight samples per cell. That annulus sits inside the cell boundary, so it never picks up a grid line, and outside the glyph, so no cat can hijack the reading. The samples are reduced by taking the median of each channel rather than the mean, which outvotes the few that land on an anti-aliased edge or a highlight instead of blending them in.
Step 4: cluster the colors into exactly N regions
Now there are N×N colors to sort into regions. That is a clustering problem, and clustering problems are usually hard in one particular way: you do not know how many clusters to look for, and guessing wrong ruins the answer quietly.
Meowdoku knows. The rules fix it. An N×N board is divided into exactly N connected regions, so a 9×9 board has nine, never eight and never ten. That single fact turns an open-ended question into a closed one, k-means with k already known, and it is why this step is dependable while the two before it are best-effort.
Two details keep it stable. Starting centers are chosen farthest-first, each new one being the color furthest from every center picked so far, which spreads the starting points across the hues actually present instead of leaving two to fight over the same pale yellow. And because that seeding is deterministic rather than random, one screenshot always yields the same board. A solver that answered differently on two uploads of one picture would be worse than none.
The region ids are then renumbered in reading order, so the region holding the top-left cell comes first. Nothing in the solving depends on it; the board just arrives numbered the way a person would number it.
Step 5: solve, and what a second solution tells you
With a grid of region ids and a size, solving is the straightforward part, running the same constraint solver the game uses to build boards. The interesting decision is that it asks for two solutions, not one.
A correctly read Meowdoku board has exactly one solution, because the generator guarantees that when it builds the board. So two solutions mean the board being solved is not the board in your screenshot, and some cell went to the wrong region. No solutions mean something was misread in the other direction and the constraints now contradict each other. Asking for a second answer turns the result into a verdict on the reading that produced it.
Where it fails, and why you can paint
Everything before step 4 is a best effort, and all of it can be beaten. These are the cases that actually come up:
- Two close hues in a compressed screenshot. Heavy JPEG artefacts can pull two region colors near enough together that k-means merges them, then splits some third region in half to keep the count at N.
- A photo of a screen instead of a screenshot. Shot at an angle, cells stop being evenly spaced, which breaks the assumption under both the grid count and the ring sampling.
- A crop that keeps part of the interface. Half a rule chip left in frame can push the board box a few pixels off, and near the edges that is enough to slide the rings into the next cell.
- A board that is nearly finished. The more cats and ✕ marks on it, the more of each cell is covered. The rings help a great deal here, but they are not magic.
The paint tool is the design, not the fallback
This is why every detected cell can be repainted by dragging across the board, and why the solver refuses to run until exactly N distinct regions are present, telling you how many you currently have. That guardrail catches the merge-and-split failure above before it can produce a confident wrong answer.
The board is also drawn back to you in the colors sampled from your own screenshot rather than in the game’s palette, so you can check the reading at a glance instead of trusting it. If a cell looks like the wrong color on our board, it is the wrong color, and one drag fixes it. Detection does the tedious ninety-odd percent; you supply the judgment for the rest.
Try it on a board of your own
Take a screenshot of a board you are stuck on, drop it into the solver, and watch which cells it gets wrong. The misreads are almost always in the places this article predicts.
The solver runs entirely in your browser. Screenshots are read on your device and are never uploaded.