软件工程第三次作业

Github项目地址

https://github.com/kiyo-me/031702302


PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 60 45
Estimate 估计这个任务需要多少时间 60 45
Development 开发 500 1175
Analysis 需求分析 (包括学习新技术) 50 400
Design Spec 生成设计文档 30 45
Design Review 设计复审 15 45
Coding Standard 代码规范 (为目前的开发制定合适的规范) 15 45
Design 具体设计 140 100
Coding 具体编码 200 300
Code Review 代码复审 30 60
Test 测试(自我测试,修改代码,提交修改) 30 180
Reporting 报告 90 180
Test Repor 测试报告 45 90
Size Measurement 计算工作量 15 30
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 30 60
合计 650 1300

思路描述

  • 题目的第一个PART,<命令行参数>以及<用文件实现输入输出>。以往写代码使用的都是int main(void),如今却要使用int main(int argc,char *argv[])。同样的,除了c/c++实践考试时,老师直接给出的文件输入输出命令让大家复制粘贴外,我也再没有接触过文件输入输出了。所以,学习资料如下:
    ·https://blog.csdn.net/u014106566/article/details/84141718 [argc atgv]
    ·https://blog.csdn.net/bichenggui/article/details/4600153 [输入输出]
  • 其实一开始看到题目,我只想完成最简单的三宫格的任务(毕竟深刻认知自己的水平……)。但很悲伤的是,在测试的时候发现,我想的简单的方法并不适用于解开所有类型的三宫格。于是,只能学习了。
  • 在查询的过程中发现,基本上解开数独题都是通过深度搜索和回溯法来完成的。也因此,定下了最后代码的基调也是以此来完成。

实现过程&&代码展示

  • 我的代码里有两个主要函数,即实现主要功能的函数int fill(int m,int finished)和 int test_only(int m,int I,int j,int test)

  • 利用fill(int m,int finished)函数进行深度搜索(从a[ 1][ 1]开始,a[ 1][ 2],……,a[ 1][ m],a[ 2][ 1],…,a[ m][ m];从左到右,从上到下),并定义一个全局变量flag作为标志位是否所有的搜索都能完成并正确填入,flag的变化则是以finished(完成的空格数 第一次调用时设置为0)是否达到全部空格数(m*m)为依据。而关于正确填入的判断,则必须提到test_only(int m,int i,int j,int test)函数。该函数用于判断能够填入的可能性有哪些(通过分析 行,列,小宫 来完成)。如果很不凑巧,利用深度搜索填入的某个值在后续发现不正确时,函数则必须返回上一步,并将错填的地方清0,并再次开始搜索(即回溯)。
    [其实原本花了挺多时间画了个流程图的,不过感觉画的不是很好……希望我的语言表述能够解释清楚思想]
    [补充:画的不太好的流程图一张]:

  • 关于test_only(int m,int i,int j,int test)函数,因为题目要求的宫格类型不同,如3 5 7是不需要判断小宫的,可归做一类,而剩余的却因为划分的方式不同需要逐一划出小宫,于是我采用了余数的方法来的得出当前在的小宫的位置,并加以运算获得该从何处开始何处停止的信息。

  • 另外,还设置了一个函数delete_all(int m),用于一个数独盘完成解答输出后清除数据,为下一个数独做准备。

  • 代码的独到之处:我个人认为,我的函数test_only()使用余数这点来指明小宫格的具体位置以及运算出其循环判断时需要的范围,这一部分我觉得虽然可能并不是那么的简洁,但应该是相当易懂了吧。

