2011-11-02 3 views
1

나는 스도쿠 퍼즐을 취하고 해결하는 프로그램을 작성하려고합니다. 그러나,이 라인에서 StackOverflow의 오류로 실행 해요 :StackOverflow 오류가 발생했습니다

Move nMove = new Move(current.nextMove(current, sboard).i, current.nextMove(current, sboard).j); 

은 이동이 유효한지 여부를 확인하는 방법 isLegal 있습니다. 이동이 유효하고 다음 이동이 유효하면 스택에 추가됩니다. 유효하지만 다음 이동이 유효하지 않은 경우 올바른 번호를 계속 검색해야합니다. 무엇이 원인인지 확실하지 않습니다.

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; 
    } 
}; 
+3

일반적으로 stackoverflow 오류는 종료되지 않는 재귀 함수로 인해 발생합니다. solve() 함수는 재귀 적으로 보인다 ... 기본 조건을 생각하고 종료해야 할 때/자신을 호출하는 것을 멈추어야한다. – mpen

+1

당신은 확실히 당신의 생성자로부터'solve' 함수 호출을 옮기고 싶습니다. – Perception

+1

그래, 아마 재귀 루프 때문일거야. 예외를 잡아 내고 ex.printStackTrace()를 호출하여 메소드 계층 구조를 살펴볼 수 있습니다. – oldSkool

답변

1

하나를 들어, 형식 current.nextMove(current, board)이 기능을 가지고 나에게 중복 보인다. 이 함수를 정적으로 만들거나 Move current 매개 변수를 제거 할 수 있습니다.

하지만 당신의 solve(i, j) 기능을 살펴 복용, 당신은 기본적으로이 있습니다

  1. sboard[i][j] = 0 가정 (가 명확하지하는 경우에, 당신의 입력에서).
  2. solve(i, j)으로 전화한다고 가정합니다.
  3. currentnew Move(i, j)입니다.
  4. nMove
  5. 다음도 new Move(i, j) 될 것입니다 (이동 # nextMove, 당신이 본질적으로 단계 1에서 수행 if sboard[i][j] == 0을 말 이후).
  6. 당신은 nMove.i == inMove.j == j 때문에, 당신은 본질적으로 다시 solve(i, j)를 호출 solve(nMove.i, nMove.j)
  7. 호출 끝날 것입니다.

동일한 매개 변수로 동일한 함수를 호출하고 기본 사례에 도달하지 않으므로 결국 스택 오버플로가 발생합니다.

0

(명시 적) 스택을 정의 했으므로 solve()를 재귀 적으로 호출하면 안됩니다.

루프를 움직여 보드를 튕기고 유효한 모든 다음 동작을 생성하고 그 중 하나가 솔루션인지 확인한 다음 그 중 하나가 솔루션인지 확인하고 그렇지 않은 경우 스택에 밀어 넣습니다.

은 (당신이 보드가 완전한지 확인 어디서 찾을 수 없습니다,하지만 난 아마 피곤하다.)

는, BTW 스택은 아마 큐에서해야한다. 스택이 동기화되어 코드가 느려지는 것 같습니다.

관련 문제