C语言中的回溯数独解算器

C语言中的回溯数独解算器,c,recursion,backtracking,solver,C,Recursion,Backtracking,Solver,这是一个我被要求为一门课做的程序,它必须解决一个nxn大小的数独难题 使用回溯算法,但不需要检查子正方形,只检查行和列。 我的程序的问题是,回溯部分从不触发:(每当它到达无法继续的点时,它就会停止并打印电路板,而不是删除最后一次尝试并尝试其他操作。 很抱歉没有评论,我现在只能访问代码(不在家中),但大部分都是非常简单的函数,问题在于aux_sudoku和sudoku函数,下面是代码: #include <stdio.h> #include <stdlib.h> #incl

这是一个我被要求为一门课做的程序,它必须解决一个nxn大小的数独难题 使用回溯算法,但不需要检查子正方形,只检查行和列。 我的程序的问题是,回溯部分从不触发:(每当它到达无法继续的点时,它就会停止并打印电路板,而不是删除最后一次尝试并尝试其他操作。 很抱歉没有评论,我现在只能访问代码(不在家中),但大部分都是非常简单的函数,问题在于aux_sudoku和sudoku函数,下面是代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define UNASSIGNED 0

bool aux_SolveSudoku(int n, int array[][n]);
bool SolveSudoku(int n, int array[][n], int row, int col);
bool check(int n, int array[][n], int row, int col, int number);
bool CheckRow(int n, int array[][n], int row, int number);
bool CheckCol(int n, int array[][n], int col, int number);
bool CheckIfFull(int n, int array[][n]);
void printArray(int n, int array[][n]);

int main()
{
    int n;
    scanf(" %d", &n);
    int array[n][n];

    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            scanf(" %d",&array[i][j]);
        }
    }
    if (aux_SolveSudoku(n, array) == true)
          printArray(n, array);
    else
         printf("No Solution!");


  return 0;
}

bool aux_SolveSudoku(int n, int array[][n]){
    for (int row = 0; row < n; row++){
        for (int col = 0; col < n; col++){
            if (SolveSudoku(n, array, row, col) && CheckIfFull(n, array))
                return true;}
    }
    return false;
}

bool SolveSudoku(int n, int array[][n], int row, int col){
    if(array[row][col] != UNASSIGNED)
        return true;

    for(int i=1; i<=n; i++){
        if(check(n, array, row, col, i)){
            array[row][col] = i;

            if(SolveSudoku(n, array, row, col))
                return true;

            array[row][col] = UNASSIGNED;
        }
    }    
    return false;
}

bool check(int n, int array[][n], int row, int col, int number){
    return (!CheckRow(n, array, row, number) && !CheckCol(n, array, col, number));
} 

bool CheckRow(int n, int array[][n], int row, int number){
    for (int col = 0; col < n; col++){
        if (array[row][col] == number){
            return true;}
    }
    return false;
}

bool CheckCol(int n, int array[][n], int col, int number){
    for (int row = 0; row <  n; row++){
        if (array[row][col] == number){
            return true;}
    }
    return false;

}

bool CheckIfFull(int n, int array[][n]){
    for (int i = 0; i < n; i++){
            for (int j = 0; j < n; j++){
                if(array[i][j] == UNASSIGNED)
                    return false;
                    }
            }
    return true;
}

void printArray(int n, int array[][n]){
    for (int row = 0; row < n; row++){
            for (int col = 0; col < n; col++){
                printf("%d ", array[row][col]);}
            printf("\n");
        }
}
这显然有一个解决方案:

1 3 5 2 4
3 1 4 5 2
4 2 1 3 5
2 5 3 4 1
5 4 2 1 3

不幸的是,该程序没有找到解决方案,但我不明白为什么没有。

您需要提供一个它处理错误的数独板的示例。我的(无可否认,压力不是很大)测试表明它运行正常,尽管它似乎不会在
数独()中重现
,这可能是您关注的要点

3x3可解 插入指令的程序的输出

