我正在尝试编写一个采用数独谜题并解决它的程序。 但是,我在这一行遇到了StackOverflow错误:
Move nMove = new Move(current.nextMove(current, sboard).i, current.nextMove(current, sboard).j);
它有一个方法isLegal,用于检查移动是否有效。如果move有效且下一步移动也有效,则将其添加到堆栈中。如果它有效但下一步不是,则应继续搜索有效数字。 不知道是什么导致了它。
import java.util.Stack;
public class Board {
Stack<Move> stack = new Stack<Move>();
int boardSize = 9;
public int[][] sboard = {{2,0,0,3,9,5,7,1,6},
{5,7,1,0,2,8,3,0,9},
{9,3,0,7,0,1,0,8,2},
{6,8,2,0,3,9,1,0,4},
{3,5,9,1,7,4,6,2,8},
{7,1,0,8,6,0,9,0,3},
{8,6,0,4,1,7,2,9,5},
{1,9,5,2,8,6,4,3,7},
{4,2,0,0,0,0,8,6,1}};
public Board() {
//for every cell in board:
for (int i = 0; i < boardSize; i++) {
for (int j = 0; j < boardSize; j++) {
//get the value of each cell
int temp = getCell(i,j);
//if cell is empty:
if (temp == 0) {
//print out location of cell
System.out.print ("("+i+", "+j+") ");
//guess values for that cell
solve(i, j);
}
}
}
}
//places a value into specified cell
public void setCell(int value, int row, int col) {
sboard[row][col] = value;
}
//returns value contained at specified cell
public int getCell(int row, int col) {
return sboard[row][col];
}
//if value is legal, continue
public boolean isLegal(int value, int row, int col) {
int r = (row / boardSize) * boardSize;
int c = (col / boardSize) * boardSize;
for (int i = 0; i < boardSize; i++) {
for (int j = 0; j < boardSize; j++) {
if (value == getCell(i, col) || value == getCell(row, j)) {
return false;
}
}
}
return true;
}
//guesses values for empty cells
public boolean solve(int i, int j) {
//set location as current
Move current = new Move(i, j);
Move nMove = new Move(current.nextMove(current, sboard).i, current.nextMove(current, sboard).j);
//guesses values 1 through 9 that are legal
for (int k = 1; k <= 9; k++) {
//if a legal value is found and the next move is possible:
if(isLegal(k, i, j) && solve(nMove.i, nMove.j)) {
//add current to stack
stack.push(current);
//enter the value k into the cell
setCell(k, i, j);
//print new value
System.out.print(sboard[i][j]+"\n");
//return as true
return true;
}
else if (stack.empty()){
}
//if next move is not possible
else if(!solve(nMove.i, nMove.j)){
//remove last "solved" location from stack
stack.pop();
//solve last location again
solve(stack.peek());
}
}
return false;
}
public void solve(Move m) {
solve(m.i, m.j);
}
public static void main(String[] args) {
Board b = new Board();
}
};
class Move {
int i, j;
public Move(int i, int j) {
this.i = i;
this.j = j;
}
public int i() { return i;}
public int j() { return j;}
public Move nextMove(Move current, int[][] sboard){
for (int i = current.i; i < 9; i++) {
for (int j = current.j; j < 9; j++) {
//get the value of each cell
int temp = sboard[i][j];
if (temp == 0) {
return new Move(i, j);
}
}
}
return current;
}
};
答案 0 :(得分:1)
首先,以current.nextMove(current, board)
的形式提供此功能似乎是多余的。您可以将此功能设为静态,也可以删除Move current
参数。
但是看一下你的solve(i, j)
函数,你基本上就有这个:
sboard[i][j] = 0
(在某些情况下,它显然是根据您的意见)。solve(i, j)
。current
将为new Move(i, j)
。nMove
也将是new Move(i, j)
(因为在Move#nextMove中,
你基本上说if sboard[i][j] == 0
,它从步骤开始
1)。solve(nMove.i, nMove.j)
nMove.i == i
和nMove.j == j
以来,您基本上是再次致电solve(i, j)
。由于您使用相同的参数调用相同的函数,并且没有达到任何基本情况,因此最终会出现堆栈溢出。
答案 1 :(得分:0)
由于您已定义(显式)堆栈,因此不应以递归方式调用solve()。
只需循环,弹出一个棋盘,生成所有有效的下一步动作,看看其中一个是否是解决方案,如果不是,请将它们推到堆叠上。
(我无法找到你验证电路板完整的地方,但我可能已经累了。)
顺便说一下,堆栈应该是Dequeue。我相信堆栈是同步的,这会降低代码的速度。