Android Studio扫雷递归触发java.lang.StackOverflowError错误求解
问题原因分析
- 核心问题是缺少已揭示格子的拦截判断:当前代码只要坐标合法就会执行完整逻辑,哪怕格子已经被设置为
revealed=true,会导致相邻的0值格子互相递归调用,进入死循环最终栈溢出。比如格子(i,j)是0,调用相邻的(i+1,j),如果(i+1,j)也是0,又会回头调用(i,j),无限递归很快就会撑爆8MB栈空间。 - 次要问题是冗余的多分支判断,可优化简化代码逻辑。
修复方案
进入函数第一时间增加已揭示格子的拦截逻辑,只要格子已经被揭开就直接返回,完全避免重复递归调用。修复后代码如下:
public void bomb(int i,int j) { // 先判断坐标越界 或 格子已被揭示,直接返回终止递归 if(i < 0 || i >= 8 || j < 0 || j >= 10 || board[i][j].isRevealed()) { return; } // 标记当前格子为已揭示 board[i][j].setRevealed(true); int mineNearby = board[i][j].getNumOfMinesNearby(); switch (mineNearby) { case 0: board[i][j].setPicture("@drawable/zero"); board_xml[i][j].setImageResource(R.drawable.zero); // 递归展开周围8格 bomb(i-1,j+1); bomb(i-1,j); bomb(i-1,j-1); bomb(i,j+1); bomb(i,j-1); bomb(i+1,j+1); bomb(i+1,j); bomb(i+1,j-1); break; case 1: board[i][j].setPicture("@drawable/one"); board_xml[i][j].setImageResource(R.drawable.one); break; case 2: board[i][j].setPicture("@drawable/two"); board_xml[i][j].setImageResource(R.drawable.two); break; case 3: board[i][j].setPicture("@drawable/three"); board_xml[i][j].setImageResource(R.drawable.three); break; case 4: board[i][j].setPicture("@drawable/four"); board_xml[i][j].setImageResource(R.drawable.four); break; // 如有5-8的相邻雷数需求,补充对应case即可 } }
额外优化建议
如果后续需要适配更大尺寸的棋盘,可以把递归实现改为基于队列的广度优先搜索(BFS)实现,完全规避栈溢出风险,兼容性更强。
内容的提问来源于stack exchange,提问作者עמית אזרזר
相关产品推荐
相关产品推荐