int fill(int m,int finished)
{
	int all=m*m; //need to fill
	if(finished>=all)
	{
		flag=1;
		return 0; //all successed
	}
	
	int i,j;
	i=finished/m+1;
	j=finished%m+1; //a[1][1],a[1][2]…a[m][m]
	
	int x;
	if(a[i][j]==0)
	{
		for(x=1;x<=m;x++)
		{
			if(test_only(m,i,j,x)==1)
			{
				a[i][j]=x;
				fill(m,finished+1); //continue
				
				if(flag==1)	return 0;
				
				a[i][j]=0; //unsuccessed,so restart
			}
		}
	}
	else
	{
		fill(m,finished+1); //continue
	}
	
	return 1;
}
int test_only(int m,int i,int j,int test)
{
	int x,y;
	
	y=j; //test col
	for(x=1;x<=m;x++)
	{
		if(a[x][y]==test) return 0;
	}
	
	x=i; //test rol
	for(y=1;y<=m;y++)
	{
		if(a[x][y]==test) return 0;
	}
	
	if(m!=3&&m!=5&&m!=7) //test every cube
	{
		int p,q,r,s; //p=cube_up q=cube_left +r,s==range
		if(m==4)
		{
			if(i%2==0) p=i-1;
			else p=i;
			if(j%2==0) q=j-1;
			else q=j;
			r=s=1;
		}
		else if(m==6)
		{
			if(i%2==0) p=i-1;
			else p=i;
			if(j%3==0) q=j-2;
			else if(j%3==2) q=j-1;
			else q=j;
			r=1;
			s=2;
		}
		else if(m==8)
		{
			if(i%4==0) p=i-3;
			else if(i%4==3) p=i-2;
			else if(i%4==2) p=i-1;
			else p=i;
			if(j%2==0) q=j-1;
			else q=j;
			r=3;
			s=1;
		}
		else if(m==9)
		{
			if(i%3==0) p=i-2;
			else if(i%3==2) p=i-1;
			else p=i;
			if(j%3==0) q=j-2;
			else if(j%3==2) q=j-1;
			else q=j;
			r=s=2;
		}
		for(x=p;x<=p+r;x++)
			for(y=q;y<=q+s;y++)
			{
				if(a[x][y]==test) return 0;
			}
	}
	
	return 1;
}
void delete_all(int m) //for next loop
{
	int i,j;
	for(i=1;i<=m;i++)
		for(j=1;j<=m;j++)
			a[i][j]=0;
}

性能分析

单元测试

Sudoku.exe -m 3 -n 5 -i input.txt -o output.txt

Sudoku.exe -m 4 -n 2 -i input.txt -o output.txt

Sudoku.exe -m 5 -n 2 -i input.txt -o output.txt

Sudoku.exe -m 6 -n 2 -i input.txt -o output.txt

Sudoku.exe -m 7 -n 2 -i input.txt -o output.txt

Sudoku.exe -m 8 -n 2 -i input.txt -o output.txt

Sudoku.exe -m 9 -n 2 -i input.txt -o output.txt


改进

一开始编译的时候其实是有提醒一个小警告的,如图:

后来发现是fill()忘记在最后设置一个返回值了,于是设置后,再次编译:

因为题目有对错误报告有一定要求,一开始我的代码即使是无解的情况也会原样地将原本输入的数据再输出一次,考虑到无解应该报告,于是设置了

if(flag==0) f<<"Error: No answer!"<<endl;

效果如图:


心路历程与收获

啊……其实我的脑袋写到这里时,已经很混乱了(作为一只小菜鸟的我,真的好累哦T^T),可能有些人会觉得难以置信吧,不过确实在整个过程中花了很多的时间,我觉得PSP表格虽然记录了一定的时间,但是还是有其他琐碎的时间难以记录呢,以及非常焦虑的心态(还有每天上课都好困哦,其他课程的东西也有点被搁置了……搞完这些一会得接着赶别的了……)。我想,对于知识而言,想要一口吃成个大胖子,实在是不大可能(不过对于吃饭而言,多吃一口,真的可能会变胖)。[对不起,一看到心路两个字就不由自主打出这些感慨了]
正文如下

其实应该还是有收获的吧。毕竟以前只知道玩别人创造的数独游戏,自己硬想着答案,却没想过能够利用计算机来完成这些。第一次试着用visual studio,用文件输入输出,用参数传递指令,用性能分析器……等真的把代码写出来,看到输出的时候也是有一点小开心的(毕竟完成了一部分啊)。还是感谢一下科技的发展,好多知识都是通过搜索学到的,真的查了好多。也要承认还有很多的很多的不足,比如性能分析器用的并不好,单元测试也没有写出代码来,还有不知道怎么样才能把多解之类的情况也考虑好……在写代码的时候,也收获了非常宝贵的经验:在下次循环前一定要先把数据清0!!!(我真的在这个地方改了好久啊……在灵光一现的瞬间,真的好气)总的来说,还是继续努力,继续学习吧。

posted on 2019-09-25 16:21  _kiyo  阅读(203)  评论(5编辑  收藏  举报