Search code examples
javascriptminesweeper

javascript minesweeper issue with revealing tiles surrounding a clicked 0 tile


Clicking on one of the tiles triggers clickerbox().

The issue is that if the user clicks on a tile with b no surrounding mines it's supposed to reveal them, and if any of those also have no mines it should do the same.

It seems to do some of this and then stop before revealing all the tiles it should. I was wondering if anyone knew why or how to fix this?

screenshot of the game board after a zero is clicked on

The first 5 clicks were made by the user then the rest where triggered by the function.

var width = 0;
var height = 0;
var bombs = 0;
var score = 0;
var boxs = 0;
let feild = new Array(2);
userfeild = new Array;

function selectdificulty() {
  feild = new Array(2);
  userfeild = new Array;
  document.getElementById('board').innerHTML = '';
  boxs = 0;
  score = 0;
  if (document.getElementById('dificulty').value == '4') {
    var widthinput = document.createElement('input');
    var heightinput = document.createElement('input');
    var bombinput = document.createElement('input');
    widthinput.placeholder = 'width';
    heightinput.placeholder = 'height';
    bombinput.placeholder = 'mines';
    widthinput.id = 'width';
    heightinput.id = 'height';
    bombinput.id = 'bombs';
    widthinput.setAttribute('type', 'text');
    heightinput.setAttribute('type', 'text');
    bombinput.setAttribute('type', 'text');
    document.getElementById('board').appendChild(widthinput);
    document.getElementById('board').appendChild(heightinput);
    document.getElementById('board').appendChild(bombinput);
    var entercustom = document.createElement('button')
    entercustom.id = 'entercustom';
    entercustom.innerHTML = 'enter custom values'
    document.getElementById('board').appendChild(entercustom);
    document.getElementById('entercustom').addEventListener('click', customsize);
  } else {
    if (document.getElementById('dificulty').value == '1') {
      width = 9;
      height = 9;
      bombs = 10;
    } else if (document.getElementById('dificulty').value == '2') {
      width = 16;
      height = 16;
      bombs = 38;
    } else if (document.getElementById('dificulty').value == '3') {
      width = 32;
      height = 16;
      bombs = 99;
    }
    createuserboard(width, height, bombs);
  }
}

function customsize() {
  var width = document.getElementById('width').value;
  var height = document.getElementById('height').value;
  var bombs = document.getElementById('bombs').value;
  if (!isNaN(width) && !isNaN(height) && !isNaN(bombs)) {
    if (width * height <= 601) {
      createuserboard(width, height, bombs);
    }
  }
}

function createuserboard(width, height, bombs) {
  document.getElementById('board').innerHTML = '';
  for (y = 0; y < height; y++) {
    userfeild[y] = new Array;
    var row = document.createElement('div');
    row.classList = 'row';
    row.id = 'row' + y;
    document.getElementById('board').appendChild(row);
    for (x = 0; x < width; x++) {
      var box = document.createElement('button');
      box.classList = 'box';
      box.id = +y + ',' + x;
      document.getElementById('row' + y).appendChild(box);
      document.getElementById(y + ',' + x).onclick = clickedbox;
      userfeild[y][x] = '/';
    }
  }
}

function clickedbox() {
  var y = this.id.split(',')[0];
  var x = this.id.split(',')[1];
  if (boxs == 0) {
    createmineboard(x, y)
  }
  autoclick(x, y);
}

