确保我的for循环生成恰好8个唯一的数字对

时间:2015-07-14 09:13:17

标签: javascript

这是一场扫雷游戏。这里的目标是生成确切的地雷数量。在这种情况下,我有一个8x8网格的盒子,里面有10个地雷(见下图)。因此,嵌套for循环生成64个具有xy坐标的对象(以便稍后绘制网格)和state属性以指示该字段是否已被挖掘。然后,在generateBombs中,我使用随机state:minedx y生成10个对象,以随机覆盖box数组中的64个对象中的8个,从而种植地雷。我的方法存在的问题是,有可能会生成2对非唯一的xy对象,这样我最终会得到比原来少的对象地雷数量,因为同一个对象将被覆盖两次。这里有什么好方法?

另外,我的要求之一是让生成器为地雷使用辅助函数,但它们采用相同的参数,可能会失败。

var minesweeper = {
  boxes: [],
  //rows
  boxesNum: 0,
  bombsNum: 0,

  //creates a 8x8 grid 
  generateMap: function (width, height, bombsNum) {
    for (i = 1; i < height; i++) {
        this.boxes.push({
            x: i,
            y: 1,
            state: "safe"
        });
        for (j = 1; j < width; j++) {
            this.boxes.push({
                x: 1,
                y: j,
                state: "safe"
            });
        }
    }
    this.generateBombs(width, height, bombsNum)
  },
  //mines random fields from the grid
  generateBombs: function (width, height, bombsNum) {
      for (k = 0; k < bombsNum; k++) {
          this.boxes.push({
             x: Math.floor(Math.random() * width + 1),
             y: Math.floor(Math.random() * height + 1),
             state: "mined"
          });
      }
   }
}

minesweeper.generateMap(8, 8, 10);

1 个答案:

答案 0 :(得分:1)

你最好不要在盒子阵列上工作,而不是先生成炸弹。

generateBombs: function (width, height, bombsNum) {
    var bombCount = 0;                          // Count how many bombs we planted,
    while(bombCount < 10){                      // Loop until we have 10 bombs,
        var index = parseInt(Math.random() * this.boxes.length + 1); // Get a random box id,
        if(this.boxes[index].state === "safe"){ // If the box is safe, plant a bomb.
            this.boxes[index].state = "mined";
            bombCount++;                        // Increase bomb count with 1.
        }
    }
}

这种方法可以保证在10个不同地点种植10枚炸弹。 可以两次选择同一个框,但如果它这样做,它只会再次尝试。

在最好的情况下,与其他需要检查每个要生成的炸弹的坐标数组的方法相比,你有10次循环迭代。

然而,这种随机挑选炸弹位置的方法存在一个问题:
如果你增加炸弹数量,该方法将会击中越来越多已经种植炸弹的盒子,导致生成任意数量的炸弹所需的迭代指数增加。基本上,该领域越密集,该函数越有可能随机选择已经有炸弹的单元格,因此它必须再试一次。

但是,我不希望这种情况在炸弹数量上显着,比如50%或更低。

您的generateMap功能也被破坏了。试试这个:

generateMap: function (width, height, bombsNum) {
    for (var i = 0; i < width; i++) {
        for (var j = 0; j < height; j++) {
            this.boxes.push({
                x: (i + 1),
                y: (j + 1),
                state: "safe"
            });
        }
    }
    this.generateBombs(width, height, bombsNum)
},