
How to Build Minesweeper with JavaScript - maynman
https://mitchum.blog/how-to-build-minesweeper-with-javascript/
======
duiker101
That first image really needs to be the game itself. I had such an instinct to
click it as soon as I saw it and was sad when I noticed it was just an image.
Overall the article is nice, if a bit dated, but at least it's a change from a
new reactive library.

~~~
dylan604
It looks like they may have taken your advice. I came across this thread 9
hours after you, and the image was of a game in progress

~~~
duiker101
Yeah it was like that even before! I want to actually play the game! Not just
see an image :)

~~~
maynman
Good call! I agree, I think that would be better. Unfortunately the WordPress
theme I'm using wouldn't let me do that by default. I'll have to do some
research to see if there is a good plugin for that :)

~~~
duiker101
Thanks for considering it already! I don't really have any WP knowledge but
maybe you could just slap it in an iframe?

------
dilatedmind
I was working on a multiplayer minesweeper game in elixir and react a couple
years back to try and get a better understanding of otp.

[https://mines.gdf3.com](https://mines.gdf3.com)
[https://github.com/slofurno/minesweepers-
ex](https://github.com/slofurno/minesweepers-ex)
[https://github.com/slofurno/minesweepers-
front](https://github.com/slofurno/minesweepers-front)

Wound up spending most of my time focusing on performance. Large boards (say
4000x4000) naively represented by a map in elixir consumed too much memory and
trying to render 16 million dom elements in react didn't fly.

Never got around to basic ui stuff like setting player name and color, but I
thought the bots were pretty cool.

~~~
goddtriffin
An MMO Minesweeper Royale.... Not a bad idea actually! This definitely
inspires me to make my own!

------
mikehodgson
I'm sure there's only a few ways to do it, but this code is really similar to
the one I wrote back in December:
[https://github.com/mikehodgson/minesweeper](https://github.com/mikehodgson/minesweeper)

It is playable here: [https://sweeper.games](https://sweeper.games)

No jQuery, just straight CSS/HTML/ES6

~~~
dylan604
This playable version seems to be missing the feature of auto-revealing the
squares, usually a ctrl-click on a square to compare against placed flags.
It's actually rule 5 from the linked page

~~~
mikehodgson
That feature is implementation specific, not a rule of the game. I've never
used it, so I didn't bother implementing it.

------
lowdose
Google Chrome Labs released a very shiny typescript minesweeper on
[https://proxx.app](https://proxx.app) The source code is on Github
[https://github.com/GoogleChromeLabs/proxx](https://github.com/GoogleChromeLabs/proxx)

~~~
kaycebasques
Here’s a technical overview on it. Most interesting thing for me was how they
made it accessible and feature phone support.

[https://web.dev/proxx-announce](https://web.dev/proxx-announce)

Disclosure: Work on same team as the PROXX people

~~~
lowdose
Thank you for open sourcing this. Across Googles github accounts there are
some amazing showcases that offer an invaluable source of inspiration. The
web.dev site is awesome! I actually came across proxx after I forked the
website. Eleventy seems to be a robust static site framework with nifty
template options.

I was a bit disappointed the actual dynamic part of the website was removed a
couple of months ago during migration to eleventy. The express server, url
fetching of lighthouse results & the option to save this in Firebase. For me
this is the most interesting part of the website. How to setup a fetching api
& Cloud Firestore with identity features. It would be awesome if devsite.js
would be included for the people that want to take a peak under the hood.

------
tomjohnson3
excellent post.

can i make a (hopefully useful) comment about programming style - something
that someone shared with me a long time ago when reading my code that i have
found to be very valuable over the years?

it can be incredibly beneficial (for readability, catching logic errors, etc.)
to "exit early" from "if" statements. meaning, if you find that you're nesting
"ifs" more than a couple of levels deep, the code _may_ be a candidate for
flattening.

so - your handleClick function could be rewritten (with stuff removed) as:

    
    
        var handleClick = function( id )
        {
            if ( gameOver ) return;
            if ( ctrlIsPressed )
            {
                // do stuff...
                return;
            }
            if ( cell.opened || cell.flagged ) return;
            if ( cell.mined )
            {
                // do stuff...
                return;
            }
            // else do stuff...
            if ( cell.neighborMineCount > 0 )
            {
                // ...
                return;
            }
    
            // else do final stuff...
        }
    

i may have missed something, but hopefully you get the point. this simple
refactoring reduced the depth of the if statements from ~5 to 1. ...many of
the other functions could be flattened just like this.

...and how do you know when something can be flattened?

if there is no code after the if statement and the end of the function - just
swap the logic and return early.

e.g., this:

    
    
        var handleClick = function( id )
        {
            if ( !gameOver )
            {
                // ...lots of code and if statements...
            }
            // ...but no code after the block before returning from the function...
        }
    

...turns into this:

    
    
        var handleClick = function( id )
        {
            if ( gameOver ) return; // NOTE: logic check change...
            // ...do the stuff in the block here...
        }
    

...and this is also a great pattern for checking input variables (and
returning or throwing an exception) at the top of the function, ensuring that
the code following it has valid input parameters.

since you're sharing your coding projects on your blog (which are excellent) -
hopefully you can share this tidbit about coding style with your readers and
they'd find it as useful as i have.

~~~
maynman
Thanks for the kind words, and thanks for sharing! That is a cool pattern. I
definitely have a little too much nesting going on in that function, and it
could use some refactoring.

I've always felt funny about multiple return statements though, which is
probably one reason why a pattern like this doesn't usually come to my mind
when considering how to refactor code. I've always liked having one exit point
at the end of functions because programmers naturally expect a function to
return at the very end. I think minimizing the number of return statements is
generally a good thing, but perhaps I have been too strict about applying that
rule.

~~~
shhsshs
"programmers naturally expect a function to return at the very end"

I disagree. I expect a function to return at the moment the final result is
known. The decisions and logic are over. I shouldn't have to glaze over even a
single extra line of code, because the work has already been done.

~~~
maynman
That's a fair point. I guess the main argument in favor of single return
statements in modern programming languages is ease of debugging and logging.
Like most things in programming, you have to consider the trade-offs. A few
return statements isn't the end of the world, but after too many you might
just want to make some more functions.

------
ronilan
Here is my implementation from 2014 (with jquery...). Watch out. It has lots
of bugs!

[http://www.ronilan.com/bugsweeper/](http://www.ronilan.com/bugsweeper/)

~~~
AlanSE
Awesome job implementing a single-click clearing when clicking on, say, a 2
with 2 marked mines next to it. The original Windows version where you had to
double click was too cumbersome.

[https://github.com/AlanCoding/AlanCoding.github.io/blob/mast...](https://github.com/AlanCoding/AlanCoding.github.io/blob/master/old/mine.html)

This was my version. I need to go re-host it somewhere, but you would not be
much surprised by its functionality. My only unique feature was a wider
variety of expressions of the smiley face button.

------
NohatCoder
The game board is a well ordered grid, I can't fathom why you'd not organise
it into an array. The cell object has 3 completely redundant fields. Most of
the code just checks the mined parameter of cell objects, but for some reason
there is also an isMined function. The code placing mines uses its own data
structure to keep track of where mines have been placed, rather than the board
data, and manages to be O(n^2) instead of O(n) because of that choice.

Overall it is code that takes a lot of unnecessary detours.

------
d--b
In a notebook:

[https://observablehq.com/@benjaminadk/minesweeper](https://observablehq.com/@benjaminadk/minesweeper)

------
aykutcan
Well. it is good tutorial but there is a little problem.

In minesweeper mines should be generated after first open. You can't hit mine
at first click it must empty or number.

~~~
dylan604
Is this true? I remember plenty of times unsuccessfully guessing the first
block to be a mine. Maybe I'm remembering incorrectly?

~~~
WorldMaker
The version bundled with Windows has always had a first click check to avoid
mines, but a lot of clones don't. I remember back in my AOL days in the 1990s
it was very much a sign of a bad clone and an immediate uninstall, though I
don't recall why I went through so many clones at the time. (I think I was
looking for more challenge having got tired of even "Expert Mode"? I was a
strange kid.) (The best clones not only did a first click was safe build out,
but also a solvability check that the first click opened enough hints that
every puzzle was theoretically solvable on given hints alone.)

The version included in Microsoft Entertainment Pack 1 prior to Minesweeper
being bundled with Windows might not have had that check, my memory is fuzzy
on that. I'd be surprised how many people remember it from the Entertainment
packs before Windows 3.1.

The clone that I recall most Mac users had in 90s, such as was on school
computers at the time, definitely did not have a first click fix up.

------
schwartzworld
This was a lot of work and you should be really proud.

One suggestion which could simplify things. I noticed this bit of code:

    
    
      var getNumberColor = function( number )
      {
          var color = 'black';
          if (number === 1)
          {
              color = 'blue';
          }
          if (number === 2)
          {
              color = 'green';
          }
          // etc        
      }
    

You mention using a switch statement, but why not just use an array and look
it up by the index?

~~~
rezistik
And why not just return the result instead of assigning it to something you
eventually return?

~~~
winrid
The argument against this is usually one return statement is preferred.

~~~
maynman
Yep, that's why I chose to implement it that way. I generally prefer single
return statements. Plus my day job enforces it as part of the coding
convention, so force of habit too haha.

------
marshmellman
Uh oh. Since folks are posting their own implementations, here’s mine, written
as an exploratory exercise for Angular2:

[https://github.com/jonmellman/angular2-minesweeper](https://github.com/jonmellman/angular2-minesweeper)

[https://jonmellman.com/minesweeper/](https://jonmellman.com/minesweeper/)

 _Grimace_

------
tazard
I guess this is a good time to share my implementation too. Unfortunately it's
pretty much desktop only, but includes a high scores board!

[https://github.com/reed-jones/minesweeper_js](https://github.com/reed-
jones/minesweeper_js)

And to play it:

[https://minesweeper.zone/](https://minesweeper.zone/)

------
cbau
I built a copy of Minesweeper using AngularJS for fun that may be instructive.

Demo:
[http://ceasarbautista.com/minesweeper/](http://ceasarbautista.com/minesweeper/)

Source:
[https://github.com/Ceasar/minesweeper](https://github.com/Ceasar/minesweeper)

------
nojvek
One weekend I was bored and made a React version of minesweeper. Needless to
say I had a lot of fun.

Emoji minesweeper:
[https://codepen.io/nojvek/full/KjLxdx](https://codepen.io/nojvek/full/KjLxdx)

------
BZH314
MSFT, our multiplayer Twitch Plays implementation of minesweeper, playable
directly with your mouse (left click to dig, middle click to flag):

MineSweeper For Twitch (MSFT) [1]

\----

[1] [https://www.twitch.tv/bzh314](https://www.twitch.tv/bzh314)

------
cumwolf
cool tutorial, love all of the code examples. Some of that code is brutally
unreadable with all of the nested statements and loops. I guess it works for
the tutorial but ooof!

------
IvanK_net
My friend (Math genius) made a video tutorial about writing Minesweeper in JS
in a Notepad
[https://www.youtube.com/watch?v=OuahlosQ1m0](https://www.youtube.com/watch?v=OuahlosQ1m0)

 __* It is in Czech :(

------
kraucrow
Aren't people afraid of being kicked and beaten with sticks in 2019 if they
build things with jQuery.

~~~
have_faith
It's a shame jQuery gets demonised so much, it's still a great tool to use
even in 2019. Don't use it for the wrong job (web apps) and there's nothing
wrong with it. It's actually strange you can meet people who learned something
like React/Angular as an intro JavaScript and don't know how to do simple
things outside of a framework without a tutorial.

~~~
FreeFull
Modern Javascript standards have incorporated a lot of things that have
started their life in jQuery. What advantages does jQuery still have?

~~~
rofo1
Sure, when you need to update 1 single thing once, you can use vanilla js.

But when you need to do more than that, you'll realize jQuery is still useful
(assuming you don't use a framework or whatever). Either you will use
something like jQuery or you'll reinvent by writing the methods yourself.

IMO it's still relevant, despite the hype of other frameworks.

~~~
onion2k
There's really nothing you need jQuery for any more except supporting old
jQuery components. You can do things like
Array.from(document.querySelectorAll('.foo')).map((fooEl)=>{
fooEl.classList.toggle('bar'); }) in a browser (with no Babel-style transpile
step) these days.

In case you want to play with that -
[https://codepen.io/onion2k/pen/NQrEKq](https://codepen.io/onion2k/pen/NQrEKq)

~~~
yrwwywtywsrty
Although I usually agree with the 'jQuery is overused' side of the crowd, I
think your example is one of the times when I see that jQuery wins in ease and
readability.

The jQuery equivalent for this is $('.foo').addClass('bar');

~~~
chrismorgan
I really dislike the way jQuery makes no distinction between mutations on
_one_ or _many_ elements. I view the native APIs’ differentiation of the two,
requring you to be explicit
(`document.querySelector('.foo').classList.add('bar')` versus
`document.querySelectorAll('.foo').forEach(foo => foo.classList.add('bar'))`)
to be a feature.