function autoclick(x, y) {
  userfeild[y][x] = feild[y][x];
  boxs = boxs + 1;
  document.getElementById(y + ',' + x).innerHTML = feild[y][x];
  document.getElementById(y + ',' + x).classList = 'clickedbox';
  console.log(userfeild[y][x] + ' | x:' + x + ' | y:' + y);
  document.getElementById(y + ',' + x).onclick = '';
  if (feild[y][x] == 9) {
    //gameover();
  } else if (feild[y][x] == 0) {
    var check = [
      [-1, 0, 1, -1, 1, -1, 0, 1],
      [-1, -1, -1, 0, 0, 1, 1, 1]
    ];
    for (i = 0; i < 8; i++) {
      var newx = parseInt(x) + parseInt(check[0][i]);
      var newy = parseInt(y) + parseInt(check[1][i]);
      if (newx >= 0 && newx < width && newy >= 0 && newy < height) {
        if (userfeild[newy][newx] == '/') {
          autoclick(newx, newy);
        }
      }
    }
  }
}

function createmineboard(clickedx, clickedy) {
  for (x = 0; x < height; x++) {
    feild[x] = new Array;
    for (y = 0; y < width; y++) {
      feild[x][y] = 0;
    }
  }
  for (bomb = 0; bomb < bombs;) {
    var valid = false;
    let bombx = 0;
    let bomby = 0;
    bombx = Math.floor(Math.random() * width);
    bomby = Math.floor(Math.random() * height);
    if (feild[bomby][bombx] !== 9 && !(bombx == clickedx && bomby == clickedy)) {
      valid = true;
      feild[bomby][bombx] = 9;
      bomb++
    }
  }

  function nearbombs(x, y, w, h, feild) {
    var count = 0;
    if (y !== 0) {
      if (x !== 0) {
        if (feild[y - 1][x - 1] == 9) {
          count = count + 1
        }
      } //top left
      if (feild[y - 1][x] == 9) {
        count = count + 1
      } //top
      if (x !== w - 1) {
        if (feild[y - 1][x + 1] == 9) {
          count = count + 1
        }
      } //top right
    }
    if (x !== 0) {
      if (feild[y][x - 1] == 9) {
        count = count + 1
      }
    } //left
    if (x !== w - 1) {
      if (feild[y][x + 1] == 9) {
        count = count + 1
      }
    } // right

    if (y !== h - 1) {
      if (x !== 0) {
        if (feild[y + 1][x - 1] == 9) {
          count = count + 1
        }
      } //bottom left
      if (feild[y + 1][x] == 9) {
        count = count + 1
      } //bottom
      if (x !== w - 1) {
        if (feild[y + 1][x + 1] == 9) {
          count = count + 1
        }
      } //bottom right
    }
    return count;
  }
  for (y = 0; y < height; y++) {
    for (x = 0; x < width; x++) {
      if (feild[y][x] == 0) {
        feild[y][x] = nearbombs(x, y, width, height, feild);
      }
    }
  }
  console.log(feild);
}
.board {
  display: flex;
  flex-direction: column;
  height: fit-content;
  width: fit-content;
}

.row {
  display: flex;
  flex-direction: row;
  height: fit-content;
  width: fit-content;
  background-color: aquamarine;
}

.box {
  width: 30px;
  height: 30px;
  background-color: #C0C0C0;
  border-radius: 0;
  border: 0 solid;
  box-shadow: inset 2px 2px #FFFFFF, inset -2px -2px #808080, inset 4px 4px #FFFFFF, inset -4px -4px #808080;
}

.clickedbox {
  width: 30px;
  height: 30px;
  background-color: #C0C0C0;
  border-radius: 0;
  border: 0 solid;
  box-shadow: inset 2px 2px #808080;
}
<select name="dificulty" id="dificulty" onchange="selectdificulty()">
  <option value="1">begginer</option>
  <option value="2">intermediate</option>
  <option value="3">expert</option>
  <option value="4">custom</option>
</select>
<script src="windows.js"></script>
<script src="minesweeper.js"></script>
<div class="board" id="board">
</div>


Solution

  • The mistake is hidden in for loop of autoclick function:

    for (i = 0; i < 8; i++) { ... }

    You have to use var keyword to create local iteration variable. Otherwise the global variable is created and reused by recursive calls.

    for (var i = 0; i < 8; i++) { ... }

    My favorite game btw.