数独_软件工程基础个人项目

一、Github项目地址

https://github.com/maoshuo1754/sudoku

二、预估时间

预估时间
PSP2.1Personai software process stage预估耗时(分钟)
Planning计划30
Estimate估计这个任务需要多长时间30
Development开发500
Analysis需求分析(包括学习新技术)180

Design Spec

生成设计文档120
Design review设计复审60
Coding Standard代码规范30
Design具体设计120
Coding具体编码120
Code review代码复审120
Test测试(自我测试,修改代码,提交修改)600
Reporting报告300
Test Report测试报告120
Size Measurment计算工作量60

Postmortem&Process

Inprovement Plan

事后总结,并提供过程改进计划180
 合计2600

三、解题思路描述

数独规则:9*9的方格,满足每一行、每一列、每一个3*3宫内的数字均含1-9,不重复。

刚拿到数独问题,因为以前接触过数独,所以对数独有一定的了解,首先我联想到之前做过的N皇后问题,因为都是N*N的格子,所以我想能不能用同样的方法做,于是尝试了用回溯法写这个程序,因为第一个格子的内容是确定的,所以从第二个格子开始,从1到9尝试不冲突的数字,当填完第81个格子之后也就生成一种终局。

有了这个思路之后很快就写完了代码,发现效果也很不错,至于解数独,只要修改一下输入和生成终局的算法就可以了。整个过程比较顺利。

 

四、设计实现过程

4.1 总体流程图

4.2 函数组成

整段代码有四个函数,Input(),Output(),check_num(),TraceBack(),其中Inout和Outout是输入输出函数,不必细讲。其中的Check_num函数是判断9*9方格中的某一位置的数字是否符合要求,TraceBack()则是递归函数,其中用Check_num()函数判断当前方格里的数字是否符合要求,如果符合则判断下一方格,否则尝试下一个数字。递归到第81格代表数独方格已经填完,作为解可以输出。

TrackBack()函数流程图

4.3单元测试用例

sudoku.exe -a

sudoku.exe -c
sudoku.exe -c -1
sudoku.exe -c 20  
sudoku.exe -c abc
sudoku.exe -c 20 abc 

sudoku.exe -s
sudoku.exe -s C:\Users\Joo\Desktop\数独\in.txt
sudoku.exe -s C:\Users\Joo\Desktop\数独\in.txt 20
sudoku.exe -s abc

4.3.2测试结果

五、程序改进

输入为100w时的情况进行测试。

 程序运行了46+s,通过VS的性能分析工具列出各个函数所占用CPU的比例,占用最大的是回溯函数Traceback(),占用了99.71%,其中函数体本身的操作占用了20.16%,调用的check_num()函数占用了42.53%,Output()函数占用了36.64%,所以后面两个函数是优化的重点,Traceback()和check_num()两个函数在后面都有介绍。

改进 通过行交换或列交换可以获得新的数独矩阵

通过资料查询发现,通过行交换或列交换可以获得新的数独矩阵,比如对前三行进行排列组合,一共可以得到6个不同的数独,因为题目中要求第一个数字不变,所以我通过交换4-6行,7-9行,4-6列,7-9列,这样的排列组合,通过回溯生成的一个数独可以生成 6^4=1296个数独矩阵,生成100w个就需要回溯生成100w/1296=772个数独矩阵,这样大大降低了回溯算法所占用的时间。

改进后,程序运行了16.664s,且Output()函数占用了CPU的97.37%,所以程序运行的大部分时间都在输出,大大提高了程序的效率。

 

 

六、代码说明

代码主要部分为Check_num() 和 TraceBack() 两个函数,下面分别说明

6.1 check_num() 函数

int check_num(int i, int j, int num)//检查在第i行第j列填入数字num是否冲突,冲突的话返回0
{
	if (num == 0) 
	{
		return 1;
	}

	for (int k = 0; k < 9; k++) //检查本行 
	{
		if (a[i][k] == num&&k != j&&a[i][k] != 0)
			return 0;
	}

	for (int k = 0; k < 9; k++) //检查本列 
	{
		if (a[k][j] == num&&k != i&&a[k][j] != 0)
			return 0;
	}

	for (int k = i / 3 * 3; k < i / 3 * 3 + 3; k++)//检查所在九宫格 
		for (int l = j / 3 * 3; l < j / 3 * 3 + 3; l++)
		{
			if (a[k][l] == num && !(k == i&&l == j))
				return 0;
		}

	return 1;
}

 

6.2 TraceBack() 函数

前面已经用流程图的形式解释此函数

void TraceBack(int n)          //回溯函数
{
	if (sum > SUM - 1)     //生成终局总数达到目标,结束整个程序,解数独中SUM值为1
	{
		exit(0);
	}

	if (n > 80)            //所有81个方格填完,输出此终局并return    
	{
		sum++;
		Output(a);
		return;
	}

        //n/9为当前方格所在行数,n%9位列数
	if (a[n / 9][n % 9] != 0) //当前方格不为0,代表值固定不能更改,直接进入下一格
	{
		TraceBack(n + 1);
	}
	else
	{
		for (int i = 1; i <= 9; i++)
		{
			int temp = a[n / 9][n % 9];
                        //check_num()不为0代表当前值不冲突,可以进入下一格
			if (check_num(a, n / 9, n % 9, i)) 
			{
				a[n / 9][n % 9] = i;
				TraceBack(n + 1);
			}
			a[n / 9][n % 9] = temp;   //还原当前格
		}
	}
}

七、实际花费时间

 

实际花费时间
PSP2.1Personai software process stage实际耗时(分钟)
Planning计划30
Estimate估计这个任务需要多长时间30
Development开发450
Analysis需求分析(包括学习新技术)180

Design Spec

生成设计文档120
Design review设计复审60
Coding Standard代码规范30
Design具体设计150
Coding具体编码180
Code review代码复审120
Test测试(自我测试,修改代码,提交修改)

270

Reporting报告300
Test Report测试报告120
Size Measurment计算工作量60

Postmortem&Process

Inprovement Plan

事后总结,并提供过程改进计划180
 合计2600

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值