生成1-24不重复随机数时触发RangeError: Maximum Call Stack Size Exceeded
生成1-24不重复随机数时出现调用栈溢出错误
我正在开发一个JavaScript项目,需要生成1-24之间的24个不重复随机数。运行代码时,在Safari、Firefox和Chrome浏览器中均出现RangeError: Maximum Call Stack Size Exceeded错误。我对调用栈了解有限,但知道递归次数过多会触发此类错误,且错误出现在generated24()函数的if语句中。我尝试过拆分if语句、拆分函数等基础方法,但问题仍未解决。我是JavaScript新手,若表述有误还请见谅,感谢您的帮助!
原代码
let d1 = 0 let d2 = 0 let d3 = 0 let d4 = 0 let d5 = 0 let d6 = 0 let d7 = 0 let d8 = 0 let d9 = 0 let d10 = 0 let d11 = 0 let d12 = 0 let d13 = 0 let d14 = 0 let d15 = 0 let d16 = 0 let d17 = 0 let d18 = 0 let d19 = 0 let d20 = 0 let d21 = 0 let d22 = 0 let d23 = 0 let d24 = 0 function getRandomInt(max) { return Math.floor(Math.random() * max); } function generated1() { d1 = getRandomInt(24) if (d1 == 0) { generated1() } else { generated2() } } function generated2() { d2 = getRandomInt(24) if (d2 == d1) { generated2() } else if (d2 == 0) { generated2() } else { generated3() } } function generated3() { d3 = getRandomInt(24) if (d3 == d2 || d3 == d1 || d3 == 0) { generated3() } else { generated4() } } function generated4() { d4 = getRandomInt(24) if (d4 == d3 || d4 == d2 || d4 == d1 || d4 == 0) { generated4() } else { generated5() } } function generated5() { d5 = getRandomInt(24) if (d5 == d4 || d5 == d3 || d5 == d2 || d5 == d1 || d5 == 0) { generated5() } else { generated6() } } function generated6() { d6 = getRandomInt(24) if (d6 == d5 || d6 == d4 || d6 == d3 || d6 == d2 || d6 == d1 || d6 == 0) { generated6() } else { generated7() } } function generated7() { d7 = getRandomInt(24) if (d7 == d6 || d7 == d5 || d7 == d4 || d7 == d3 || d7 == d2 || d7 == d1 || d7 == 0) { generated7() } else { generated8() } } function generated8() { d8 = getRandomInt(24) if (d8 == d7 || d8 == d6 || d8 == d5 || d8 == d4 || d8 == d3 || d8 == d2 || d8 == d1 || d8 == 0) { generated8() } else { generated9() } } function generated9() { d9 = getRandomInt(24) if (d9 == d8 || d9 == d7 || d9 == d6 || d9 == d5 || d9 == d4 || d9 == d3 || d9 == d2 || d9 == d1 || d9 == 0) { generated9() } else { generated10() } } function generated10() { d10 = getRandomInt(24) if (d10 == d9 || d10 == d8 || d10 == d7 || d10 == d6 || d10 == d5 || d10 == d4 || d10 == d3 || d10 == d2 || d10 == d1 || d10 == 0) { generated10() } else { generated11() } } function generated11() { d11 = getRandomInt(24) if (d11 == d10 || d11 == d9 || d11 == d8 || d11 == d7 || d11 == d6 || d11 == d5 || d11 == d4 || d11 == d3 || d11 == d2 || d11 == d1 || d11 == 0) { generated11() } else { generated12() } } function generated12() { d12 = getRandomInt(24) if (d12 == d11 || d12 == d10 || d12 == d9 || d12 == d8 || d12 == d7 || d12 == d6 || d12 == d5 || d12 == d4 || d12 == d3 || d12 == d2 || d12 == d1 || d12 == 0) { generated12() } else { generated13() } } function generated13() { d13 = getRandomInt(24) if (d13 == d12 || d13 == d11 || d13 == d10 || d13 == d9 || d13 == d8 || d13 == d7 || d13 == d6 || d13 == d5 || d13 == d4 || d13 == d3 || d13 == d2 || d13 == d1 || d13 == 0) { generated13() } else { generated14() } } function generated14() { d14 = getRandomInt(24) if (d14 == d13 || d14 == d12 || d14 == d11 || d14 == d10 || d14 == d9 || d14 == d8 || d14 == d7 || d14 == d6 || d14 == d5 || d14 == d4 || d14 == d3 || d14 == d2 || d14 == d1 || d14 == 0) { generated14() } else { generated15() } } function generated15() { d15 = getRandomInt(24) if (d15 == d14 || d15 == d13 || d15 == d12 || d15 == d11 || d15 == d10 || d15 == d9 || d15 == d8 || d15 == d7 || d15 == d6 || d15 == d5 || d15 == d4 || d15 == d3 || d15 == d2 || d15 == d1 || d15 == 0) { generated15() } else { generated16() } } function generated16() { d16 = getRandomInt(24) if (d16 == d15 || d16 == d14 || d16 == d13 || d16 == d12 || d16 == d11 || d16 == d10 || d16 == d9 || d16 == d8 || d16 == d7 || d16 == d6 || d16 == d5 || d16 == d4 || d16 == d3 || d16 == d2 || d16 == d1 || d16 == 0) { generated16() } else { generated17() } } function generated17() { d17 = getRandomInt(24) if (d17 == d16 || d17 == d15 || d17 == d14 || d17 == d13 || d17 == d12 || d17 == d11 || d17 == d10 || d17 == d9 || d17 == d8 || d17 == d7 || d17 == d6 || d17 == d5 || d17 == d4 || d17 == d3 || d17 == d2 || d17 == d1 || d17 == 0) { generated17() } else { generated18() } } function generated18() { d18 = getRandomInt(24) if (d18 == d17 || d18 == d16 || d18 == d15 || d18 == d14 || d18 == d13 || d18 == d12 || d18 == d11 || d18 == d10 || d18 == d9 || d18 == d8 || d18 == d7 || d18 == d6 || d18 == d5 || d18 == d4 || d18 == d3 || d18 == d2 || d18 == d1 || d18 == 0) { generated18() } else { generated19() } } function generated19() { d19 = getRandomInt(24) if (d19 == d18 || d19 == d17 || d19 == d16 || d19 == d15 || d19 == d14 || d19 == d13 || d19 == d12 || d19 == d11 || d19 == d10 || d19 == d9 || d19 == d8 || d19 == d7 || d19 == d6 || d19 == d5 || d19 == d4 || d19 == d3 || d19 == d2 || d19 == d1 || d19 == 0) { generated19() } else { generated20() } } function generated20() { d20 = getRandomInt(24) if (d20 == d19 || d20 == d18 || d20 == d17 || d20 == d16 || d20 == d15 || d20 == d14 || d20 == d13 || d20 == d12 || d20 == d11 || d20 == d10 || d20 == d9 || d20 == d8 || d20 == d7 || d20 == d6 || d20 == d5 || d20 == d4 || d20 == d3 || d20 == d2 || d20 == d1 || d20 == 0) { generated20() } else { generated21() } } function generated21() { d21 = getRandomInt(24) if (d21 == d20 || d21 == d19 || d21 == d18 || d21 == d17 || d21 == d16 || d21 == d15 || d21 == d14 || d21 == d13 || d21 == d12 || d21 == d11 || d21 == d10 || d21 == d9 || d21 == d8 || d21 == d7 || d21 == d6 || d21 == d5 || d21 == d4 || d21 == d3 || d21 == d2 || d21 == d1 || d21 == 0) { generated21() } else { generated22() } } function generated22() { d22 = getRandomInt(24) if (d22 == d21 || d22 == d20 || d22 == d19 || d22 == d18 || d22 == d17 || d22 == d16 || d22 == d15 || d22 == d14 || d22 == d13 || d22 == d12 || d22 == d11 || d22 == d10 || d22 == d9 || d22 == d8 || d22 == d7 || d22 == d6 || d22 == d5 || d22 == d4 || d22 == d3 || d22 == d2 || d22 == d1 || d22 == 0) { generated22() } else { generated23() } } function generated23() { d23 = getRandomInt(24) if (d23 == d22 || d23 == d21 || d23 == d20 || d23 == d19 || d23 == d18 || d23 == d17 || d23 == d16 || d23 == d15 || d23 == d14 || d23 == d13 || d23 == d12 || d23 == d11 || d23 == d10) { generated23() } if (d23 == d9 || d23 == d8 || d23 == d7 || d23 == d6 || d23 == d5 || d23 == d4 || d23 == d3 || d23 == d2 || d23 == d1 || d23 == 0) { generated23() } else { generated24() } } function generated24() { d24 = getRandomInt(24) if (d24 == d23 || d24 == d22 || d24 == d21 || d24 == d20 || d24 == d19 || d24 == d18 || d24 == d17 || d24 == d16 || d24 == d15 || d24 == d14 || d24 == d13 || d24 == d12 || d24 == d11 || d24 == d10 || d24 == d9 || d24 == d8 || d24 == d7 || d24 == d6 || d24 == d5 || d24 == d4 || d24 == d3 || d24 == d2 || d24 == d1 || d24 == 0) { generated24() } else { printAll() } } function printAll() { console.log(d1) console.log(d2) console.log(d3) console.log(d4) console.log(d5) console.log(d6) console.log(d7) console.log(d8) console.log(d9) console.log(d10) console.log(d11) console.log(d12) console.log(d13) console.log(d14) console.log(d15) console.log(d16) console.log(d17) console.log(d18) console.log(d19) console.log(d20) console.log(d21) console.log(d22) console.log(d23) console.log(d24) }
问题原因
- 递归无限制调用:越到后面的函数(比如
generated24()),可选的有效数字越少,随机函数可能反复生成已存在的数字或0,导致递归次数远超浏览器调用栈上限,触发溢出错误。 - 代码冗余且逻辑有漏洞:
generated23()的两个if语句是独立判断,若第一个if触发递归,递归回来后会继续执行第二个if,可能导致重复判断或逻辑错误;同时24个独立变量和重复函数完全没必要,增加了出错概率。
解决方案:Fisher-Yates洗牌算法
这是生成不重复随机序列的标准高效方法,用循环替代递归,彻底避免栈溢出问题:
// 生成1-24的有序数组 function createNumberList() { const list = []; for (let i = 1; i <= 24; i++) { list.push(i); } return list; } // Fisher-Yates洗牌:原地打乱数组 function shuffleList(list) { let currentPos = list.length; while (currentPos > 0) { // 随机选一个未打乱的位置 const random
相关产品推荐
相关产品推荐

