基于C语言的9*9数独生成器
题目要求如下图所示:
我们采用的思路是首先生成一个完整的9*9数独,然后再随机挖空,这样就形成了一个数独局面。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int sudo[9][9], hole[9][9];
bool set(int x, int y, int val)
{
if (sudo[y][x] != 0)
return false;
int x0, y0;
for (x0=0; x0<9; x0++)
{
if (sudo[y][x0] == val)
return false;
}
for (y0=0; y0<9; y0++)
{
if (sudo[y0][x] == val)
return false;
}
for (y0=y/3*3; y0<y/3*3+3; y0++)
{
for(x0=x/3*3; x0<x/3*3+3; x0++)
{
if (sudo[y0][x0] == val)
return false;
}
}
sudo[y][x] = val;
return true;
}
void reset(int x, int y)
{
sudo[y][x] = 0;
}
void initXOrd(int* xOrd)
{
int i, k, tmp;
for (i=0; i<9; i++)
{
xOrd[i] = i;
}
for (i=0; i<9; i++)
{
k = rand() % 9;
tmp = xOrd[k];
xOrd[k] = xOrd[i];
xOrd[i] = tmp;
}
}
bool fillFrom(int y, int val)
{
int xOrd[9];
initXOrd(xOrd);
for (int i=0; i<9; i++)
{
int x = xOrd[i];
if (set(x, y, val))
{
if (y == 8)
{
if (val == 9 || fillFrom(0, val+1))
return true;
}
else
{
if (fillFrom(y+1, val))
return true;
}
reset(x, y);
}
}
return false;
}
void digHole(int holeCnt)
{
int idx[81];
int i, k;
for (i=0; i<81; i++)
{
hole[i / 9][i % 9] = 0;
idx[i] = i;
}
for (i=0; i<holeCnt; i++)
{
k = rand() % 81;
int tmp = idx[k];
idx[k] = idx[i];
idx[i] = tmp;
}
for (i=0; i<holeCnt; i++)
{
hole[idx[i] / 9][idx[i] % 9] = 1;
}
}
void printSudo()
{
for (int y=0; y<9; y++)
{
if(y%3==0)
printf("-------------------------\n| ");
else
printf("| ");
for (int x=0; x<9; x++)
{
if(hole[y][x] == 0)
printf("%d ",sudo[y][x]);
else
printf(" ");
if(x%3==2)
printf("| ");
else
printf("");
}
printf("\n");
}
printf("-------------------------\n");
}
int main(int argc, char* argv[])
{
int n,m;
printf("填空数目M=(X+1)*10,请输入难度等级X 1~3:\n");
scanf("%d",&n);
m=(n+1)*10;
srand((unsigned)time(NULL));
while (!fillFrom(0, 1)) ;
digHole(m);
printSudo();
return 0;
}
运行结果如下图所示:
空缺数是对应难度+1的十倍,比如难度2是空缺30个数
整体思路:
1.在我们的思路中,我们先要生成一个完整的数独数组sudo[9][9],然后再随机挖洞,空出指定数目的空,形成hole[9][9],这就是我们生成的数独游戏。
2.用回溯法进行填数,保证没有重复项,满足数独要求。
从算法而言,整体是一个回溯算法:
1)初始化数据结构。
2)设置long_row进入第一行,设置一个随机开始列xl和y。
3)如果没有到达最后一行,则继续搜索。
4)从当前搜索列y开始,查找可放置的列位置,找到则放置在该位置(并更新y),并转入下一行的搜索。
5)如果没有找到,则回溯到上一行。
6)全部数字放置完毕后,结束循环。