-->> SolveSudoku (3x3) - r=0, c=0, level = 1:
0 1 0 
2 0 1 
0 0 0 
-->> SolveSudoku (3x3) - r=0, c=2, level = 1:
3 1 0 
2 0 1 
0 0 0 
-->> SolveSudoku (3x3) - r=1, c=1, level = 1:
3 1 2 
2 0 1 
0 0 0 
-->> SolveSudoku (3x3) - r=2, c=0, level = 1:
3 1 2 
2 3 1 
0 0 0 
-->> SolveSudoku (3x3) - r=2, c=1, level = 1:
3 1 2 
2 3 1 
1 0 0 
-->> SolveSudoku (3x3) - r=2, c=2, level = 1:
3 1 2 
2 3 1 
1 2 0 
Solution:
3 1 2 
2 3 1 
1 2 3 
-->> SolveSudoku (4x4) - r=0, c=1, level = 1:
4 0 1 0 
3 2 0 0 
0 0 0 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=0, c=3, level = 1:
4 3 1 0 
3 2 0 0 
0 0 0 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=1, c=2, level = 1:
4 3 1 2 
3 2 0 0 
0 0 0 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=1, c=3, level = 1:
4 3 1 2 
3 2 4 0 
0 0 0 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=2, c=0, level = 1:
4 3 1 2 
3 2 4 1 
0 0 0 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=2, c=1, level = 1:
4 3 1 2 
3 2 4 1 
1 0 0 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=2, c=2, level = 1:
4 3 1 2 
3 2 4 1 
1 4 0 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=3, c=0, level = 1:
4 3 1 2 
3 2 4 1 
1 4 2 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=3, c=1, level = 1:
4 3 1 2 
3 2 4 1 
1 4 2 3 
2 0 0 0 
-->> SolveSudoku (4x4) - r=3, c=2, level = 1:
4 3 1 2 
3 2 4 1 
1 4 2 3 
2 1 0 0 
-->> SolveSudoku (4x4) - r=3, c=3, level = 1:
4 3 1 2 
3 2 4 1 
1 4 2 3 
2 1 3 0 
Solution:
4 3 1 2 
3 2 4 1 
1 4 2 3 
2 1 3 4 
4x4可解 预期解决方案

4 3 1 2
3 2 4 1
1 4 2 3
2 1 3 4
插入指令的程序的输出

-->> SolveSudoku (3x3) - r=0, c=0, level = 1:
0 1 0 
2 0 1 
0 0 0 
-->> SolveSudoku (3x3) - r=0, c=2, level = 1:
3 1 0 
2 0 1 
0 0 0 
-->> SolveSudoku (3x3) - r=1, c=1, level = 1:
3 1 2 
2 0 1 
0 0 0 
-->> SolveSudoku (3x3) - r=2, c=0, level = 1:
3 1 2 
2 3 1 
0 0 0 
-->> SolveSudoku (3x3) - r=2, c=1, level = 1:
3 1 2 
2 3 1 
1 0 0 
-->> SolveSudoku (3x3) - r=2, c=2, level = 1:
3 1 2 
2 3 1 
1 2 0 
Solution:
3 1 2 
2 3 1 
1 2 3 
-->> SolveSudoku (4x4) - r=0, c=1, level = 1:
4 0 1 0 
3 2 0 0 
0 0 0 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=0, c=3, level = 1:
4 3 1 0 
3 2 0 0 
0 0 0 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=1, c=2, level = 1:
4 3 1 2 
3 2 0 0 
0 0 0 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=1, c=3, level = 1:
4 3 1 2 
3 2 4 0 
0 0 0 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=2, c=0, level = 1:
4 3 1 2 
3 2 4 1 
0 0 0 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=2, c=1, level = 1:
4 3 1 2 
3 2 4 1 
1 0 0 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=2, c=2, level = 1:
4 3 1 2 
3 2 4 1 
1 4 0 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=3, c=0, level = 1:
4 3 1 2 
3 2 4 1 
1 4 2 3 
0 0 0 0 
-->> SolveSudoku (4x4) - r=3, c=1, level = 1:
4 3 1 2 
3 2 4 1 
1 4 2 3 
2 0 0 0 
-->> SolveSudoku (4x4) - r=3, c=2, level = 1:
4 3 1 2 
3 2 4 1 
1 4 2 3 
2 1 0 0 
-->> SolveSudoku (4x4) - r=3, c=3, level = 1:
4 3 1 2 
3 2 4 1 
1 4 2 3 
2 1 3 0 
Solution:
4 3 1 2 
3 2 4 1 
1 4 2 3 
2 1 3 4 
4x4不可解 这是无法解决的,因为在第一排没有地方放2

-->> SolveSudoku (4x4) - r=0, c=1, level = 1:
4 0 1 0 
3 2 0 0 
0 0 0 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=0, c=3, level = 1:
4 3 1 0 
3 2 0 0 
0 0 0 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=1, c=2, level = 1:
4 3 1 0 
3 2 0 0 
0 0 0 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=1, c=3, level = 1:
4 3 1 0 
3 2 4 0 
0 0 0 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=2, c=0, level = 1:
4 3 1 0 
3 2 4 1 
0 0 0 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=2, c=1, level = 1:
4 3 1 0 
3 2 4 1 
1 0 0 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=2, c=2, level = 1:
4 3 1 0 
3 2 4 1 
1 4 0 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=3, c=0, level = 1:
4 3 1 0 
3 2 4 1 
1 4 3 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=3, c=1, level = 1:
4 3 1 0 
3 2 4 1 
1 4 3 2 
2 0 0 0 
-->> SolveSudoku (4x4) - r=3, c=2, level = 1:
4 3 1 0 
3 2 4 1 
1 4 3 2 
2 1 0 0 
-->> SolveSudoku (4x4) - r=3, c=3, level = 1:
4 3 1 0 
3 2 4 1 
1 4 3 2 
2 1 0 0 
No Solution!
插入指令的代码
#包括
#包括
#定义未分配的0
布尔数独(整数n,整数数组[][n]);
布尔数独(整数n,整数数组[][n],整数行,整数列);
布尔检查(整数n,整数数组[][n],整数行,整数列,整数编号);
布尔校验行(整数n,整数数组[][n],整数行,整数编号);
布尔校验列(整数n,整数数组[][n],整数列,整数编号);
bool-checkifull(int-n,int-array[][n]);
void printary(int n,int array[][n]);
内部主(空)
{
int n;
scanf(“%d”和“&n”);
整数数组[n][n];
对于(int i=0;i>数独(%dx%d)-r=%d,c=%d,level=%d:\n”,n,n,行,列,level);
printArray(n,数组);

对于(int i=1;i来说,由于代码的这一部分,回溯无法工作

bool SolveSudoku(int n, int array[][n], int row, int col){
    if(array[row][col] != UNASSIGNED)
        return true;

    for(int i=1; i<=n; i++){
        if(check(n, array, row, col, i)){
            array[row][col] = i;

            if(SolveSudoku(n, array, row, col))
                return true;

            array[row][col] = UNASSIGNED;
        }
    }    
    return false;
}
bool-SolveSudoku(int-n,int-array[][n],int-row,int-col){
if(数组[行][列]!=未分配)
返回true;

对于(int i=1),我只知道这不是有效的C代码。它是C++的C函数。C中没有布尔类型。你必须使用int来代替。@ CaseP255:在C99和C11中有一个<代码>布尔布尔< /COD>类型;如果使用头<代码> <代码>,也有一个<代码> BOOL 类型,代码使用<代码> <代码>。别忘了,MSVC编译器实现了一个几乎是四分之一世纪的标准(今年晚些时候,它将是四分之一个世纪),而不是标准的最新版本。实际上,还有一个原因,C++不是C++代码,它使用C99 VLAS(可变长度数组)。它不是任何C++标准版本的一部分(虽然G+编译器确实接受它们作为扩展)。首先要做的是确保输入的数据与你输入的内容相匹配;在调用<代码> AuxiSudokUsLoValor之前,打印数独板。
。调用入口点
SudokuSolver()
和递归函数
aux\u SudokuSolver()
(反转当前角色)可能更为传统。但是,这只是一些琐事。您在1x1和2x2板上测试过它吗?3x3怎么样?代码对我来说编译得很干净(很好)。我想在处理过程中,在
SudokuSolver()
的每个(递归)条目上打印出电路板,这样我就可以看到它在做什么。非常感谢您的输入,我想我更清楚地了解我的问题所在,但我仍然无法解决:(我尝试根据您的解决方案进行更正(我甚至尝试应对解决方案并使其适应我的代码)但是现在不是不返回到n,而是继续超过n,例如,如果电路板是5x5,无法求解,它开始分配6s来求解它,即使i循环在函数内部停止在5,并且对于某些输入,它出于某种原因进入无限循环。问题是辅助解算数独和解算数独之间的交互。在我的代码,注意我“启动”了solve方法,它负责调用自己。这是一种管理递归级别的简单方法。这有帮助吗?is行为不当的一个例子是:5 0 0 0 2 4 3 1 0 0 2 0 2 1 0 5 2 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0,这应该是可解的。我可以肯定(a)有一个解决方案(1 3 5 2 4 3 1 4 5 2 4 2 1 3 5 2 5 3 4 1 5 2 1 3)和(b)上面的程序找不到它。此外,除非我的级别跟踪代码中存在错误,否则它不会再次出现。到目前为止,我没有更多要补充的内容。我观察到,您可以通过添加失败的示例来改进您的问题-这将为调查提供方向。
-->> SolveSudoku (4x4) - r=0, c=1, level = 1:
4 0 1 0 
3 2 0 0 
0 0 0 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=0, c=3, level = 1:
4 3 1 0 
3 2 0 0 
0 0 0 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=1, c=2, level = 1:
4 3 1 0 
3 2 0 0 
0 0 0 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=1, c=3, level = 1:
4 3 1 0 
3 2 4 0 
0 0 0 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=2, c=0, level = 1:
4 3 1 0 
3 2 4 1 
0 0 0 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=2, c=1, level = 1:
4 3 1 0 
3 2 4 1 
1 0 0 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=2, c=2, level = 1:
4 3 1 0 
3 2 4 1 
1 4 0 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=3, c=0, level = 1:
4 3 1 0 
3 2 4 1 
1 4 3 2 
0 0 0 0 
-->> SolveSudoku (4x4) - r=3, c=1, level = 1:
4 3 1 0 
3 2 4 1 
1 4 3 2 
2 0 0 0 
-->> SolveSudoku (4x4) - r=3, c=2, level = 1:
4 3 1 0 
3 2 4 1 
1 4 3 2 
2 1 0 0 
-->> SolveSudoku (4x4) - r=3, c=3, level = 1:
4 3 1 0 
3 2 4 1 
1 4 3 2 
2 1 0 0 
No Solution!
#include <stdio.h>
#include <stdbool.h>

#define UNASSIGNED 0

bool aux_SolveSudoku(int n, int array[][n]);
bool SolveSudoku(int n, int array[][n], int row, int col);
bool check(int n, int array[][n], int row, int col, int number);
bool CheckRow(int n, int array[][n], int row, int number);
bool CheckCol(int n, int array[][n], int col, int number);
bool CheckIfFull(int n, int array[][n]);
void printArray(int n, int array[][n]);

int main(void)
{
    int n;
    scanf(" %d", &n);
    int array[n][n];

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
            scanf(" %d", &array[i][j]);
    }

    if (aux_SolveSudoku(n, array) == true)
    {
        printf("Solution:\n");
        printArray(n, array);
    }
    else
        printf("No Solution!\n");

    return 0;
}

bool aux_SolveSudoku(int n, int array[][n])
{
    for (int row = 0; row < n; row++)
    {
        for (int col = 0; col < n; col++)
        {
            if (SolveSudoku(n, array, row, col) && CheckIfFull(n, array))
                return true;
        }
    }
    return false;
}

bool SolveSudoku(int n, int array[][n], int row, int col)
{
    if (array[row][col] != UNASSIGNED)
        return true;
    static int level = 0;

    level++;
    printf("-->> SolveSudoku (%dx%d) - r=%d, c=%d, level = %d:\n", n, n, row, col, level);
    printArray(n, array);

    for (int i = 1; i <= n; i++)
    {
        if (check(n, array, row, col, i))
        {
            array[row][col] = i;

            if (SolveSudoku(n, array, row, col))
            {
                level--;
                return true;
            }

            array[row][col] = UNASSIGNED;
        }
    }
    level--;
    return false;
}

bool check(int n, int array[][n], int row, int col, int number)
{
    return(!CheckRow(n, array, row, number) && !CheckCol(n, array, col, number));
}

bool CheckRow(int n, int array[][n], int row, int number)
{
    for (int col = 0; col < n; col++)
    {
        if (array[row][col] == number)
        {
            return true;
        }
    }
    return false;
}

bool CheckCol(int n, int array[][n], int col, int number)
{
    for (int row = 0; row <  n; row++)
    {
        if (array[row][col] == number)
        {
            return true;
        }
    }
    return false;
}

bool CheckIfFull(int n, int array[][n])
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (array[i][j] == UNASSIGNED)
                return false;
        }
    }
    return true;
}

