为什么我的 C# 数独解算器不起作用?

bad*_*_94 -1 c# solver sudoku

这是我的第一篇文章,所以如果我做错了,我深表歉意。几个月前我开始使用 Python 编写代码,现在已经转向 C#。为了学习回溯,我尝试编写数独求解器。但是,在我的一生中,我无法理解为什么我的代码不起作用。当然,有很多解决方案。我觉得现在对我来说进步的最好方法是了解我的个人代码中缺少什么。所以,如果你有时间:

为什么我的代码不会返回已解决的数独板?我怀疑问题出在递归上。

主要程序:

using System;

namespace Sudoku
{
    class Program
    {
        static void Main(string[] args)
        {          
            
            var sudokuTemplate = new SudokuTemplate();
            var sudoku = sudokuTemplate.CreateSudoku();
            Print.print(sudoku);
            Console.WriteLine();
            Print.print(driver(sudoku));
        }    

        static int[,] driver(int[,] board)
        {
            var check = new ErrorCheck();

            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    if (board[i,j] == 0)
                    {   
                        for (int n = 1; n <= 9; n++)
                        {
                            if (check.legal(board, i, j, n))
                            {
                                board[i, j] = n;  
                                driver(board); 
                            }   
                            else
                            {
                                board[i, j] = 0;
                            }                         
                        } 
                        return board;                      
                    }                  
                }
            }
            return board;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

未解的数独

    namespace Sudoku
{
    class SudokuTemplate
    {
        public int[,] CreateSudoku()
        {
            var array = new int[,] 
            {
                {5,3,0,0,7,0,0,0,0},  
                {6,0,0,1,9,5,0,0,0},  
                {0,9,8,0,0,0,0,6,0},  
                {8,0,0,0,6,0,0,0,3},  
                {4,0,0,8,0,3,0,0,1},  
                {7,0,0,0,2,0,0,0,6},  
                {0,6,0,0,0,0,2,8,0},  
                {0,0,0,4,1,9,0,0,5},  
                {0,0,0,0,8,0,0,7,9}  
            };
            return array;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

错误检查器检查数字 n 是否合法放置在板上:

namespace Sudoku
{
    public class ErrorCheck
    {
        public bool legal(int[,]array, int row, int col, int n)
        {   //check col & rw
            for (int i = 0; i < 9; i++)
            {
                if (array[row, i] == n)
                {
                    return false;
                }
                if (array[i, col] == n)
                {
                    return false;
                }
            }

            //check boxes
            int valRow = 0;
            if (row < 6 && row > 2)
            {
                valRow = 3;
            }
            else if (row < 9 && row > 5)
            {
                valRow = 6;
            }

            int valCol = 0;
            if (col < 6 && col > 2)
            {
                valCol = 3;
            }
            else if (col < 9 && col > 5)
            {
                valCol = 6;
            }
            
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (array[(j+valRow), (i+valCol)] == n)
                        {
                            return false;
                        }
                }
            }
            return true;
        }   
        
    }
}
Run Code Online (Sandbox Code Playgroud)

最后是打印功能:

    namespace Sudoku
{
    class Print
    {
        public static void print(int[,] array)
        {
            // prints sudoku
            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++) 
                {
                    Console.Write("{0} ", array[i, j]);
                    Console.Write("|");     
                }
                Console.WriteLine();
            }
            
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

代码导致原始未解数独板打印两次。最初似乎工作正常,但在某个地方,所有内容都只是重置为原始未解决的板。

小智 5

存在三个问题。

第一个是 sgmoore 的答案,数独无效。尝试从互联网复制现有的数独。

第二个是在 ErrorCheck 类中:

if (array[(i+valCol), (j+valRow)] == n)
Run Code Online (Sandbox Code Playgroud)

您必须反转矩阵的两个索引才能获得正确的框。

if (array[(j+valRow), (i+valCol)] == n)
Run Code Online (Sandbox Code Playgroud)

第三个错误出现在 Program 类中:您在单元格中放入了第一个有效数字。在数独中,您必须输入唯一有效的数字。因此,在我看来,对于每个单元格,您必须检查所有九个数字并将所有可能的值保存在列表中,之后如果只有一个可能的值,则将其放入。此方法对于简单的数独来说已经足够了,但如果复杂性增加,您将不得不使用其他高级技术,例如双对或 X-Wing。

除了错误之外,我认为您的代码非常清晰且易于阅读。我要做的唯一更改是在 Program 类中将“i”和“j”重命名为“row”和“col”。