My rewrite of the original Minesweeper, for the web

To-do list, tic-tac-toe, snake – all great baby’s first program choices for sure. I, however, was sort of frustrated with the selection of Mine­sweeper re­implementations online, so here we are.

Check it out at the memorable vanity domain https://minesweepe.rs. You will be served a static site with no ads, no tracking, and no writing your record times into your local­Storage without explicit permission. The code is AGPLv3 and available here – all in Scala!

What did I add to the status quo? Well:

By status quo I am referring to the big two of https://minesweeper.online and https://minesweeperonline.com. The more niche sites are not usually that great, although there are exceptions, with one major one being https://llamasweeper.com/, which is arguably the best one of them all. Llama­sweeper provides some of the features I listed above as well as plenty of other great and unique ones, so definitely also check it out!

But let us now go into a little bit of detail on what I have done, as of September 2025.

Responsive design

I was not able to find a single online minesweeper which automatically grows to or dynamically grows with the viewport size. With my version, whether you are on desktop or mobile, you are greeted with the screen full to the brim of that which you came for!

On a large desktop monitor this is of course not ideal behaviour, so there is a zoom slider in the settings. And for a tad more extra space or con­centration, there is also the option of going full screen. Unfortunately, if you use Safari – the Internet Explorer of the 2020s – going full screen on anything but video elements is sacrilegious and thus disallowed. To hide the browser UI elements on Apple, you need to install the site as a Progressive Web App (PWA).

Proper touch support

I want to see the little smiley react with concern as I lay my finger on the screen. I want to be able to slide around and see the animation move along without the viewport scrolling anywhere. I want to add a second or, dear me, even a third finger and have them all tracked independently. Et voilà:

All animations follow touch and each finger.

The downside? You cannot pan or zoom anymore, which means you are not going to be able to play very large levels on tiny screens. Thus, in its current iteration, the game is perhaps the most at its element on a tablet.

In fact, here is the developer of the aforementioned Llamasweeper demonstrating the potential of multiple inputs at once on a large screen:

Llama’s sorcery on display, with the confetti and zoom-in edited in by me.

They had an uplifting comment to add: “This is niche, but the touch performance is SO GOOD on mobile. I got a 10s game on int just now (will send screenshot later). I’m one of a few people that can play using both hands at once, so the multitouch feature is excellent for that, and makes it better even than lots of native apps.” Very kind!

As a final note on this part, I should mention that I have some ideas on how to implement zoom by altering the portions of the CSS grid. Someday, maybe.

Offline & multiplatform

Once the code is loaded, you can cut your connection and things will keep working. Even better, the PWA truly works offline, meaning once you do the installation, you will never need a connection. Fundamentally, Mine­sweeper is a solo game, so there should not be a need for the internet.

Where the option to install will usually appear.

I do understand why sites such as minesweeper.online require a connection, as they have global leaderboards, which requires some anti-cheating measures. People enjoy having a fair, social and competitive aspect to their games, but my version is there for the more casual playing sessions.

As for working on multiple platforms, I tried to make sure to support all mainstream operating systems and browsers. The web shines as a target for universal development! I do dream of one day making a native application with something like Qt, Flutter, or, most likely, Kotlin Multiplatform, but that would be a lot of effort for a game with a small player base, each member of which already having their own good favourite on their preferred platform.

Graphics

The original Minesweeper is a game with sharp retro graphics, so I do not want to see any curved lines or fuzziness. My version copies the original graphics quite faithfully using crisp and optimised svgs.

A tiny thing I adjusted was the crossed-out mine graphic. Originally, the red cross is not centered to the mine, so I went and “fixed” that. I do not know what their idea was behind doing it the way they did, but I found it distracting.

Original on the left, mine on the right.

Another insignificant detail is that the mine counter and the timer can grow dynamically just a bit if necessary. The maximum sizes could just be calculated at the start as done by https://minesweeper.us, but this works and does not seem to be a thing anywhere else:

If you ever want to flag every single tile…

As an aside, many newer implementation do not allow flagging before a cell has been opened! I do not know the reason for that. You can go for the cheeky 0 second attempts all you want with mine.

One last small graphical flair comes by the way of the menus, which mimick Windows 3.11, which is where the original Minesweeper was first introduced. This does not affect gameplay in any way and is not even that accurate, but it is something.

Windows used to look good.

Algorithms

I needed to pay attention to the algorithms I used in order to keep the game performant, but I will not bore you with any code. Quickly:

MH.ZiNi

This algorithm gets its own chapter, since it is possibly a semi-novelty. There is this thing called ZiNi, which aims to calculate the lowest number of clicks required for a board to be solved. Its variant, Human ZiNi (HZiNi), is claimed to be more humanlike and comparable to an actual solve.

However, every ZiNi method starts with an advantage over any fleshly being, that being Unfair Prior Knowledge (UPK), which means they see the full board from the start. In the case of HZiNi, the algorithm starts by opening every single zero area, which is basically impossible for a human to achieve outside of the beginner level.

It wants to be human © Hand-Drawn Goods.

Enter what I am dubbing More Human ZiNi (MH.ZiNi). It still has UPK, but the main difference is that it starts from where the player themself started and then goes on from there in a similar manner to HZiNi:

  1. Calculate the premium for each open cell
    • premium = [adjacent 3bv] - [adjacent unflagged mines] - 1_[if cell is closed] - 1
  2. Find the one with the highest premium
    • Chord if premium ≥ 0
    • Else open a zero if any is touching the opened area
    • Else open a possible safe cell touching our opened area
    • Else open a random zero anywhere if available (heavy use of UPK here)
    • Else open the first closed cell going from top-left to bottom-right
  3. Go back to 1 if closed cells remain

I am still contemplating whether I should add a step there – after the first “else” – to instead do the more human thing of chording a cell if the number of opened cells does not cost any clicks. That sometimes even leads to more optimal solves, as the current way can be shortsighted (on purpose).

MH.ZiNi adds a more realistic efficiency goal for the player without me having to implement a proper solver. It can be beaten and it can even lose against 3BV (at least on beginner level).

What is missing

Far from a perfect creation, here are some missing features (this post is quickly devolving into a bunch of bullet points):

I should mention that “alternative” browsers – even some based on Chrome/Blink – may cause issues. As an example, DuckDuckGo seems to ignore many of the ways I use to make touch work well. It is what it is.

The end

Final random fact: the custom level supports a height of 1, which is sort of funny. Go try it out: https://minesweepe.rs.

Thanks for reading. Click here to go to back to main page, which may or may not have anything on it.