【问题标题】:Unwanted behavior in a JavaScript function that uses Math.random in a for loop在 for 循环中使用 Math.random 的 JavaScript 函数中的不良行为
【发布时间】:2020-06-20 17:24:25
【问题描述】:

我正在观看有关使用 Vanilla JavaScript、HTML 和 CSS 编写 2048 游戏的 YouTube 教程。在看教程的时候,我想我也可以重构讲师给出的代码。在某一时刻,她调用了两次函数以在网格的随机位置生成两个编号的正方形(不是 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>

【问题讨论】:

  • 不要使用固定轮数的for(...)。使用while 并计算“生成”了多少个正方形。如果数字等于positions,则退出循环。
  • 非常感谢!这确实有效,现在适用于任何给定的 positions 值。
  • 将您的解决方案添加为答案并接受它(或删除问题),以便将其标记为“问题已解决”

标签: javascript function loops frontend


【解决方案1】:

我听从了@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;
      }
    }
  }

【讨论】:

    【解决方案2】:

    我认为这里的问题在于

    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 语句来检查位置是否大于数组的大小,以防万一。

    希望你喜欢。

    【讨论】:

    • 感谢您的建议,尽管我使用了上面的解决方案。它更简单,而且效果很好。
    猜你喜欢
    • 2017-05-03
    • 1970-01-01
    • 2021-03-15
    • 2016-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-08
    • 2021-09-20
    相关资源
    最近更新 更多