Math.random引发调用栈溢出及偶数次水果数组生成问题求助
解决生成偶数次水果数组的栈溢出问题
问题根源分析
原代码的递归逻辑存在多个致命缺陷:
- 随机插入位置时,重复选中已占用索引会触发递归调用,但循环变量未做调整,导致同一轮循环反复递归,最终触发栈溢出。
- 生成的重复次数(2或4)可能超过剩余可用位置,导致无法完成填充,递归失去终止条件。
generateRandomFruits未返回任何值,最终randomizedFruits始终为undefined。
修复方案:更可靠的构建+洗牌思路
换一种更简洁且避免递归的方式:先构建一个包含偶数次水果的数组,再通过洗牌保证随机性。
const fruitsList = [ { id: 1, img: "/apple.jpg", flipped: false }, { id: 2, img: "/banana.jpg", flipped: false }, { id: 3, img: "/cherry.jpg", flipped: false }, { id: 4, img: "/coconut.jpg", flipped: false }, { id: 5, img: "/grapes.jpg", flipped: false }, { id: 6, img: "/lemon.jpg", flipped: false }, { id: 7, img: "/muskmelon.jpg", flipped: false }, { id: 8, img: "/watermelon.jpg", flipped: false }, ]; function generateRandomFruits() { const result = []; let remainingSlots = 12; // 为每个水果分配2或4次出现(不超过剩余位置) for (const fruit of fruitsList) { if (remainingSlots <= 0) break; // 计算当前水果最多能加的偶数次数 const maxCount = Math.min(4, remainingSlots); // 随机选2或4(如果剩余位置允许) const count = Math.random() > 0.5 && maxCount >=4 ? 4 : 2; // 加入数组 for (let i = 0; i < count; i++) { result.push({...fruit}); // 浅拷贝避免引用共享 } remainingSlots -= count; } // 补全剩余位置(每次补2个,保证次数为偶数) while (remainingSlots > 0) { const randomFruit = fruitsList[Math.floor(Math.random() * fruitsList.length)]; result.push({...randomFruit}); result.push({...randomFruit}); remainingSlots -= 2; } // Fisher-Yates洗牌算法打乱顺序 for (let i = result.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [result[i], result[j]] = [result[j], result[i]]; } return result; } const randomizedFruits = generateRandomFruits(); console.log(randomizedFruits);
方案优势
- 无递归风险:全程用循环实现,彻底避免栈溢出问题。
- 严格保证偶数次:每个水果的出现次数都是2或4,总长度固定为12。
- 随机性充足:通过洗牌算法保证最终数组的随机分布。
- 避免引用问题:浅拷贝水果对象,防止后续修改
flipped等属性时影响原数组。
内容的提问来源于stack exchange,提问作者Abhi
相关产品推荐
相关产品推荐

