第三次软件工程实践作业
我的GitHub:mmbhwhh
PSP
PSP | 预估耗时(小时) | 实际耗时(小时) |
---|---|---|
计划 | 2 | 3 |
估计这个任务需要多少时间 | 16 | 20 |
开发 | 1 | 2 |
需求分析 (包括学习新技术) | 2 | 2 |
生成设计文档 | 2 | 3 |
设计复审 | 3 | 3 |
具体设计 | 2 | 3 |
具体编码 | 3 | 5 |
代码复审 | 3 | 3 |
测试(自我测试,修改代码,提交修改) | 1 | 2 |
报告 | 2 | 3 |
过程改进计划 | 1 | 2 |
总计 | 22 | 31 |
思考
开始拿到题目的时候,以为是我想象中的数独,就简单的想着只要把每个已经确定的数对它当前所在的行、列、宫格的影响扩散出去,题目又说给的数独都是唯一解的,这更加让我确信用我的思路可以解出来,然后就试了试。
刚开始的思路
大体和第一位交作业的莫多同学一样,就是对数独遍历两次,第一次找到入口(因为题目说测试的数据都是唯一解),找到一个确定的点,然后将它的影响扩散给行、列、宫格,最终就会将整个表格填满。写了很久的代码,却发现我的思路只能填写一部分数据,没玩过数独的我还是太嫩了,后面冷静下来思考一番,如果数独有这么简单还叫什么数独呢,从我的那些错误的数据我知道了,尽管一个数独只有一个解,但是它也不一定可以用逻辑直接确定全部的值,因为我从我错误的代码打出来的错误结果显示,没填的那部分数据的确不能确定,必须要填入数值进去试探,虽然填的数字合法,但是解不出来。这结果让我原地自闭。
第二次想法
经历了上次的教训,索性直接用暴力的办法解这道题。思路就是从第一个格子一直找到最后一个格子,如果找到了空格子,那就给它赋上合法的数值,然后继续找,如果找不到了就出现了两种情况。一是已经填完了,结果出来了,并且它是合法的也就是它的解了;二是,找不到合法的值了,但是它却还是空着的,说明前面赋的值不对,此时再回去改,直到正确为止。代码如下:
check(u,i)函数是检测在u(把宫格的格子编号,从左上角为起始点一直到右下角,例如9宫格就有1、2、3...........80、81的编号)的位置,填入i合不合法
bool check(int u, int t)
{
int x, y;
x = (u - 1) / type + 1;
y = (u - 1) % type + 1;//找到u这个位置的坐标
for (int i = 1; i <= type; i++)
{
if (gg[x][i] == t && i != y) return false;
if (gg[i][y] == t && i != x) return false;
}//判断这个位置填入的数会不会与行和列冲突
if (type == 4 || type == 6 || type == 8 || type == 9)
{
int xs, ys;
int beginx, beginy;//当前坐标所在宫格的左上角坐标,可当做起始坐标
switch (type)//判断宫格的规模
{
case 4:
xs = 2;
ys = 2;
break;
case 6:
xs = 2;
ys = 3;
break;
case 8:
xs = 4;
ys = 2;
break;
case 9:
xs = 3;
ys = 3;
break;
}
int flogx = xs;
int flogy = ys;//flogx和flogy只是待会下面用到的循环次数
beginx = (x - 1) / xs * xs + 1;
beginy = (y - 1) / ys * ys + 1;
for (int i = beginx; flogx > 0; flogx--, i++)
{
for (int j = beginy; flogy > 0; flogy--, j++)
{
if (t == gg[i][j] && (x != i || y != j)) return false;
}
flogy = ys;
}
flogy = xs;
}//判断此位置填入的数会不会与宫格里的冲突
return true;//能走到这里说明填的数合法
}
上面的check函数会在dfs函数中用到,dfs的作用就是搜索
bool dfs(int u)
{
if (u > type*type) return true;//迭代到编号以外,说明前面填的数都是合法的
int x, y;
x = (u - 1) / type + 1;
y = (u - 1) % type + 1;//给它坐标化
if (gg[x][y]) return dfs(u + 1);//如果这个位置有数字,就去下一个点
else {
for (int i = 1; i <= type; i++)
{
if (check(u, i))
{
gg[x][y] = i;
if (dfs(u + 1))return true;
gg[x][y] = 0;
}
}//这个位置还没填入数据,就随便给它一个值,然后再执行下一个点,如果下一个点不可以了就会回来这个点重新赋值
return false;
}
}
测试结果