全网最简易懂c++数独问题解决方法

先上问题:

这个游戏只有一个规则:
将格子填满使得每一行,每一列,和每一个小的九宫格,恰好包含1-9这9个数字

正是由于规则简单而又变化多端,数独一时间风靡全球。
现在,我们希望你能编写一个程序解决数独问题。

输入

输入数据一共9行,每行有9个字符。
输入数据描述了一个待解决的数独,其中,“?”表示数独中的空缺。
我们的输入数据总保证有唯一解。

输出

输出一共9行,每行9个数字,表示你的答案。

样例输入 Copy
5????7??6
?6????5?4
?834?????
???182?4?
??1???9??
?7?369???
?????543?
1?5????9?
7??2????1
样例输出 Copy
514927386
967831524
283456179
659182743
321574968
478369215
892615437
135748692
746293851

要解决数独问题,可以使用回溯算法。回溯算法是一种递归的算法,它通过尝试不同的可能性来搜索解空间,当发现当前路径不可行时,则返回上一步并尝试其他可能性。

具体步骤如下:

  1. 创建一个函数来解决数独问题,函数参数包括数独矩阵和当前待填充的行和列。

  2. 在函数内部,首先判断当前待填充的行和列是否已经超出了数独矩阵的范围。如果超出了,则说明已经找到了数独的解,将数独矩阵输出。

  3. 然后,判断当前位置是否已经有数字。如果有数字,则跳过当前位置,继续递归地调用函数填充下一个位置。

  4. 如果当前位置是空缺(即“?”),则从1到9依次尝试在当前位置填入数字,并进行下一步的递归调用。

  5. 在递归调用中,检查当前填入的数字是否符合数独规则。需要检查当前行、当前列和当前小九宫格是否已经包含了相同的数字。

  6. 如果满足数独规则,则继续递归地调用函数填充下一个位置。

  7. 如果不满足数独规则,则回溯到上一个位置,尝试其他的数字。

  8. 当找到数独的解或者所有可能性都已经尝试完毕时,结束递归。

    目录

    输入

    输出

    样例输入 Copy

    样例输出 Copy


    首先定义了一个 isValid 函数,用于检查在给定位置(行、列)放置特定数字是否满足数独规则。这个函数会检查当前行、当前列和当前小九宫格是否已经包含了相同的数字。接下来定义了 solveSudoku 函数,用于解决数独问题。这个函数使用了递归的方法,通过遍历数独矩阵中的每个空缺位置,在每个空缺位置尝试填入数字并递归调用自身,直到找到解或者所有可能性都尝试完毕。紧随其后是 printSudoku 函数,用于打印数独的解。该函数遍历数独矩阵并将每个位置上的数字打印出来。在 main 函数中,首先声明并初始化一个大小为 9x9 的二维数组 grid,用于存储数独的初始状态。之后通过循环读取数独输入。每次读取一行输入,并将其中的字符转换为数字(0表示空缺),将结果保存到 grid 数组中。调用 solveSudoku 函数来解决数独问题。如果数独有解,则调用 printSudoku 函数打印解;如果数独无解,则输出提示信息。

  9. bool isValid(int grid[9][9], int row, int col, int num)

    这个函数用于检查在给定位置(行、列)放置特定数字是否满足数独规则。它接受以下参数:

    • grid:整个数独矩阵
    • row:当前位置的行索引
    • col:当前位置的列索引
    • num:要尝试放置的数字

    函数首先检查当前行中是否已经存在相同的数字,如果存在则返回 false,否则继续检查当前列和当前小九宫格。如果任何一个位置已经包含了相同的数字,函数都会返回 false,表示这个数字不能放置在当前位置上。如果所有位置均不包含相同的数字,则返回 true,表示当前位置可以放置该数字。

  10. bool solveSudoku(int grid[9][9])

    这个函数用于解决数独问题。它接受一个 9x9 的二维数组 grid,表示数独的初始状态,并尝试填入缺失的数字。函数返回一个布尔值,表示是否找到了解。

    函数使用了递归的方法解决数独问题。它首先遍历数独矩阵中的每个位置,如果该位置是一个空缺(用 0 表示),则尝试将数字 1 到 9 中的每个数字填入当前位置。在尝试填入数字之前,会调用 isValid 函数进行检查,判断是否满足数独规则。如果满足规则,则继续递归调用自身,处理下一个空缺位置。如果在递归调用中找到了解,函数返回 true,否则会回溯到上一级递归,并尝试下一个数字。

    如果所有数字都尝试完毕,仍然没有找到解,则返回 false,表示当前状态无解。

  11. void printSudoku(int grid[9][9])

    这个函数用于打印数独的解。它接受一个 9x9 的二维数组 grid,表示数独的解。

    函数遍历数独矩阵的每个位置,并将每个位置上的数字打印出来。同时,根据需要可以在数字间加入分隔符或换行符以便更好地显示数独的布局。

  12. int main()

    main 函数是程序的入口点。在这里,我们声明并初始化一个大小为 9x9 的二维数组 grid,用于存储数独的初始状态。

    接下来,通过一个循环读取数独的输入。每次读取一行输入,并将其中的字符转换为数字,将结果保存到 grid 数组中。

    最后,调用 solveSudoku 函数来解决数独问题。如果数独有解,则调用 printSudoku 函数打印解;如果数独无解,则输出提示信息。

  13. #include <iostream>
    using namespace std;
    
    bool isValid(int grid[9][9], int row, int col, int num) {
        // 检查行
        for (int c = 0; c < 9; c++) {
            if (grid[row][c] == num) {
                return false;
            }
        }
        
        // 检查列
        for (int r = 0; r < 9; r++) {
            if (grid[r][col] == num) {
                return false;
            }
        }
        
        // 检查小九宫格
        int startRow = row - row % 3;
        int startCol = col - col % 3;
        for (int r = 0; r < 3; r++) {
            for (int c = 0; c < 3; c++) {
                if (grid[startRow + r][startCol + c] == num) {
                    return false;
                }
            }
        }
        
        return true;
    }
    
    bool solveSudoku(int grid[9][9]) {
        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                if (grid[row][col] == 0) {
                    for (int num = 1; num <= 9; num++) {
                        if (isValid(grid, row, col, num)) {
                            grid[row][col] = num;
                            
                            if (solveSudoku(grid)) {
                                return true;
                            }
                            
                            grid[row][col] = 0;
                        }
                    }
                    
                    return false;
                }
            }
        }
        
        return true;
    }
    
    void printSudoku(int grid[9][9]) {
        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                cout << grid[row][col] << " ";
            }
            cout << endl;
        }
    }
    
    int main() {
        int grid[9][9];
        
        // 读取数独输入
        for (int row = 0; row < 9; row++) {
            string line;
            cin >> line;
            for (int col = 0; col < 9; col++) {
                if (line[col] == '?') {
                    grid[row][col] = 0; // 0表示空缺
                } else {
                    grid[row][col] = line[col] - '0';
                }
            }
        }
        
        if (solveSudoku(grid)) {
            printSudoku(grid);
        } else {
            cout << "No solution exists!" << endl;
        }
        
        return 0;
    }
    

    希望这样的详细解释可以帮助你全面理解每个函数的作用和流程。如果还有其他问题,请随时提问。

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

善程序员文

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值