Browser Minesweeper Clone
A couple weeks ago, I started playing minesweeper after downloading a game app on my phone. It got me thinking, had been a while since making the last small browser game, could be fun to try recreating this one, complete with the distinctive styling of the original Windows version.
The game
It’s a minimal implementation, HTML/CSS/build-free Javascript without any external dependencies (code here. Attempted to take the chance to learn a bit about web component by building the game as a simple one.
Click/tap reveals cells, right-click/long tap marks cells with flags.
Styling 3D effect borders
To recreate the retro look, CSS has some interesting possibilities for border-style to give 3D effects:
The outset
border can be used to create the game grid itself:
.grid { border-collapse: separate; border-spacing: 0; } .grid tr td { width: 40px; height: 40px; background: lightgray; border: 8px outset white; box-sizing: border-box; }
First thought was a similar 3D effect for the containing game frame could be achieved by simply collapsing the borders, but it looked rubbish and broke the 3D effect (1). After some experimentation, the trick was to have an outer outset
frame around the whole game, and inset
border on the 3 inner panels to create the 3D effect (2), ensuring border-spacing: 0
(3):
(As fun as using nested tables for layout is, I rewrote using divs
– the same principle works there too, using inner inset
and outer outset
borders in tandem).
Game logic
The game logic is separated from the visualisation. Random mines are placed with field
represents a state of every cell in the game grid (whether it is a mine, a number or empty). Each click reveals more about the world state to the user. revealed
is what is known to the user of the grid.
One interesting logic aspect is when clicking on an empty cell not adjacent to a mine. Then, all adjacent non-mine cells should also be revealed. For example, the state below could have been created by a single click on a currently revealed empty cell:
This is an example of a flood-fill. This was implemented here recursively:
floodFill(x, y) {
let curr = [x, y];
// if this cell is already revealed or out of bounds, do nothing
if (this.revealed[curr] || this.outOfBounds(x, y)) {
return;
}
if (this.field[curr] === undefined) {
// field is empty, need to flood-fill and reveal adjacent empty cells
this.revealed[curr] = MinesweeperGame.FIELD_EMPTY;
for (let [dx, dy] of MinesweeperGame.NEIGHBOUR_OFFSETS)
this.floodFill(x + dx, y + dy)
} else if (typeof this.field[curr] == "number") {
// field is a number cell, should reveal
this.revealed[curr] = this.field[curr];
}
}
There are a few features of the game left unimplemented still, such as chording.
Playing online
Stumbled on minesweeper.online – pretty fully featured site with the game, your statistics, tournaments and other challenges. Didn’t realise people played competitively. Up for a challenge?