1.Github项目地址 :
https://github.com/DFHG10/031702429
2.PSP表格
PSP是卡耐基梅隆大学(CMU)的专家们针对软件工程师所提出的一套模型:Personal Software Process (PSP, 个人开发流程,或称个体软件过程)。
PSP2.1 | Personal Software Process Stages | 预估耗时(小时) | 实际耗时(小时) |
---|---|---|---|
Planning | 计划 | 1h | 0.5h |
Estimate | 估计这个任务需要多少时间 | 28h | 26h |
Development | 开发 | 4h | 2h |
Analysis | 需求分析 (包括学习新技术) | 4.5h | 5h |
Design Spec | 生成设计文档 | 2h | 2h |
Design Review | 设计复审 | 2h | 1h |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 1h | 0.5h |
Design | 具体设计 | 2h | 1h |
Coding | 具体编码 | 6h | 8h |
Code Review | 代码复审 | 1.5h | 1h |
Test | 测试(自我测试,修改代码,提交修改) | 0.5h | 1h |
Reporting | 报告 | 1.5h | 2h |
Test Repor | 测试报告 | 0.5h | 0.5h |
Size Measurement | 计算工作量 | 0.5h | 0.5h |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 1h | 1h |
合计 | 28h | 26h |
3.思路描述:
作业刚发布的时候,看到是数独的题,就想到之前做过的八皇后问题,感觉是很类似的,是通过深搜回溯求解,我就想着这题应该是差不多的。由于之前没怎么做过数独,特意去网站上做了几个数独。做了一圈,发现有很多的做法,网络上提供了三链数法,侯选数法,频率法多种方法。最后思来想去,还是决定用常规方法,也就是回溯(其他方法试过,不过没有成功。。。,留下泪水/(ㄒoㄒ)/~~)。然后去网络上学习vs项目生成,文件管理等等各个没用过的知识。
4.实现过程:
深搜回溯:我们首先将数独中空缺的部分记录下来,然后依次判断1-9在各个位置上是否能填入,如果能的话则将其填入,进行下一个空缺位置的填入,如果某一个位置所有数字都不能继续填入,那么将本位置还原,回溯到上一层,将上一层所填入的数字清0,重复上述过程,直到所有位置都填入成功,生成数独的一个解。这次是说不考虑多解,所以我是解出数独的一个解就退出求解函数,进行输出。这部分有两个函数,一个判断合法性,一个进行深搜回溯的操作。
文件的输入输出:查找资料之后,决定用c的文件处理进行文件的读写。
错误整理:这部分也不知道会有什么错误,与同学交流之后,想着可以是命令行参数错误,就写了一个判断的函数,判断输入的参数是否错误,这个有待改进。
5.改进思路:
6.代码说明:
定义全局变量:
int board[10][10];//定义数独二维数组// int num, x;//定义数独阶数x,盘面数num;
检测合法性函数:检测数字是否能否放在某个格子中
bool Check(int check_number, int check_now_row, int check_now_column, int check_block_row, int check_block_column) Check函数用于判断行、列、和宫格的合法性(如果有宫格的话) check_number:当前待判断数字 int check_now_row:待判断格子行坐标 int check_now_column:待判断格子列坐标 int check_block_row:如果有宫格,为所在宫格左上角第一格行坐标 int check_block_column:如果有宫格,为所在宫格左上角第一格行坐标
行列判断:
for (int i = 0;i <= x;i++)//检查与待检查的坐标同行或同列的位置 { if (board[check_no_row][i] == check_number || board[i][check_now_column] == check_number) return false; }
此外,有对四,六,八,九宫格进行宫格判断,这里举个九宫格的例子:
if (x == 9) { check_block_row = (check_now_row / 3) * 3; check_block_column = (check_now_column / 3) * 3; for (int i = 0;i <= 2;i++)//检查与待检查的坐标同3*3方格的位置 { for (int j = 0;j <= 2;j++) { if (board[check_block_row + i][check_block_column + j] == check_number) return false; } } }
深搜回溯:
对每个格子进行判断是否有数字,即判断board[now_row][now_column]是否为0;
从第一个为0(即无数字)的格子开始操作,尝试填入数字1~x(x为阶数),并进行合法性分析,调用Check函数;
通过Check函数判断填入的数字是否合法,如果合法,则对下一个空格进行同样的操作;
如果从数字1到数字x均不合法,则说明上一个数填写出错,进行回溯退后上一个数,并将正在操作的格子的数字还原为0;
数独求解完成,则完成。
bool Work(int now_row, int now_column) { if (now_row == x) { return true;//如果将数独解完,返回true } else { int next_row, next_column; int block_row = 0, block_column = 0; next_column = now_column + 1; next_row = (next_column >= x ? now_row + 1 : now_row);//如果最后一列,换行 next_column = (next_column >= x ? 0 : next_column);//如果最后一行,列置为0 if (board[now_row][now_column] != 0)//如果当前坐标有数字,则对下一个坐标进行工作 { if (Work(next_row, next_column)) return true;//如果数独最终有解,则不断向前返回true } else { for (int i = 1;i <= x;i++) { if (Check(i, now_row, now_column, block_row, block_column)) { board[now_row][now_column] = i;//如果i值合法,则对下一个坐标进行工作 if (Work(next_row, next_column)) return true; } } board[now_row][now_column] = 0;//回溯操作 return false;//如果i的值为1-x均不合法,则返回上一层继续循环 } return 0; } }
命令行判断函数:
int canshu(int argc)//判断命令行参数是否有误 { if (argc != 9) { cout << "参数个数出错!"; return 1; } if (x<3 || x>9 || num<0 ) { cout << "数字出错!"; return 1; } return 0; }
命令行参数:
主函数main可以接收两个参数
int main(int argc, char *argv[])
其中: argc:代表启动程序时,命令行参数个数。C/C++语言规定,可执行程序程序本身的文件名也算一个命令行参数。因此,argc的值至少是1.
argv:是一个指针数组,里面每一个元素都是一个char* 类型的指针,该指针指向一个字符串,即指向命令行参数。如argv[0]指向第一个命令行参数,也就是可执行文件名。argv[1]指向第二个命令行参数……
本题中argv[2],argv[4],argv[6],argv[8]分别对应m,n,输入文件名,输出文件名。注意,我们接受到的参数都是字符型,需要进行转换。
x = atoi(argv[2]); num = atoi(argv[4]);
然后是文件的读入和写出,在这里其实还好一些,看了书,之后就差不多了解了,这部分有一个问题就是文件使用方式,我先用的“w”,发现只有一个输出,
在这里我用了两个FILE变量,用fopen打开input文件,fscanf读取数据。然后用fopen打开output文件,fprintf输出数据到output,在这里我是输入一个盘面后,立马进行解答的操作,然后输出到output,然后重置数组,不知道会不会出问题,自己做的时候是行的。
FILE* fp1; FILE* fp2; fp1 = fopen("input.txt", "r");//只读打开文件 fp2 = fopen("output.txt", "a");// 追加打开文件 fclose(fp2);//关闭文件,防止数据丢失 fclose(fp1//关闭文件,防止数据丢失
7.心得体会:
总结一下,这次的作业过程中,学习到了很多,Visual Studio 项目的创建,.h文件和.cpp文件的关联,Github建立库和文件的上传,VS的C4715警告的解决办法(不是所有控件都返回路径)/(ㄒoㄒ)/~~(这个处理了好久),还是学到了一些东西,但是花的时间也很多。。。继续努力吧,上次的学习计划也在慢慢步入正轨,加油。