p5js开发扫雷点击0周边雷方块或炸弹报Max call stack size exceeded错误
问题核心原因
- 无限递归导致栈溢出:
reveal方法递归展开相邻方块时,没有判断当前方块是否已经被展开过,相邻的无炸弹方块会互相触发reveal调用,最终触发栈溢出导致游戏崩溃,这也是点击炸弹、点击0炸弹方块都会崩溃的核心诱因。 - 炸弹生成逻辑错误:
setFeild方法中生成方块的逻辑完全颠倒:调用SelectBomb判断为炸弹后,你重新实例化了一个默认isBomb=true的新方块,相当于所有方块最终都会被标记为炸弹,逻辑完全错误。 - 数组越界风险:你定义的
grid和baseGrid都是11行,但画布大小只有400400(对应1010的40px方块),第11行的方块超出画布边界,计数周边炸弹时可能触发异常。 - 剩余方块计数错误:只有点击方块时会扣减
remainingSpaces,自动展开的方块没有扣减,同时递归调用reveal时会重复扣减计数,导致获胜逻辑异常。 - 数字被覆盖:没有统一的渲染逻辑,后展开的方块绘制背景时会覆盖相邻方块已经绘制的数字,导致数字消失。
修复方案
- 给
Block类新增isRevealed属性,默认值为false,每次调用reveal时先判断如果已经是true就直接返回,终止递归。 - 修正炸弹生成逻辑:调用
SelectBomb后如果是炸弹就直接保留,不要重新实例化方块。 - 删掉
grid和baseGrid的第11行,保留10行即可,对应400px高度的画布。 - 只有第一次展开方块的时候扣减
remainingSpaces,自动展开的方块同步扣减。 - 统一先完成所有方块状态更新,再统一绘制所有方块和数字,避免覆盖。
关键代码修改示例
- Block构造函数新增属性:
constructor(x, y, scale, color) { this.x = x; this.y = y; this.scale = scale; this.color = color; this.isBomb = true; this.nearBombs = 0; this.hasCounted = false; this.isRevealed = false; // 新增展开状态标记 }
- reveal方法开头加终止条件,统一处理计数:
reveal(placement) { if (this.isRevealed) return; // 已经展开过直接返回,终止递归 this.isRevealed = true; remainingSpaces--; // 统一在这里扣减剩余方块数 // 原有逻辑保持不变 }
- 修正setFeild里的炸弹生成逻辑:
let block = new Block(x * 40, y * 40, 40, grid[y][x] == 1 ? "green" : "lime"); block.SelectBomb(); if (block.isBomb) { amountOfBombs += 1; } grid[y][x] = block; block.draw();
- 删掉
mousePressed方法里的remainingSpaces--代码,改为在reveal里统一处理即可。
内容的提问来源于stack exchange,提问作者Maddox Fox
相关产品推荐
相关产品推荐

