软件工程个人项目数独工程(三)
这篇博客我就是来讲讲这个解数独的功能。
首先说说思想吧,当我有一道数独题目,那么我想解,按照正常人的思路,我就是正常人,我想我肯定是在这个空所有能填的数字里面我就一个一个的试,先往下填,等到有一个空我填不了了,那么我就把我最近一次填的空给改了,说白了,我用了回溯。
先给大家看一下我的代码实现
void jieti(int row, int line, ofstream &file4)//再调用此函数之前必须先找到题目矩阵中,第一个空,并用这个点的参数调用这个函数和
{//默认输入的所有的题目都是有解的;
int numth = line * 9 + row;//我们的起始是第几个空
int biaozhi = numth;
int flag = 0;
int templ2[9] = { 0 };
int sys = check2(row, line, templ2);
if (sys == 0)
return;
while (sys--)
{
for (int i = 0; i < 9; i++)
{
if (templ2[i] == 0)
{
templ2[i] = 1;
question[line][row] = i + 1;
break;
}
}
for (int i = 0; i < 81 - biaozhi; i++)
//虽然我们在解决问题的时候,我们把这个数组看作是一维的,但是我们的数据还是二维数据。二位数据的检查函数相对来说简单一些
{
numth = biaozhi + i;
int transline = numth / 9;
int transrow = numth % 9;
if (question[transline][transrow] == 0)
{
jieti(transrow, transline, file4);
flag = 1;
break;
}
}
if (Qnum != 0)
{
return;
}
if (flag == 0)
{
Print2(question, file4);
Qnum++;
return;
}
}
question[line][row] = 0;
}
这个程序很简单吧!用到了check2 和print2这两个函数,check2的功能和前面介绍的check函数功能是一样的:
int check2(int row, int line, int *templ2)
{
int blocklinenum, blockrownum;
blocklinenum = line / 3;//块行数
blockrownum = row / 3;//块列数
//int innerlinenum = line % 3;
//int innerrownum = row % 3;
int startaddline = blocklinenum * 3;//块的起始行地址
int startaddrow = blockrownum * 3;//块的起始列地址
int i = 0; int j = 0; int sum = 0;
sum = startaddline * 9 + startaddrow;
for (i = 0; i <= 20; i++)
{
int tempsum = sum + i;
if (question[tempsum / 9][startaddrow + (tempsum % 3)] != 0)
templ2[question[tempsum / 9][startaddrow + tempsum % 3] - 1] = 1;
}
for (i = 0; i < 9; i++)
{
if (question[line][i] != 0)
{
templ2[question[line][i] - 1] = 1;
}
if (question[i][row] != 0)
templ2[question[i][row] - 1] = 1;
}
for (i = 0; i < 9; i++)
{
if (templ2[i] == 0)
j++;
}
return j;//j代表了我们会有多少的候选值
}
print2是非常简单的,这里就不给大家看了,因为这个就是解题,不要求速度的问题,所以输出你不管是用文件流还是用fputc其实都是ok的