随机数生成器不生成相同的数字

Random number generator to not generate same number

我在 javascript 中创建了一个地雷游戏,其中我生成了一个分配给 div 的随机数,这个 div 将是一个地雷,但问题是例如(我将地雷的数量设置为 8,而不是得到 8 个不同的地雷,我得到 8 个地雷,但其中 2 个在同一个地方所以它算作我有 6 个地雷,我该如何修复它?这里是codem 的重要部分,还有关于如何改进我的代码的任何提示,我将不胜感激,因为我对编程很陌生)

let tiles = document.getElementsByClassName('tile');
let numMines = 6

for (i = 0; i < 1; i++) {
    bomb = [tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))],
    tiles[(Math.floor(Math.random ()* tiles.length))]]
    bomb.splice(numMines) 


    bomb[0].style.backgroundColor = "red"; 
    bomb[1].style.backgroundColor = "red";  
    bomb[2].style.backgroundColor = "red";
    bomb[3].style.backgroundColor = "red"; 
    bomb[4].style.backgroundColor = "red";  
    bomb[5].style.backgroundColor = "red";
    bomb[6].style.backgroundColor = "red"; 
    bomb[7].style.backgroundColor = "red";  
    bomb[8].style.backgroundColor = "red";
    bomb[9].style.backgroundColor = "red"; 
    bomb[10].style.backgroundColor = "red";  
    bomb[11].style.backgroundColor = "red";
    bomb[12].style.backgroundColor = "red";
    bomb[13].style.backgroundColor = "red"; 
    bomb[14].style.backgroundColor = "red";  
    bomb[15].style.backgroundColor = "red";
    bomb[16].style.backgroundColor = "red"; 
    bomb[17].style.backgroundColor = "red";  
    bomb[18].style.backgroundColor = "red";
    bomb[19].style.backgroundColor = "red";  
    bomb[20].style.backgroundColor = "red";
    bomb[21].style.backgroundColor = "red"; 
    bomb[22].style.backgroundColor = "red";  
    bomb[23].style.backgroundColor = "red";
    bomb[24].style.backgroundColor = "red"; 
    bomb[24].style.backgroundColor = "red";   
} ```

简要说明:

这里有一些逻辑可以解决您面临的问题,它与@Hackytech 所说的类似,但我选择跟踪 tile indecies。您基本上可以创建 n 个炸弹,并且 select 每个炸弹都有一个独特的图块。 select 独特图块的方式是在 getTileIndex 函数中,该函数本质上不断调用自身,直到找到尚未使用的索引并且 return 是该索引。下面是一个不涉及 DOM.

的示例

对你来说 tiles 最终会是 document.getElementsByClassName("tile"),我把它做成一个随机数数组只是为了提供一些占位符信息。

您提到您是编程新手,所以这里逐行更详细地解释了发生了什么。第一行,我创建了一个大小为 100 的空数组并用空值填充它,所以它最终是 [null, null, null ... 100 times]。然后我调用 .map,这就像一个创建新数组的 for 循环,其中数组中的每个项目都取决于从回调中编辑的内容 return。由于回调是 item => Math.random(),我正在 return 为数组中的每个项目设置一个随机数。然后我创建一个名为 tileIndex 的新数组,我在其中跟踪已经使用了哪些图块索引,这样我们就不会重叠图块。 getTileIndex 函数确实可以解决您的问题。它是一个 recursive function,它只是不断调用自己,直到它找到一个尚未添加到炸弹数组的索引。然后 return 就是那个索引。最后一行代码创建一个大小为 27 的空数组,并用 null 填充它。与之前类似,这个数组随后被映射,但是我们 return 不是 return 一个随机数,而是通过调用我们的 getTileIndex 函数 return 一个唯一索引的瓦片 return唯一图块索引。

如果您不明白这里的内容,请随时在评论中提问!

const tiles = new Array(100).fill(null).map(item => Math.random());
const tileIndex = [];

function getTileIndex() {
  const i = Math.floor(Math.random() * tiles.length);
  if(tileIndex.findIndex(item => i == item) < 0) {
    tileIndex.push(i);
    return i;
  }
  
  return getTileIndex();
}

let bombs = new Array(27).fill(null).map(bomb => tiles[getTileIndex()]);

console.log(tiles)

确保获得正确数量且没有重复的随机地雷的一种方法是创建一个包含所有图块的临时数组,然后移除随机选择的每个图块。第一次选择 24、23、22 等等

下面是一些示例代码:

const { floor, random } = Math;
const tiles = document.getElementsByClassName('tile');
const numMines = 6;
const t2 = [...tiles]; // clone of tiles, since we're going to mutate it
const b = [];
for (let i = 0; i < numMines; i++) {
  const j = floor(random() * t2.length);
  b.push(t2[j]); // add bomb tile to b array
  t2.splice(j, 1); // remove tile from t2
}

// loop through all tiles, make tile red if it's a bomb, black if not
for (const tile of tiles) {
  const isMine = b.indexOf(tile) >= 0;
  tile.style.backgroundColor = isMine ? 'red' : 'black';
}

还有一个工作示例:

const { floor, random } = Math;
const tiles = document.getElementsByClassName('tile');
const numMines = 6;
const t2 = [...tiles];
const b = [];
for (let i = 0; i < numMines; i++) {
  const j = floor(random() * t2.length);
  b.push(t2[j]);
  t2.splice(j, 1);
}
const bomb = [];

for (const tile of tiles) {
  const isMine = b.indexOf(tile) >= 0;
  bomb.push(isMine);
  tile.style.backgroundColor = isMine ? 'red' : 'black';
}
.tile {
  display: inline-block;
  width: 1em;
  height: 1em;
}
<div class='row'>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
</div>
<div class='row'>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
</div>
<div class='row'>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
</div>
<div class='row'>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
</div>
<div class='row'>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
</div>
<div class='row'>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
  <span class='tile'></span>
</div>

另一种方法是将相关的ID存储在一个数组中,这样很容易找到:

let tiles = document.getElementsByClassName('tile');
let numMines = 6;
let tileIndexes = Array();
let i = 0;

while (i < 6) {
  const rand = Math.floor(Math.random() * tiles.length);
           
  if (!tileIndexes.includes(rand)) {
    tileIndexes.push(rand);
    i++;
  }
}

tileIndexes.forEach(e => {
  tiles[e].style.backgroundColor = "red";
});

为确保您获得一组独一无二的 ID,请将这些数字添加到一个数组中,并将所有新随机生成的数字与数组中的数字进行比较。 while 循环将迭代,直到数组中有 numMines 个元素。