问题
Im writing a method for minesweeper that opens a cell if there is no mine there. If there are no adjacent cells next to mines, it opens the cells around it that do not have mines. I regularly have this error:
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError This is my source code:
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;
}
}
Help would be much appreciated
回答1:
Your Open
method has infinite recursion in some scenarios which is why you are getting a StackOverflowError. Your algorithm doesn't check whether or not it has already handled a cell so it ends up being called for the same cells over and over until it blows the stack.
Consider the scenario of a 3 x 3 grid. In this instance size = 3
. Imagine that row 2, column 1 was clicked we would end up with the following call stack:
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.
Obviously this situation only arises if aray[row][col] == 0
on each call otherwise the else
won't execute and the extra calls aren't generated but this is only one example of how the code infinitely recurs.
To solve the issue you need to check if you have already dealt with the current cell. As @Marco13 pointed out in his comment you can do this by adding a check at the start of the method to see if the cell is already disabled as this means the method has already been called for that cell: if (!butt[row][col].isEnabled()) return;
.
回答2:
Too many recursions is your problem. Your open function is called too many times recursively and causes a stack overflow. Try to change your "else" part by doing it without recursion. It would be something like this (pseudo-code):
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
*/
}
来源:https://stackoverflow.com/questions/24598121/minesweeper-stackoverflowerror