在 for 循环中使用 Math.random 的 JavaScript 函数中不需要的行为



我正在观看YouTube教程,内容是用Vanilla JavaScript,HTML和CSS编写2048游戏。当我在观看教程时,我想我也可以重构讲师给出的代码。在某个点上,她调用两次函数,在网格的随机位置生成两个编号的正方形(不是 0(。我想我可以写一个函数(称之为randomSquaresGenerator(,给定不同位置的所需数量,可以生成各自数量的随机编号的正方形。问题是,经过一些测试(在我的浏览器上刷新(,有时我可以看到的正方形少于所需的方块。我发现这是因为在某些调用中,该函数可能会检查已经编号的正方形并通过。不过,我仍然没有想出如何解决这个问题。有什么想法吗?

这是我的JavaScript代码:

document.addEventListener("DOMContentLoaded", () => {
const gridDisplay = document.querySelector(".grid");
const scoreDisplay = document.querySelector(".score");
const resultDisplay = document.querySelector(".result");
const width = 4;
const squaredWidth = width ** 2;
let squares = [];
function createBoard(width) {
for (let i = 0; i < squaredWidth; i++) {
square = document.createElement("div"); 
square.innerHTML = 0; 
gridDisplay.appendChild(square); 
squares.push(square);
}
}

//The function with the unwanted behavior.
function randomSquaresGenerator(positions) {
for (let i = 0; i < positions; i++) {
let randomSquare = Math.floor(Math.random() * squaredWidth);
if (squares[randomSquare].innerHTML == 0) {
squares[randomSquare].innerHTML = 2;
}
}
}
createBoard();
randomSquaresGenerator(2);
});

还有我的 HTML 代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>2048</title>
<link rel="stylesheet" href="style.css" />
<script src="app.js" charset="utf-8"></script>
</head>
<body>
<div class="score-container">
<div class="score-title">SCORE</div>
<span class="score">1000</span>
</div>
<div class="grid"></div>
<div class="result"></div>
</body>
</html>

我遵循@Andreas建议并使用了while循环。它工作正常。代码如下:

function randomSquareGenerator(positions) {
let generatedSquares = 0;
while (generatedSquares != positions) {
let randomSquare = Math.floor(Math.random() * squaredWidth);
if (squares[randomSquare].innerHTML == 0) {
squares[randomSquare].innerHTML = 2;
generatedSquares += 1;
}
}
}

我认为这里的问题是在

let randomSquare = Math.floor(Math.random() * squaredWidth);

在那里,您有时可能会得到一个已经设置的位置。在这种情况下,也许你应该尝试不同的方法。

function randomSquaresGenerator(positions) {
let arrIndex=[];
for(let i=0;i<squares.length;i++){
arrIndex.push(i);
}
for (let i = 0; i < positions; i++) {
let randomIndex = Math.floor(Math.random() * arrIndex.length);
let randomSquare = arrIndex[randomIndex];
arrIndex= [].concat(arrIndex.slice(0,randomIndex),arrIndex.slice(randomIndex+1,arrIndex.length));

squares[randomSquare].innerHTML = 2;

}

在那里,我定义了一个带有主数组索引的数组,因此,您只需从那里选择一个随机数,它就会将您映射到具有 0 的数组位置。 然后,您从数组中删除该元素并执行相同的操作,因为您知道您将始终获得可用位置。 您可能需要添加一个 if 语句来检查仓位是否大于数组的大小,以防万一。

希望你喜欢。

最新更新