Overview
A faithful Minesweeper clone in JavaFX. 16×12 grid, 50px tiles, mines sprinkled at 20% density, click to reveal, cascade through every empty cell touching another empty cell until the wave hits a numbered border. The whole thing is one Java file and a couple of sound clips — no FXML, no scene-builder, no game engine. The interesting part isn't that Minesweeper got built; it's the small recursive routine in the middle that does the cascading reveal, which is the algorithm every implementation has to get right.
Interesting bits
The reveal pass is the part worth pointing at. When you click a tile with zero adjacent mines, the game has to open every connected empty tile and the numbered border around that region — in one click. It's a flood fill, and the cleanest way to write it is the way that almost looks too simple:
public void open(Tile t) {
if (t.isOpen) return;
t.isOpen = true;
t.text.setVisible(true);
t.border.setFill(null);
if (t.text.getText().isEmpty())
neighbours(t.x, t.y).forEach(e -> open(e));
}
That's the entire algorithm. Three things make it work:
The
if (t.isOpen) returnguard turns a recursion that would loop forever on a connected region into one that terminates the moment every reachable empty tile has been touched once.A tile with at least one neighbouring mine has non-empty text, so the recursion opens it but doesn't recurse past it. That's how the flood "stops at the border" without any explicit boundary check.
Every tile's number is filled in at board setup — one pass over the grid, counting bombs in the 8 neighbours. The reveal step doesn't compute anything; it just makes things visible.
The neighbour function is the boring half: eight conditional adds with
edge guards on x == 0, x == width - 1, y == 0, y == height - 1.
Every Minesweeper writes this function. The recursion is what makes
the game feel alive on the first click.
What this version skips, that fuller implementations include:
first-click safety (the very first tile you click should never be
a mine — usually solved by deferring mine placement until after the
first click, or by relocating any mine that lands under the click), a
flag/right-click mode, and a proper win condition (count
non-mine tiles opened, win when it equals total non-mine tiles). Mine
placement here is plain Math.random() < 0.2 per tile, so the bomb
count varies each game — a real version pins the count and shuffles
positions.
Stack and shape
JavaFX, programmatic UI, no FXML. The board is a Pane with one
StackPane per tile; each tile stacks a Rectangle (the border /
fill) under a Text node (the number or "X"), and the click handler
lives on the StackPane itself. Translation rather than a GridPane
because position is x * tileSize arithmetic — simpler than fighting
grid constraints. Two AudioClips for click and bomb sounds, played
inline from the reveal handler.
What I'd change
Picking this up again, the rewrite would keep the recursion and fix the rules around it.
- Fixed mine count, post-first-click placement. Pick a number (e.g. 24 mines), shuffle positions across the grid, and only commit the layout after the first click so the opener is guaranteed safe.
- Right-click to flag. Two-state cells (hidden, flagged) with a separate handler; the win check ignores flagged-but-unrevealed tiles.
- Real win/lose flow. Track opened-non-mines count, end the game when it equals total non-mines, reveal all mines on a loss, lock input, offer a reset.
- Iterative flood fill. The recursion is fine for an 800×600 board, but a queue-based BFS scales to arbitrary sizes without worrying about the JVM stack.
- Difficulty presets. Beginner / intermediate / expert grids and mine densities, picked from a start menu.
Repo
Source on GitHub.
