为什么我的页面会陷入死循环?

Why does my page fall into the infinite loop?

function randomNumber(){
    var value;
    var flag = false;
    var tds = document.querySelectorAll('td');
    do{
        value = Math.round(Math.random() * (26 - 1) + 1);
        for(var t = 0; t < tds.length; t++){
            if(tds[t].innerHTML == value)
                flag = true;
        }
        if(!flag){
            return value;
        }
    }while(flag == true)
}

这个函数returns一个新td的innerHTML的随机数。如果有其他 tds 与此代码生成的编号相同,则循环再次开始。如果生成的数字是唯一的,我将其添加到新 td 的 innerHTML 中。但是我什至无法加载页面,因为我 运行 陷入了无限循环,但无论我多么努力,我都没有注意到这段代码的逻辑问题。

一旦你的循环找到 tds[t].innerHTML == value 的情况,它将 flag 设置为 true - 此时你永远无法结束循环,因为你无处检查情况您可以将 flag 设置为 false,这样您的循环条件将 始终 为真。

这是一个类似的例子,用一个数组来说明这一点。您可以看到,有时它会向数组中添加数字(在它找到新值的情况下),但有时循环会达到 5000 次迭代并退出(因为它从未找到新值),在这种情况下它会添加 undefined 到数组,因为函数没有返回任何东西。

const arr = []
function randomNumber(){
    var value;
    var flag = false;
    var tds = arr
    var iterations = 0

    do {
        value = Math.round(Math.random() * (26 - 1) + 1);
        for(var t = 0; t < tds.length; t++){
            if(tds.includes(value))
                flag = true;
        }
        if(!flag){
            return value;
        }
        iterations += 1
        console.log(iterations)
    } while(flag == true && iterations < 5000)
}

for (let i = 0;i<20;i+=1) {
  arr.push(randomNumber())
}
console.log(arr)

当您的函数至少一次将 flag 设置为 true 时,它​​就结束了 - 它再也不会将其设置为 false。为了修复它,我添加了一行代码。

function randomNumber(){
    var value;
    var flag = false;
    var tds = document.querySelectorAll('td');
    do {
        flag = false; // this line i added
        value = Math.round(Math.random() * (26 - 1) + 1);
        for(var t = 0; t < tds.length; t++){
            if(tds[t].innerHTML == value)
                flag = true;
        }
        if(!flag){
            return value;
        }
    }while(flag == true)
}

我也会写一些更高效的代码给你

function randomNumber(){
    var value;
    var found = false;
    var tds = document.querySelectorAll('td');
    var existingIds = [];
    tds.forEach(td => existingIds.push(td.innerHHML)); // fill up the ids
    do {
        value = Math.round(Math.random() * (26 - 1) + 1); // this line would make problems (comment below)
        if (existingIds.indexOf(value) === -1) found = true; // check if value can be found in existing ids and if found - set dount to true (you can also return from here, but i would rather user break (if there was more code after this line, than use retur in the middle of any loop;
    } while(found === false)

    return value;
}

随机注释行:

  • random() returns从0到1的数
  • 如您所写 - 该值将是 1 到 26 之间的随机数(仅此值)。
  • 如果所有值都已被使用,那么我们的循环将不会结束(当 1 到 26 之间的所有值都已被使用时,我们永远找不到未使用的 1 到 26 之间的值。

可以做什么

  • 您可以添加一些计数器(如@Ben 所做的那样)并在这种情况下退出循环。
  • 或者您可以将数字 26 提高到更高
  • 您可以使用连续的数字(获取全部,取最大的一个,加 1 return 作为新数字)

你当然可以找到一些其他的方法来应对