2020软件工程03

 

2020软件工程作业03

 

这个作业属于那个课程https://edu.cnblogs.com/campus/zswxy/software-engineering-2017-1
这个作业的要求在哪里 https://edu.cnblogs.com/campus/zswxy/software-engineering-2017-1/homework/10494
这个作业的目标 https://edu.cnblogs.com/campus/zswxy/software-engineering-2017-1/homework/10494
作业正文 如下
其他参考文献 百度等

 


我的github项目链接:https://github.com/54

  

PSP表格

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

# 解题思路 看完题目要求之后,我就自己动手画了了一个九宫格。在做题目的过程中,我慢慢体会到解题的思路。基本上就是,排查一个空可能填的数,当只剩下一种可能的时候就可以填了。但是有时候可能有两种或者更多的可能值,这就需要我们去试探了。因为题目比较简单,思路也很快就出来了。用正常的搜索+递归,就能把题目要求的唯一解(标准)数独算出来。比较难的就需要我们去试探了。听说有道史上最难的数独,只有最聪明的人才能解出来,希望我的程序可以算出来。 # 源代码 先看一下主函数吧。这个文件输入输出我整整搞了两天,最后发现两个问题。一个是vs2017建立项目的时候,应该选择建立Windows控制台应用程序。还有一个问题就是input.txt和output.txt写成input.txt.txt和output.txt.txt。讲真的,我自闭了,心态被搞崩了。看了好多资料,用了无数的方法都不行。最后可以实现的那一刻,心里舒服了好多。 **主函数** ``` int main(int argc, char** argv) { int i, j; ifstream ifp; ofstream ofp; m = atoi(argv[2]);//宫阶数 n = atoi(argv[4]);//盘面数 choosemn(); ifp.open(argv[6]); if (!ifp.is_open())//判断文件是否成功打开 cout << "文件打开失败" << endl; ofp.open(argv[8]); if (!ofp.is_open()) cout << "文件打开失败" << endl; while (n > 0) { resetmay(); for (i = 0; i < m; i++)//输入数独盘面 { for (j = 0; j < m; j++) { ifp >> a[i][j].num; } } inputsign(); scansign();

	for (i = 0; i < m; i++)//输出解出的数独
	{
		for (j = 0; j < m; j++)
		{
			if (j < (m - 1))
				ofp << a[i][j].num << " ";
			else
				ofp << a[i][j].num;
		}
		ofp << endl;
	}
	ofp << endl;
	n--;
}
return 0;

}

**结构体定义数据**

struct number //每个数的结构体 sa
{
int sign;//定义一个标记,表示这个数还有几种可能的取值
int maybe[9] = { 1,2,3,4,5,6,7,8,9 };//定义num的可能取值
int num;//定义num的确定值
}a[9][9];

### 核心代码
核心代码是两个函数,一个**唯一值函数**,一个**排查函数**。

 **唯一值函数**

void onlyone(int i, int j)//这个函数是把唯一解求出来;
{
for (int k = 0; k < line; k++) //唯一解在maybe里面
{
if (a[i][j].maybe[k] != 0)
{
a[i][j].num = a[i][j].maybe[k];
a[i][j].maybe[k] = 0;
a[i][j].sign = 0;
del(i, j);
break;
}
}
}


**排查函数**

void deletehl(int i, int j)
{
for (int k = 0; k < line; k++)//把同一行的sign减一,把maybe的可能取值变零
{
if (a[i][k].maybe[a[i][j].num - 1] != 0)//如果不等0,说明还没去掉这个可能;
//等0的话,说明前面已经去掉了,sign不用再减一了;
{
a[i][k].maybe[a[i][j].num - 1] = 0;
a[i][k].sign--;
if (a[i][k].sign == 1)
{
onlyone(i, k);
}
}//把同一行的相同可能值删掉

	if (a[k][j].maybe[a[i][j].num - 1] != 0)
	{
		a[k][j].maybe[a[i][j].num - 1] = 0;
		a[k][j].sign--;
		if (a[k][j].sign == 1)
		{
			onlyone(k, j);
		}
	}//把同一列的相同可能值删掉 
}

}

void deletegong(int i, int j)
{
//宫的首地址计算 //x,y;这个宫的首个数的地址为a[x][y] ;
int x, y;
x = (i / gongrow) * gongrow;
y = (j / gongline) * gongline;
for (int gi = 0; gi < gongrow; gi++)
for (int gj = 0; gj < gongline; gj++)//把同一宫的sign减一,把maybe【num】的取值变零
{
if (a[gi + x][gj + y].maybe[a[i][j].num - 1] != 0)
{
a[gi + x][gj + y].maybe[a[i][j].num - 1] = 0;
a[gi + x][gj + y].sign--;
if (a[gi + x][gj + y].sign == 1)
{
onlyone(gi + x, gj + y);
}
}
}
}

唯一值函数就是当一个空的可能性只有一种的时候,就可以填入了。
排查函数就是把同一列或同一行或同一宫的,已存在的值的可能性排除掉。
### 数据测试
下面是5和6宫格的数据测试结果
![](https://img2018.cnblogs.com/blog/1797348/201909/1797348-20190925220600589-545168212.png)
![](https://img2018.cnblogs.com/blog/1797348/201909/1797348-20190925220640289-1100503425.png)
### 性能分析
![](https://img2018.cnblogs.com/blog/1797348/201909/1797348-20190925223552849-1785591570.png)
![](https://img2018.cnblogs.com/blog/1797348/201909/1797348-20190925223640034-1913736679.png)
![](https://img2018.cnblogs.com/blog/1797348/201909/1797348-20190925223659569-995779287.png)


###总结
这次作业花了我很长的时间,但也是收获很多,学习了使用github这个工具,以及编程能力的提高,代码的检查等等。
原文地址:https://www.cnblogs.com/biao0110/p/12594253.html