void printArray(int n, int array[][n])
{
    for (int row = 0; row < n; row++)
    {
        for (int col = 0; col < n; col++)
        {
            printf("%d ", array[row][col]);
        }
        printf("\n");
    }
}
bool SolveSudoku(int n, int array[][n], int row, int col){
    if(array[row][col] != UNASSIGNED)
        return true;

    for(int i=1; i<=n; i++){
        if(check(n, array, row, col, i)){
            array[row][col] = i;

            if(SolveSudoku(n, array, row, col))
                return true;

            array[row][col] = UNASSIGNED;
        }
    }    
    return false;
}
void solve(int r, int c)
{
    if(board[r][c] == 0)
    {
        for(int i = 1; i < 10; i++)
        {
            if (!inRow(i, r) && !inCol(i, c) && !inSqr(i, r, c))
            {
                board[r][c] = i;
                if(r == 8 && c == 8)
                {
                    printBoard();
                    System.exit(0);
                }
                else if(c == 8) solve(r + 1, 0);
                else solve(r, c + 1);
            }
        }
        board[r][c] = 0;
    }
    else if(r == 8 && c == 8)
    {
        printBoard();
        System.exit(0);
    }
    else if(c == 8) 
    {
        solve(r + 1, 0);
    }
    else 
    {
        solve(r, c + 1);
    }
}