软件工程实践第二次作业

作业链接

1.github链接

2.PSP

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

3.解题思路描述。即刚开始拿到题目后,如何思考,如何找资料的心路历程。


(刚开始拿到题目之后)

看到这个题目的时候,内心是非常拒绝的,一开始看到了数独,有点茫然,对于数独的了解并不大深,通过了解,原来就是九宫格里的每行每列要有1-9的数字,并且不重复,每个宫里也是如此,没能想到合适的方法,就开始了漫漫找资料的历程。一开始搜索的关键字就是“随机生成数独”,利用深度优先遍历的方式,然后通过判断每个点是否正确摆放生成数独,对于这个方法的理解有些困难,然后继续找看看有没有其他的方法。首先随机数法对于本次的题目来说肯定是不大合适的,数字庞大效率低下,后面又找到了回溯法和置换法两种方法,觉得回溯法这个方法比较好理解,于是就选择了使用这个方法。

回溯法

先设置一个全为0的九宫格,然后从第一个为0的格子开始填入随机数,并判断是否满足数独的要求(即每行每列没宫不可有重复数字),继续向下查找为0格子填入,如果没有可选数,进行回溯,换掉前面的数字,继续执行,以此类推,知道81个格子全不为零的时候,就生成了一个数独。下面是具体代码

4.设计实现过程

分为四个函数:

5.代码说明。

rightplace函数:

bool sudokutest::rightplace(int g, int h)//检测九宫格里的每个数字是否符合数独要求
{
	int row, col;
	row = g / 9;
	col = g % 9;
	int i, j;

	for (i = 0; i < 9; i++)	//对该数字所在的行查找是否有相同的数字
	{
		if (sudoku[row][i] == h)
			return false;
	}
	for (i = 0; i < 9; i++)	//对该数字所在的行查找是否有相同的数字
	{
		if (sudoku[i][col] == h)
			return false;
	}

	int a, b;
	a = row / 3;
	b = col / 3;

	for (i = a * 3; i < a * 3 + 3; i++)	//在每一个宫里判断是否有相同的数字出现
	{
		for (j = b * 3; j < b * 3 + 3; j++)
		{
			if (sudoku[i][j] == h)
				return false;
		}
	}

	return true;

}

put函数:

void sudokutest::put(int n)
{
	int row, col;
	row = n / 9;
	col = n % 9;
	int i;
	if (n == 81)//达到81,说明九宫格已经被填满
	{
		pd = true;
		return;
	}
	if (sudoku[row][col] != 0)//找到没有被填的格子
	{
		put(n + 1);
	}
	else
	{
		if (n % 9 == 0)//每一行将数组随机调换
			random_shuffle(&(a[0]), &(a[9]));
		for (i = 0; i < 9; i++)
		{

			if (rightplace(n, a[i]))
			{
				sudoku[row][col] = a[i];
				put(n + 1);
				if (pd)
					return;
				sudoku[row][col] = 0;

			}
		}

	}

}

main函数主要:

int main(int argc, char *argv[])//实现可以从cmd输入sudoku.exe -c 1000格式
{
	int i, j, temp = 0;
	int k = 0, num = 0;
	int p = 0;
	stringstream stream;
	string na,ne;
	int n;
	if (argc!=3)
	{
		cout << "ERROR!!!more or less sentences" << endl;
		return 0;
}
	else
	{
		ne = argv[1];
		if (ne == "-c")
		{
			na = argv[2];
			int l = na.length();
			for (int m = 0; m < l; m++)//判断输入的字符串是不是纯数字
			{
				if (na[m] <= 57 && na[m] >= 48)//数字0-9的ascii码为48-57,若发现数字,p就加一
				{
					p++;
				}
			}
			if (p != l)//如果最后的p与字符串长度不相同,就说明输入的字符串不是纯数字
			{
				cout << "please enter an integer" << endl;
				return 0;
			}
			stream << na;//将字符串转换成数字
			stream >> n;
			stream.clear();
			freopen("./sudoku.txt", "w", stdout);
			while (n--)
			{
				sudokutest s;
				s.first();
				pd = false;
				s.put(0);
				s.print();
			}
		}
		else
		{
			cout << "Your input format is wrong!!!" << endl;
		}
	}
}
最主要的就是这三个代码,put函数使用回溯方法进行数字的放入,right place用来判断每行每列每宫是否有重复,是否符合数独的规定。因为测试要使用cmd,一开始不知道要使用argc ,argv[]这种方法,不能实现sudoku.exe -c 1000这样语句的实现。由于会出现-c abc或者-c 12r这样的错误语句,故需要判定输入的字符串是否为纯数字。

6.测试运行。

cmd输入测试:

输出结果:

7.效能分析

直接用该代码进行性能测试,应该是不行的,就很奇怪

后面觉得应该是main函数的问题,就把它改成了直接输入的形式,去掉了argc,argv[]方法进行测试,测试的数量为1000

从中可以看到print函数占用的最大,一开始我是使用cout进行输出的,之前听说过进行大量输出的时候,printf好像效率会高一点,于是我就把输出改成printd

emmmm,就快了三秒,然后就继续看看还有什么更高效的输出方式,搜到了putchar方法

从时间量上来看,putchar的时间还比printf多了一点点,一脸茫然。不知道还有什么其他的可以优化的方法了。


发现同样的一段代码,在同学的电脑上测试,和在自己的电脑上测试,时间差了几乎一半,我使用的是vs2015,同学的是vs2017,不知道有没有和版本有关。


关于单元测试,看了一些教程试了好多次,但一直都会有报错,所以只能暂时搁置了,以后会继续琢磨琢磨。


在性能分析上,相较于其他同学的,时间耗费还是很长的,效率还是不高,希望在今后的学习过程中能将自己的代码能力进一步加强。本次作业通过查找资料,也学习到了很多新的知识,懂得了怎么查看代码的性能,总体来说,还是很有收获的。


posted on 2017-09-12 17:57  reset-  阅读(194)  评论(0编辑  收藏  举报