c - c中的数独求解器崩溃
问题描述
我试图找出我的代码有什么问题,该代码应该解决一个 9x9 数独,当我使用 Wikipedia 中的数独示例运行它时会崩溃。
我也尝试过使用递归,但对它不是很熟悉,所以它也不起作用。
findunassignedlocation
1
如果数独中仍有 0 且0
不再有 0 ,则返回。isSafe
1
如果所有行、列和 3x3 网格不包含数字,则返回,0
否则返回。
如果问题可能出在其他功能之一,请告诉我,我将发送代码。忽略depth
变量。
下面是我的代码:
/* Returns an int which indicates whether if the sudoku has any
more empty entries (which shows as a 0) */
int FindUnassignedLocation(int grid[9][9]) {
for (int row = 0; row < 9; row++)
for (int col = 0; col < 9; col++)
if (grid[row][col] == 0)
return 1;
return 0;
}
/* Returns an int which indicates whether an assigned entry
in the specified row matches the given number. */
int UsedInRow(int grid[9][9], int row, int num) {
for (int col = 0; col < 9; col++)
if (grid[row][col] == num)
return 1;
return 0;
}
/* Returns an int which indicates whether an assigned entry
in the specified column matches the given number. */
int UsedInCol(int grid[9][9], int col, int num) {
for (int row = 0; row < 9; row++)
if (grid[row][col] == num)
return 1;
return 0;
}
/* Returns an int which indicates whether an assigned entry
within the specified 3x3 box matches the given number. */
int UsedInBox(int grid[9][9], int boxStartRow, int boxStartCol, int num) {
for (int row = 0; row < 3; row++)
for (int col = 0; col < 3; col++)
if (grid[row + boxStartRow][col + boxStartCol] == num)
return 1;
return 0;
}
/* Returns an int which indicates whether it will be legal to assign
num to the given row,col location. */
int isSafe(int grid[9][9], int row, int col, int num) {
/* Check if 'num' is not already placed in current row,
current column and current 3x3 box */
if (!UsedInRow(grid, row, num) &&
!UsedInCol(grid, col, num) &&
!UsedInBox(grid, row - row % 3, col - col % 3, num) &&
grid[row][col] == 0) {
return 1;
} else {
return 0;
}
}
void solve_sudoku(int sudoku[9][9]) {
int row = 0;
int col = 0;
if (FindUnassignedLocation(sudoku) == 0) { //if sudoku is completely filled
return;
}
for (int num = 1; num <= 9; num++) {
if (isSafe(sudoku, row, col, num) == 1) {
sudoku[row][col] = num;
solve_sudoku(sudoku, depth);
sudoku[row][col] = 0;
}
}
}
解决方案
一种简单的(但由于对称/旋转不是最有效的)方法是尝试所有可能性,尝试将数字 1 到 9 放在连续位置 (0,0 0,1 .. 0,8 1,0 。 .. ) 递归,每次可以将一个数字放在 8,8 上,这是一个解决方案
您的代码几乎不需要更改,只是为了删除无用的FindUnassignedLocation并添加递归
如果我将 9 替换为 SZ 也能够搜索尺寸 3、6 或 9,并且我添加解决方案的绘制代码可以是:
#include <stdio.h>
// 3, 6 or 9
#define SZ 9
/* Returns an int which indicates whether an assigned entry
in the specified row matches the given number. */
int UsedInRow(int grid[][SZ], int row, int num)
{
for (int col = 0; col < SZ; col++)
if (grid[row][col] == num)
return 1;
return 0;
}
/* Returns an int which indicates whether an assigned entry
in the specified column matches the given number. */
int UsedInCol(int grid[][SZ], int col, int num)
{
for (int row = 0; row < SZ; row++)
if (grid[row][col] == num)
return 1;
return 0;
}
/* Returns an int which indicates whether an assigned entry
within the specified 3x3 box matches the given number. */
int UsedInBox(int grid[][SZ], int boxStartRow, int boxStartCol, int num) {
for (int row = 0; row < 3; row++)
for (int col = 0; col < 3; col++)
if (grid[row + boxStartRow][col + boxStartCol] == num)
return 1;
return 0;
}
/* Returns an int which indicates whether it will be legal to assign
num to the given row,col location. */
int isSafe(int grid[][SZ], int row, int col, int num)
{
/* Check if 'num' is not already placed in current row,
current column and current 3x3 box */
return (!UsedInRow(grid, row, num) &&
!UsedInCol(grid, col, num) &&
!UsedInBox(grid, row - row % 3, col - col % 3, num));
}
/* print a solution */
void draw(int sudoku[][SZ])
{
for (int row = 0; row != SZ; ++row) {
for (int col = 0; col != SZ; ++col)
printf("%d", sudoku[row][col]);
putchar('\n');
}
putchar('\n');
}
void solve_sudoku(int sudoku[][SZ], int row, int col)
{
for (int num = 1; num <= 9; num++) { //loop through numbers 1 to SZ
if (isSafe(sudoku, row, col, num) == 1) { //the number is safe
sudoku[row][col] = num;
if ((col + 1) == SZ) {
if ((row + 1) == SZ) {
// done
draw(sudoku);
}
else
solve_sudoku(sudoku, row + 1, 0);
}
else
solve_sudoku(sudoku, row, col + 1);
sudoku[row][col] = 0;
}
}
}
int main()
{
int sudoku[SZ][SZ] = {0};
solve_sudoku(sudoku, 0, 0);
}
为 SZ 3 找到的第一个解决方案(362880 个可能的解决方案):
123
456
789
123
456
798
123
456
879
123
456
897
123
456
978
123
456
987
123
457
689
为 SZ 6 找到的第一个解决方案:
123456
456789
789123
214365
365897
897214
123456
456789
789123
214365
365897
897241
123456
456789
789123
214365
365897
978214
123456
456789
789123
214365
365897
978241
123456
456789
789123
214365
365978
897214
123456
456789
789123
214365
365978
897241
为 SZ 9 找到的第一个解决方案
123456789
456789123
789123456
214365897
365897214
897214365
531642978
642978531
978531642
123456789
456789123
789123456
214365897
365897214
897214365
531642978
648971532
972538641
123456789
456789123
789123456
214365897
365897214
897214365
531642978
672938541
948571632
123456789
456789123
789123456
214365897
365897214
897214365
531642978
678931542
942578631
123456789
456789123
789123456
214365897
365897214
897214365
531642978
942578631
678931542
推荐阅读
- c# - 查找 xpath 不起作用的元素 - Selenium C#
- android - Android/ios Appname 来自 packagename/appid
- openxml-powertools - 是否可以使用 Open Xml Power Tools 将 word 文档(包含形状,AltChunk)转换为 HTML
- security - 如何使用 Ethereum solidity remix IDE 和 Ganache 模拟车载自组织网络 (VANET) 区块链?
- pine-script - 突出每小时蜡烛
- bash - bash shell 内置“读取”没有按预期工作
- php - getimagesize 返回图像分辨率的大值
- compiler-construction - 如何使用 libclang 将 AST 作为字符串?
- python - 在链表中递归插入节点,给定位置和值
- authentication - 使用 azure ad 登录后,着陆页不符合要求