GitHub地址:https://github.com/WYH2/031702206
PSP表格
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 15 | 45 |
Estimate | 估计这个任务需要多少时间 | 30 | 40 |
Development | 开发 | 40 | 30 |
Analysis | 需求分析 (包括学习新技术) | 60 | 70 |
Design Spec | 生成设计文档 | 10 | 5 |
Design Review | 设计复审 | 5 | 10 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
Design | 具体设计 | 15 | 45 |
Coding | 具体编码 | 120 | 180 |
Code Review | 代码复审 | 120 | 180 |
Test | 测试(自我测试,修改代码,提交修改) | 240 | 480 |
Reporting | 报告 | 30 | 20 |
Test Repor | 测试报告 | 10 | 25 |
Size Measurement | 计算工作量 | 20 | 15 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 30 |
合计 | 755 | 1185 |
解题
1.思考
(小小吐槽一下,看到题目那么长的那一刻心态崩了)
看到数独宫格题目的时候,由于我平常还挺喜欢玩数独游戏的,我思考了一下我平常手动解题的方法:
先通过已知数字(通常是哪个数字多)确定部分(可能只有几个),然后就是在每一个空格排除掉所有不可能的数字剩下的数字一个个尝试。
但是由于我的编程能力实在太差,所以我只能通过查询网络上的解数独代码从九宫扩展到所有(三到九太难了)。
2.设计
①函数Check:判断该空格待填数字是否符合(行/列/宫)
②函数Work:递归回溯尝试每一个数字的填入
③定义全局变量:数组shudu[][]存放待填数独,s为宫格阶数,t为待填宫格数,block数值判断是否存在宫,block_line,block_column为宫存在情况下的行与列的格数
代码解析
1.函数Check:
//num为待检查的数字,now_line和now_column为待检查的坐标
bool Check(int num, int now_line, int now_column)
{
for (int i = 0;i < s;++i)//检查与待检查的坐标同行或同列的位置
{
if (shudu[now_line][i] == num || shudu[i][now_column] == num)
return false;
}
if (block != 0)
{
int i, j;
for (i = now_line / block_line * block_line;i < now_line / block_line * block_line + block_line;i++)//检查与待检查的坐标同宫的位置
{
for (j = now_column / block_column * block_column;j < now_column / block_column * block_column + block_column;j++)
{
if (shudu[i][j] == num)
return false;
}
}
}
return true;//通过所有检查,返回true
}
2.函数Work:
//Work函数定义为bool,如果数独有解则返回true,无解则返回false
bool Work(int now_line, int now_column)
{
if (now_line == s)
{
return true;//如果将数独解完,返回true
}
else
{
int next_line, next_column;
next_column = now_column + 1;//下一个坐标
next_line = (next_column == s ? now_line + 1 : now_line);
next_column = (next_column == s ? 0 : next_column);
if (shudu[now_line][now_column] != 0)//如果当前坐标有数字,则对下一个坐标进行工作
{
if (Work(next_line, next_column)) return true;//如果数独最终有解,则不断向前返回true
}
else
{
for (int i = 1;i <= s;i++)
{
if (Check(i, now_line, now_column))
{
shudu[now_line][now_column] = i;//如果i值合法,则对下一个坐标进行工作
if (Work(next_line, next_column)) return true;
}
}
shudu[now_line][now_column] = 0;//回溯操作
return false;//如果i的值为1-9均不合法,则返回上一层继续循环
}
}
}
3.数据输入与输出
void Input()
{
for (int i = 0;i < s;++i)
{
for (int j = 0;j < s;++j)
{
cin >> shudu[i][j];
}
}
}
void Output()
{
for (int i = 0;i < s;++i)
{
for (int j = 0;j < s;++j)
{
cout << shudu[i][j];
if (j != s - 1) cout << " ";
}
cout << endl;
}
if (t)
cout << endl;
}
4.主函数
#include "stdafx.h"
//#include "stdafx.cpp"
int shudu[9][9], s, t, block = 0, block_line = 0, block_column = 0;
int main(int argc, char *argv[])
{
s = atoi(argv[2]);
t = atoi(argv[4]);
freopen(argv[6], "r", stdin);
freopen(argv[8], "w", stdout);
while (t--)
{
Input();
switch (s)//根据阶数设置宫
{
case 4:block = 1, block_line = 2, block_column = 2;break;
case 6:block = 1, block_line = 2, block_column = 3;break;
case 8:block = 1, block_line = 4, block_column = 2;break;
case 9:block = 1, block_line = 3, block_column = 3;break;
default:break;
}
if (Work(0, 0)) Output();//如果有解,则调用输出函数
else cout << "No Answer." << endl;//如果无解,则输出“No Answer.”
}
//system("pause");
return 0;
}
Code Quality Analysis检测
注:要求我们要消除所有错误与警告,但抱歉的是这个警告我是真的不会改……
Studio Profiling Tools检测
注:九宫格情况下(虽然是真看不懂这是啥)
数据测试
总结与心路历程
当看到这个题目的时候觉得很可怕,虽然数独常玩,但是真正把它转化成代码对我来说真的是有点难度,整个作业过程充满不可言喻的艰辛:
首先是文件的输入与输出,之前为数不多的打代码历程中的测试我都是用手动输入测试数据,在整体函数完成后我接近30分钟都用在学习这个方面
其次是对于vs2017这个软件的使用很不熟练,Code Quality Analysis和Studio Profiling Tools都是临时现学的,不知道具体用途,而且之前写代码从来没有把头文件,函数声明,函数体和主函数分开过,所以我每写一个函数没有习惯做测试,每次的Debug都要从第一句语句开始,时间耗费很多,而且到后面会变得很烦躁
最后是我觉得我在正式编码之前做的准备工作还是不够充分,导致编码过程有时候不能很顺利进行(没有写注释的习惯这次让我尝到很多苦头),每一个函数体所调用的部分上下不连贯
虽然从发布作业开始每天晚上都是对着电脑看代码,编码,测试等,天天对着电脑发愁,但是当成功之后心里还是很开心的,有种自己这么多天的努力没有白费;我觉得我还有很多需要学习的地方,希望在之后的编程作业中能够更加熟练
(感谢我可爱的小舍友每天晚上的陪伴,很多东西都是她教我的)