Search code examples
javascriptwhile-loopfreeze

Why does this javascript while loop hang?


I was trying a very simple thing with javascript, to create a minesweeper grid.

gridsize=9;

//grid initialisation 
var grid=Array(gridsize).fill(Array(gridsize).fill(null));

// this comes from  <https://stackoverflow.com/questions/1527803/generating-random-whole-numbers-in-javascript-in-a-specific-range>
function randint(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

nbombs=20;
insertedbombs=0;

while (insertedbombs<nbombs){
    rx=randint(0,gridsize-1);
    ry=randint(0,gridsize-1);
    if (grid[rx][ry] == null){
        insertedbombs++;
        grid[rx][ry]='b';
    }
}

The while loop hangs, both in Chrome and Firefox consoles, all the values of the grid are filled, not just 20, i've no idea why, i guess i have some wrong understanding of javascript language, because the same code in python works.

Working python code:

grid= [[None for i in range(9)]for i in range(9)]

nbombs=20;
insertedbombs=0;
while (insertedbombs< nbombs):
    rx=random.randint(0,8)
    ry=random.randint(0,8)
    if (grid[rx][ry]== None):
            grid[rx][ry]='b'
            insertedbombs+=1

Solution

  • The issues is that Array#fill doesn't do what you think it does.

    In your example you create a SINGLE array Array(gridsize).fill(null) and then you put that array at each index of the outer array. Meaning that your grid actually contains the same array, 9 times over. So when you assign grid[0][0] you actually assign grid[0][0], grid[1][0], grid[2][0], grid[3][0], etc... all at once (ish).

    const gridSize = 9;
    
    //grid initialisation 
    const grid = Array(gridSize).fill(Array(gridSize).fill(null));
    
    console.log(grid[0] === grid[1]);
    
    grid[0][0] = 10;
    
    console.log(grid[0][0], grid[0][0] === grid[1][0]);

    What you want to do, is first fill the array with some dummy value, like null. Then map over the array and replace each entry with its own copy of Array(gridsize).fill(null).

    const gridSize = 9;
    
    //grid initialisation 
    const grid = Array(gridSize)
      .fill(null)
      .map(() => Array(gridSize)
        .fill(null)
      );
    
    const randInt = (min, max) =>
      Math.floor(Math.random() * (max - min + 1)) + min;
    
    const nbombs = 20;
    let insertedbombs = 0;
    
    while (insertedbombs < nbombs){
        const rx = randInt(0, gridSize - 1);
        const ry = randInt(0, gridSize - 1);
        if (grid[rx][ry] === null){
            insertedbombs += 1;
            grid[rx][ry] = 'b';
        }
    }
    
    console.log(grid);