无法理解递归如何与此Sudoku解算器一起使用

时间:2014-02-07 10:02:54

标签: java recursion sudoku

我一直在看这段代码几个小时,我无法弄清楚它是如何工作的。有人可以详细解释递归是如何使用这些函数的吗?请记住,我是编程新手。

让我最困惑的部分是如何反复调用solve()?难道它不会在它到达拼图之后停止[row] [col] = 0?

顺便说一下,这是工作代码。

编辑:谢谢你的回答!但我不知道它在哪里回溯。

void solve(int row, int col) throws Exception
{
    if(row > 8)
    {
        throw new Exception( "Solution found" ) ;
    }

    if(puzzle[row][col] != 0)
    {
        next(row, col);
    }
    else
    {
        for( int num = 1; num < 10; num++ )
         {
            if( checkHorizontal(row,num) && checkVertical(col,num) && checkBox(row,col,num) )
            {
               puzzle[row][col] = num ;
               next( row, col ) ;
            }
         }
         puzzle[row][col] = 0 ;
    }
}

 public void next( int row, int col ) throws Exception
 {
      if( col < 8 )
      {
          solve(row, col + 1) ;
      }
      else
      {
          solve(row + 1, 0) ;
      }

 }

1 个答案:

答案 0 :(得分:1)

next函数可以描述为查找第一个空闲字段的函数,并从该字段开始求解过程。

实际的递归就是一个简单的回溯(http://en.wikipedia.org/wiki/Backtracking)。使用某些伪代码可能更容易掌握一般方案:

Solution findSolution(Board board) {
    if (board.isSolved()) return solutionFor(board);


    // An "action" here refers to placing any number 
    // on any free field
    for (each possible action) {

        do the action // That is: place a number on a free field

        // The recursion:
        Solution solution = findSolution(board);
        if (solution != null) return solution;

        // No solution found
        UNdo the action // That is: remove the number from the field

        // Now the loop continues, and tries the 
        // next action...
    }

    // Tried all possible actions, none did lead to a solution
    return null;
 }

通常,人们会用两个嵌套的for循环确定这些“动作”:

for (each free field f)
{
    for (each number n in 1..9)
    {
        place 'n' on 'f' 
        try to find solution
        remove 'n' from 'f' 
    }
}

在这种情况下,外部循环在next函数中有些“隐藏”。

在这种情况下,对于数独,这种特殊的回溯实现可能效果不佳。它可能需要几万亿年才能找到解决方案,因为它有很多可能性。但这基本上取决于check*方法实现的“聪明”程度。快速检测(部分)解决方案已经无效的情况非常重要。也就是说,无论你是否有无法找到解决方案的情况。例如,当3x3-sqares之一的两个单元格包含相同的数字时,情况已经“无效”。例如,可以通过显式存储仍然可用的数字来避免这种情况,但当然代码会变得更加复杂。