软工实践第三次作业_个人编程作业
0.Gtihub项目地址
1.PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 60 |
Estimate | 估计这个任务需要多少时间 | 60 | 60 |
Development | 开发 | 1560 | 1680 |
Analysis | 需求分析 (包括学习新技术) | 360 | 300 |
Design Spec | 生成设计文档 | 60 | 60 |
Design Review | 设计复审 | 60 | 60 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 60 | 60 |
Design | 具体设计 | 120 | 180 |
Coding | 具体编码 | 240 | 300 |
Code Review | 代码复审 | 120 | 180 |
Test | 测试(自我测试,修改代码,提交修改) | 120 | 120 |
Reporting | 报告 | 180 | 180 |
Test Repor | 测试报告 | 60 | 60 |
Size Measurement | 计算工作量 | 60 | 60 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 120 | 120 |
合计 | 1620 | 1740 |
行动效率比想象中还要低...
2.解题思路
题目到手先是去仔细端详了下数独的定义,标准数独是9*9并附带九宫格限制的矩阵,而题目要求从三宫格数独到九宫格数独均要能够求解。
不同宫格之间形虽有异,但质却相同,数独矩阵的成立均建立在合乎数独规则的情况下,因此选好做法处理好类型识别后求出各个宫格的结果应该并不算难。首先想到的是根据行、列、宫的限制条件进行深搜,逐格判断各个数字在相应位置的合法性,但转念一想这样做在搜索触底回溯时可能要退后很多步再用另一个数字继续搜索,不禁感觉耗时耗力。
大一大二时的怠惰导致了我编程基础的薄弱,在网上查阅了众多数独解法后开始自闭,觉得自己在短时间内无法理解这些晦涩难懂的算法后还是选择用一开始想到的笨笨的解法。
因为对命令行参数的使用和定义一窍不通,我选择了参考他人的解法,以此为基础根据题目需求完善输入输出和不同宫格的求解。
https://blog.csdn.net/qq_31558353/article/details/50615760
3.设计过程
3.0 类和主要函数的设计
一开始想分为输入和解决&输出两个类,但因为没能处理好变量环境只定义了一个类Read。
- Read::read_judge
- 处理控制台读入数据,检验读入的几个参数,目前仅是简单的几种情况的检验。
- 正确的输入格式为 Sudoku.exe -m 9 -n 2 -i input.txt -o output.txt
-
Read::input & Read::ouput
- 使用ifstream文件流读取文件存入类内数组,供后续解答使用。
- 得到所有数独矩阵的解后再一并输出到指定文件夹
-
Read::dfs & Read::check
- 深搜求解数独盘面
- 求解过程中的合法性验证
3.1 主程序流程图
4.关键代码
Read::dfs
temp [0] [ ] [ ]表示已从文件读入的第一个数独矩阵,dimen表示数独的类型值。
void Read::DFS(int n) //深搜求解,其实就是递归啦。从(0,0)位置开始逐列遍历后再逐行遍历。
{ //n表示格子的位置,0 <= n <dimen*dimen
if (n == dimen * dimen)
{ //走完所有格子后标记成功并退出
sign = true;
return;
}
if (temp[count][n / dimen][n % dimen] != 0) //该位置已有数,跳过
{
DFS(n + 1);
}
else
{
for (int i = 1; i <= dimen; i++) //对1 -> dimen逐个填入验证
{
if (Check(n, i) == true)
{
temp[count][n / dimen][n % dimen] = i; //数i在该位置合法,填入
DFS(n + 1); //继续下一个位置的验证
if (sign == true)
{
return;
}
temp[count][n / dimen][n % dimen] = 0;//后续无解并返回当前位置,将原先赋值的i清空,尝试下一个数并继续往后搜索
}
}
}
}
Read::check
bool Read::Check(int n, int key)
{
int col = n % dimen;//列坐标
int row = n / dimen;//行坐标
for (int i = 0; i < dimen; i++)
{
if (temp[count][row][i] == key)//检查行正确性
return false;
}
for (int i = 0; i < dimen; i++)
{
if (temp[count][i][col] == key)//检查列正确性
return false;
}
if (dimen == 3 || dimen == 5 || dimen == 7)
{
//3,5,7宫格只需判断行与列的合法性
return true;
}
switch (dimen)
{ //根据所给宫格定义取出当前所在宫格的左上坐标,并遍历宫内格子
case 4: {
int x = n / 4 / 2 * 2;
int y = n % 4 / 2 * 2;
for (int i = x; i < x + 2; i++)
{
for (int j = y; j < y + 2; j++)
{
if (temp[count][i][j] == key)
return false;
}
}break;
}
case 6: {
int x = n / 6 / 2 * 2;
int y = n % 6 / 3 * 3;
for (int i = x; i < x + 2; i++)
{
for (int j = y; j < y + 3; j++)
{
if (temp[count][i][j] == key)
return false;
}
}break;
}
case 8: {
int x = n / 8 / 4 * 4;
int y = n % 8 / 2 * 2;
for (int i = x; i < x + 4; i++)
{
for (int j = y; j < y + 2; j++)
{
if (temp[count][i][j] == key)
return false;
}
}break;
}
case 9: {
int x = n / 9 / 3 * 3;
int y = n % 9 / 3 * 3;
for (int i = x; i < x + 3; i++)
{
for (int j = y; j < y + 3; j++)
{
if (temp[count][i][j] == key)
return false;
}
}break;
}
}
return true;
}
5.样例测试
六宫格
七宫格
八宫格
九宫格
因三宫格与五宫格同七宫格解法相同,四宫格与九宫格相似,便不再依次po出。
6.性能分析
找到传参启动的性能分析页面,然后,白给了😭
也不知道是程序还是使用过程不恰当的问题.....抓紧时间完善吧
7.心路历程和收获
对于没有系统完成项目的经验的我来说这次作业难在相关工具的使用和理解上。百度是我的好老师,秉承着不懂就查的想法也算是有所收获,但对于有效信息的分辨和筛选还是经验不足。这次作业算是摸了,性能检测实在没辙,自己已经想不到解决的出路。
收获的话算是巩固了下对文件的写读理解,刚好配合最近一起进行的linux课程学习文件流读写。工具使用的话算是初窥VS门径,github的常用操作已经完全理解了。