有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

爪哇扫雷机堆垛机

我正在为扫雷舰写一个方法,如果那里没有地雷,它会打开一个单元格。如果地雷旁边没有相邻的单元,它会打开周围没有地雷的单元。我经常犯这样的错误:

java线程“AWT-EventQueue-0”中出现异常。StackOverflowerr先生 这是我的源代码:

public void open(int row, int col) {
    // row = vertical index of the matrix
    // col = horizontal index of matrix
    unclicked--;
    butt[row][col].setEnabled(false); // disable the called button 
    if (aray[row][col] !=0) // checks if there are no adjacent cells with an adjacent mine count >0
      butt[row][col].setText(Integer.toString(aray[row][col]));
    else{

      if(row < size-1){
        open(row+1, col);
        if(col<size-1)
          open(row+1, col+1);
        if(col>0)
          open(row+1, col+1);
      }
      if(row>0){
        if(col>0)
          open(row-1, col-1);
        if(col< size)
          open(row-1, col+1);
      }

      if(col<size-1)
        open(row, col+1);
      if(col>0)
        open(row, col-1);

      return;   
    }  
  }

非常感谢您的帮助


共 (2) 个答案

  1. # 1 楼答案

    太多的递归是你的问题。您的open函数被递归调用的次数太多,导致堆栈溢出。尝试改变你的“else”部分,不要递归。应该是这样的(伪代码):

    public void clean(int i, int j) {
        list = [(i,j)]
        while list.size() > 0:
            i, j = list.pop()
            /*
            Do stuff here:
            Add neighbours to list and unhide current i,j
             */
    }
    
  2. # 2 楼答案

    你的Open方法在某些情况下有无限递归,这就是为什么你会得到StackOverflower错误。你的算法不会检查它是否已经处理了一个单元格,所以它最终会被一遍又一遍地调用相同的单元格,直到它耗尽堆栈

    考虑3×3网格的场景。在这个例子中size = 3。假设单击了第2行第1列,我们将得到以下调用堆栈:

    open(2,1) //initial call
    //row = 2, col = 1
    open(row-1,col-1) // as row>0 and col>0
    //row = 1, col = 0
    open(row+1, col) //as row < size-1
    //row = 2, col = 0
    open(row-1, col+1) //as row > 0 and col< size
    //row = 1, col = 1
    open(row+1, col) //as row < size-1
    //row = 2, col = 1
    open(2,1) //uh-oh, this is the initial call so we're going to overflow the stack.
    

    显然,只有在每次调用aray[row][col] == 0时才会出现这种情况,否则else将不会执行,并且不会生成额外的调用,但这只是代码无限递归的一个示例

    要解决这个问题,你需要检查你是否已经处理了当前的单元格。正如@Marco13在他的评论中指出的那样,你可以通过在方法的开头添加一个检查来查看该单元格是否已经被禁用,因为这意味着该方法已经被该单元格调用:if (!butt[row][col].isEnabled()) return;