2020软件工程作业03
1.Github项目地址:https://github.com/yyp0820/20177577sudoku/blob/master/SRC
2.PSP表格:
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
Planning | 计划 | 60 | 60 |
Estimate | 估计这个任务需要多少时间 | 800 | 1200 |
Development | 开发 | 140 | 140 |
Analysis | 需求分析 (包括学习新技术) | 60 | 80 |
Design Spec | 生成设计文档 | 30 | 30 |
Design Review | 设计复审 | 30 | 30 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 40 | 45 |
Design | 具体设计 | 60 | 80 |
Coding | 具体编码 | 480 | 600 |
Code Review | 代码复审 | 120 | 150 |
Test | 测试(自我测试,修改代码,提交修改) | 90 | 120 |
Reporting | 报告 | 30 | 30 |
Test Repor | 测试报告 | 30 | 30 |
Size Measurement | 计算工作量 | 30 | 60 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 45 | 60 |
合计 | 2045 | 2715 |
3.思路分析:一看到这个题目压根看不懂题目意思,题目要求:
1.程序能生成不重复的数独终局至文件;
2.程序能读取文件内的数独问题,求一个可行解并将结果输出到文件;
要想解决这个问题就得先问度娘数独游戏的规则:数独是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,不重复。数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。———引用自《数独_百度百科》
在了解了题目要求和规则以后,我马上想到的一种算法就是回溯法:对于生成数独终局,我们只要按顺序一个个填数字就好了,每填完一个数字都检查它所在的行,列和宫是否满足数独的规则,若满足则填下一个数字,若不满足则回溯。并且由于题目要求中的第二点只要求一个可行解,因此1、2两个要求感觉实质上是一样的。当然还有一种更简单的算法叫矩阵生成法,可是由于能力有限,学习完回溯脑袋就大了,还是老老实实用回溯吧。
3.设计实现过程:采用了回溯法,思路如下:
设了一个9X9的二维数组a[9][9],然后判断 值k是否可以插入某个点 a[i][j]
①该数组所有横向没有存在过k值
for(n=0;n<9;n++)
if(a[i][n]==k)return 0;
②该数组纵向没有存在过k值
for(m=0;m<9;m++)
if(a[m][j]==k)return 0;
③该点位于的九宫格3X3区间没有存在过k值
xm=(i/3)*3,xn=(j/3)*3;
for(m=xm;m<xm+3;m++)
for(n=xn;n<xn+3;n++)
if(a[m][n]==k)return 0;
然后开始搜索的过程:9X9总共81个格子,就用一个数字n作为标记i,j坐标点的变量(i=n/9; j=n%9;),即:80就相当于最后一个格子 8/9=8,8%9=8
如果n等于80,那么就表示已经遍历到最后一个点了,如果满足条件的话就找到最终解了。
如果n不等于80,表示还要继续往下试,即用不同的k值试探当前i,j点是否可以放下,回归后回溯就ok了。
void SD(int a[9][9],int n)//求解 { int i,j; int b[9][9]; for(i=0;i<9;i++) for(j=0;j<9;j++) b[i][j]=a[i][j]; //用b进行尝试 i=n/9; j=n%9; //行列 if(a[i][j]!=0) //如果该位置固定 (n==80)?print(b):SD(b,n+1); else { int k; //试数 for(k=1;k<=9;k++) if(test(b,i,j,k)) //可以 { b[i][j]=k; n==80?print(b):SD(b,n+1); b[i][j]=0; //回溯 } } }
4.实现结果:
5.性能分析,代码改进:
第一次调试报错C4996,这是VS的版本问题,scanf返回值被忽略,在项目属性添加:_CRT_SECURE_NO_WARNINGS,这样调试结果就没问题了。
对代码进行性能分析,探测CPU的利用率,可以看出外部代码占用最多,达到百分之九十七,其次是_src_common_main和_src_common_main_sesh函数,这两个函数没有可以优化的地方所有没有进行更改。
6.单元测试:
7.实验总结:这次个人项目做的非常坎坷,一大把原因就是对VS和C++都不熟悉,在性能测试和单元测试阶段我的VS出了很多问题,让我整个人心态都不太好了。不过也学习到了回溯法,我之前从来没有想过对一个代码进行优化,也不知道仅仅IO上的改变能对一个程序的性能造成如此大的影响,越发让我感觉自己还需要不断提高,差的实在是远。
自我评分:
作业头 | Github项目地址 | 代码要求经过code quality analysis工具的分析并消除所有警告 | PSP表格估计 | PSP表格实际 | 解题思路描述 | 代码如何组织 | 关键函数画出流程图 | 单元测试的设计 | 找出性能瓶颈 | 改进 | 展示关键代码 | 解释思路与注释说明 | 结合构建之法心路历程和思想 | 总分 |
2 | 1 | 2 | 0.5 | 0.5 | 1 | 0.5 | 0 | 0 | 0.5 | 0 | 0.5 | 0.5 | 0.5 | 9.5 |