软工实践2019第三次作业
1. 【Github项目地址】
2. 【PSP表】
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
Planning | 计划 | 30 | 40 |
Estimate | 估计这个任务需要多少时间 | 10 | 5 |
Development | 开发 | 130 | 120 |
Analysis | 需求分析 (包括学习新技术) | 120 | 130 |
Design Spec | 生成设计文档 | 90 | 80 |
Design Review | 设计复审 | 60 | 50 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 60 | 50 |
Design | 具体设计 | 180 | 200 |
Coding | 具体编码 | 180 | 210 |
Code Review | 代码复审 | 60 | 30 |
Test 测试 | (自我测试,修改代码,提交修改) | 60 | 90 |
Reporting | 报告 | 30 | 40 |
Test Repor | 测试报告 | 30 | 20 |
Size Measurement | 计算工作量 | 20 | 10 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 160 | 180 |
合计 | 1220 | 1255 |
3.【 解题思路描述】:借鉴一下人为解数独的过程,把它用代码实现。
最贴近的便是:
- 先遍历输入数据,找出所有为0的可填区域。
- 在按一定顺序(可以直接按行遍历整个盘面)标记所有可填区域的可填数字(它所在行所在列及所在宫格已填数字标记为0,可填则标记为1),并按从少到多入队列。
从最少可填数字开始填写,并更新所在行、列及宫格的可填区域的可填数字,直到最后可填区域都填完则返回输出解。
由此看来,此思路适合1只有一解的情况。
4. 【设计的实现过程】:由于本人不太会写类(太菜了,编程没学进去,还是舍友教我怎么写的这段面向过程程序),所以写了3个函数实现,分别是标记可填数字,递归处理求解,输出函数。单元测试没做,而且代码没考虑宫,所以只能解决没有宫的3、5、7阶(有bug……不知道怎么调试了...3阶的不知道有没有)仅有一解(多解也只输出一解)数独,而且输入得严格按照作业要求,没有设置容错性分析。
5. 【改进性能】本次作业我写的(应该是舍友和我)代码写完测试后就没优化了,所以性能改进并没有去做。我是按行列顺序遍历深搜的,因为发现按可填数目最少优先求解太麻烦了,不知道怎么实现。
6. 【代码说明】
- 定义全局变量。
int m, n, ans[9][9];//m-宫格阶级(3~9的整数);n-待解答盘面数目;ans-存放解的数组
bool solved[10];//标记是否得到解
int B = 0;//第几盘
fstream fr, fw;//定义输入输出对象
- 标记(x,y)格子可填数字——x,y从0到m-1取值
/*标记当前格子可填数字*/
void mark_avai(int x, int y, int(*arr)[9], int *q)
{
int i(0);
while (i < m + 1)q[i++] = 1;//q数组初始化为1,表示1~m为可填数字
for (i = 0; i < m; ++i)
{
q[arr[x][i]] = 0;//遍历当前格子所在列,并标记q[列的值]=0,表示当前格子无法填该值
q[arr[i][y]] = 0;//遍历当前格子所在行,并标记q[行的值]=0,表示当前格子无法填该值
}
}
- 定义输出函数。
/*输出函数,方便处理时输出,u为阶数*/
void fileout(int(*arr)[9], int u)
{
for (int i = 0; i < u; ++i)
{
for (int j = 0; j < u; ++j)
fw << arr[i][j] << " ";//输出一行的值并用空格隔开
fw << endl;//换行
}
fw << endl;//输出完一个盘面的解后换行
}
- 深搜计算求解。
/*通过递归,求解数独函数,u为阶数*/
void deal(int(*arr)[9], int u, int x, int y)
{
if (y == u)
{
y = 0;
++x;
}//如果列号等于阶数则处理下一行
if (arr[x][y] != 0) //如果当前格子数值不为0
{
if (x == u - 1 && y = u - 1) //最后一个格子
{
fileout(arr, m);
return;
}//处理完后便退出
else
{
deal(arr, u, x, y + 1);
} //continue
}
int mark[10]; //存放函数mark_avai中q数组的值
int record = arr[x][y]; //记录传入数组的值
mark_avai(x, y, arr, mark); //调用函数,获取当前格子(x,y)可填数字
for (int k = 1; k <= u; ++k)
{
if (mark[k] == 0)continue; //如果当前值k不可填则进行k+1判断
arr[x][y] = k; //mark[k]=1,说明当前格子(x,y)可以为k
if (x == u - 1 && y == u - 1) //为最后一个格子
fileout(arr, m), solved[B] = true;//将解输出到文件
else deal(arr, u, x, y + 1); //非最后一个格子则继续处理下一个格子
if (solved[B])return; //如果获得解则退出函数
}
arr[x][y] = record;//还原传入数组的值
}
- 命令行处理。
(太菜了,查了这么久只知道这样子处理)
int main(int argc,char *argv[])
{
m = atoi(argv[2]);
n = atoi(argv[4]);
fr.open(argv[6], ios::in); //读入输入文件
fw.open(argv[8], ios::out); //打印输出文件
......
}
7. 【构建之法学习心得】
哎,这么久过去了,书只是浏览了一半左右,并没有认真阅读,直到博客说认真阅读前三章才知道自己已经忘记了这本的具体内容,现在看这本书也宛如第一次看一样,没有丝毫印象。本书最大的特色就是举例了许多对话还告诉读者某个知识点的作用;还有就是语言朴素易理解。大概只记得书中提了代码规范,还好笔者一直都是那样码代码的(虽然没写过多少代码);还有就是结对编程。要说心路历程和收获还是等在用心读读再谈吧。整体上看,本书讲的是如何构建一个·软件及软件开发流程及软件工程理论、技术。差不多就这样子了吧......Bye......下次再见。
PS: