【问题标题】:Sudoku algorithm with backtracking - java带回溯的数独算法 - java
【发布时间】:2012-11-15 21:40:53
【问题描述】:

所以我有这个大学任务来解决数独问题……我读到了关于算法 X 和跳舞算法的文章,但它们对我没有帮助。

我需要通过回溯来实现。我用维基百科给出的位置上的数字硬编码了二维数组中的一些索引(所以我确信它是可解决的)。

我得到的代码如下:

public void solveSudoku(int row, int col)
   {
      // clears the temporary storage array that is use to check if there are
      // dublicates on the row/col
      for (int k = 0; k < 9; k++)
      {
         dublicates[k] = 0;
      }
      // checks if the index is free and changes the input number by looping
      // until suitable
      if (available(row, col))
      {
         for (int i = 1; i < 10; i++)
         {
            if (checkIfDublicates(i) == true)
            {
               board[row][col] = i;
               if (row == 8)
                  solveSudoku(0, col + 1);
               else if (col == 8)
                  solveSudoku(row + 1, 0);
               else
                  solveSudoku(row, col + 1);

               board[row][col] = 0;
            }
         }
      }
      // goes to the next row/col
      else
      {
         if (row == 8)
            solveSudoku(0, col + 1);
         else if (col == 8)
            solveSudoku(row + 1, 0);
         else
            solveSudoku(row, col + 1);
      }
   }

   /**
    * Checks if the spot on the certain row-col index is free of element
    * 
    * @param row
    * @param col
    * @return
    */
   private boolean available(int row, int col)
   {
      if (board[row][col] != 0)
         return false;
      else
         return true;
   }

   /**
    * Checks if the number given is not already used in this row/col
    * 
    * @param numberToCheck
    * @return
    */
   private boolean checkIfDublicates(int numberToCheck)
   {
      boolean temp = true;
      for (int i = 0; i < dublicates.length; i++)
      {
         if (numberToCheck == dublicates[i])
         {
            temp = false;
            return false;
         }
         else if (dublicates[i] == 0)
         {
            dublicates[i] = numberToCheck;
            temp = true;
            return true;
         }
      }
      return temp;
   }

我正在使用 StackOverflow

// goes to the next row/col
          else
          {
             if (row == 8)
                solveSudoku(0, col + 1);
             else if (col == 8)
                solveSudoku(row + 1, 0);
             else
                solveSudoku(row, col + 1);
          }

这意味着我必须在某个时候停止递归,但我不知道该怎么做! 如果您在 solve() 函数中发现任何其他错误,请告诉我。因为我不确定我是否完全理解“回溯”的东西......

【问题讨论】:

  • byteauthor.com/2010/08/sudoku-solver 有很好的例子。
  • 您应该查看您的复制代码。我不明白这如何检查一个数字是否被允许。你总是重置它(每次 SolveSudoku 调用),所以它会忘记一切。我也怀疑 9 个元素的数组如何检查所有内容

标签: java algorithm sudoku backtracking


【解决方案1】:

例如,如果您跟踪当前的递归深度,您可以停止递归

public void solveSudoku(int row, int col, int recursionDepth) {
    // get out of here if too much
    if (recursionDepth > 15) return;

    // regular code...
    // at some point call self with increased depth
    solveSudoku(0, col + 1, recursionDepth + 1);
}

如果您在 solve() 函数中发现任何其他错误,请告诉我。

代码太多:)

【讨论】:

    【解决方案2】:

    这大致是我过去的做法。

    Whenever all the definite moves have been taken and there is a choice of equally good next moves:
        copy your grid data structure and push it onto a stack.
        take the first candidate move and continue solving recursively
        Whereever you get stuck:
             pop the saved grid off the stack
             take the next candidate move.
    

    【讨论】:

      【解决方案3】:

      我以更简单的方式制作了它:

      public void solve(int row, int col)
         {
            if (row > 8)
            {
               printBoard();
               System.out.println();
               return;
            }
            if (board[row][col] != 0)
            {
               if (col < 8)
                  solve(row, col + 1);
               else
                  solve(row + 1, 0);
            }
            else
            {
               for (int i = 0; i < 10; i++)
                  if (checkRow(row, i) && checkCol(col, i))
                        //&& checkSquare(row, col, i))
                  {
                     board[row][col] = i;
                     if (col < 8)
                        solve(row, col + 1);
                     else
                        solve(row + 1, 0);
                  }
               board[row][col] = 0;
            }
         }
      
         private boolean checkRow(int row, int numberToCheck)
         {
            for (int i = 0; i < 9; i++)
               if (board[row][i] == numberToCheck)
                  return false;
      
            return true;
         }
      
         private boolean checkCol(int col, int numberToCheck)
         {
            for (int i = 0; i < 9; i++)
               if (board[i][col] == numberToCheck)
                  return false;
      
            return true;
         }
      

      【讨论】:

        【解决方案4】:

        我不知道你为什么说 Dancing Links 和算法 X 没有用。
        您的意思是您无法将数独映射到算法 X 旨在解决的精确覆盖问题的实例?
        或者对于您的需要来说,这是一种过于复杂的方法??

        如果是前者,您可能需要查看:A Sudoku Solver in Java implementing Knuth’s Dancing Links Algorithm。这很清楚,也解释了背后的原因。

        注意算法 X 是一种回溯算法,因此,如果这是您唯一的要求,您绝对可以使用这种方法。

        希望这能有所帮助。

        【讨论】:

        • 好吧,我没有说 Dancing Links 和 Algorithm X 没用。我说我不能真正理解它们,所以我不能使用它们。但我会阅读你给我的链接中写的内容。谢谢;)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多