I made a minesweeper game in javascript, which was finally running pretty smoothly, until i added the "expand()" function (see below). I have 3 issues:
The relevant code and a link is below these 2 images
var flippedCount = 0;
var alreadySetAsZero = [];
var columnAmount = 10;
function processClick(clicked) { //i use a "(this)" to pass as "(clicked)"
nextToBombCheck( parseInt(clicked.id) );
checkWin();
}
nextToBombCheck( boxNum ) {
flippedCount++;
document.getElementById("flipped").innerHTML = flippedCount;
//long function setting "bombCount" to # bombs around clicked square goes here
if ( bombCount !== 0 ) {
//blah blah blah
} else {
alreadySetAsZero[ boxNum ] = "yes";
expand(boxNum);
}
}
function expand( emptyBoxId ) {
checkRightOfEmpty( emptyBoxId + 1 );
checkLeftOfEmpty( emptyBoxId - 1 );
checkAboveEmpty( emptyBoxId - columnAmount );
checkBelowEmpty( emptyBoxId + columnAmount );
}
function checkRightOfEmpty( boxToTheRightId ) {
//check if already marked as zero
if ( alreadySetAsZero[ boxToTheRightId ] === "yes" )
return;
//if box is at the edge
if ( boxToTheRightId % columnAmount === ( 0 ) ) {
//do nothing
} else {
nextToBombCheck( boxToTheRightId );
}
}
//and the rest are 3 similar functions
I was not able to find a pattern with the lack of expansion or numbers added to flipped count.
link here
p.s. sorry about the title i dont know what else to call it
You are getting an incorrect count because your algorithm doesn't take into account squares that have already been flipped - resulting is squares getting counted twice.
The simplest way to keep an accurate count of the is to make use of that fact that 'getElementsByClassName' returns a live node list.
Note: getElementsByClassName has pretty good browser support, but if your browser requirements are different, you will need to adjust this a bit.
On entry, initialize the list (variable name just to differentiate from previous name):
var newFlippedCount = document.getElementsByClassName('flipped');
Each time you update a square with a bomb count class use this instead (adds the flipped class as well):
document.getElementById(boxNum).className = classList[bombCount] + ' flipped';
When you update the UI with the new flipped count use:
document.getElementById("flipped").innerHTML = newFlippedCount.length;
Your count is now magically correct :)
Note: you could also solve this by checking to see if the box has already been flipped before incrementing flippedCount
.
You were also periodically getting an error in the console:
Uncaught TypeError: Cannot set property 'className' of null
at this line (around line: 298):
document.getElementById(boxNum).className = classList[bombCount];
You should protect that either by checking the bounds or just by checking the return value before using it:
var ele = document.getElementById(boxNum);
if(!ele) return;
ele.className = classList[bombCount] + ' flipped';
Demo
Edit: If you are interested, here is a high level overview of the Minesweeper Cascade Algorithm
Update - cascade bug found
One of the reasons the cascade wasn't working correctly on successive replays is that the variable used to track cells that had already been set to zero wasn't getting reset in a new game. For a fix:
function start() {
…
// Reset to empty array
alreadySetAsZero = [];
...
}
Updated fiddle with additional debug statements to help find the problem:
Demo
Although you use "alreadySetAsZero" to stop squares being counted multiple times, this doesn't take into account squares with a bomb count. These will be counted multiple times in your expand method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With