MineSweeper.

A JavaFX implementation of the classic Minesweeper — recursive flood-fill reveals, 8-neighbour mine counts, and a hand-rolled scene graph.

2022
MineSweeper — cover

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:

  1. The if (t.isOpen) return guard 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.

  2. 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.

  3. 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.

One click on an empty region triggers the flood fill — every reachable empty tile opens, every numbered tile on the perimeter opens once, the rest stays hidden.

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.