高级软件工程第二次作业

1.Github地址 xinz

2.解题思路:

    一开始拿到这道题的时候,对数独的概念不是那么清晰。通过题目中百度百科的概念,即被概括成满足以下三个条件的数字范围为1-9的棋盘:(1)每一行不能有重复的数字(2)每一列不能有重复的数字(3)9乘9的大数独盘被划分成9个3乘3的小九宫格,在每个小九宫格内不能有重复数字
    按照人脑填数独的思维我们很容易想到“枚举”的方法,即从填第2个数开始递归填写观察是否满足三个条件,依次往下填写输出一个结果棋盘后进行“回溯”。所以这种“暴力的”程序还是比较简单易懂的,通过百度也了解到其他算法,比如交换行列、用随机数生成等等,但都不如枚举来的直接易懂。
    •从第二个格子开始,根据数独需要满足的三个条件从1-9枚举填数字,并同时标记该格子内哪些数字试过了
    •对剩下的格子进行递归操作
    •输出一个结果棋盘后将记录该数字是否存在的数组复原,为下一次试数做准备,进行回溯,重复上述操作
    •直到满足所需棋盘个数,结束
    途径:百度 + 自己思考 + 同学帮忙

3.设计实现过程

3.1流程图:

3.2设计思路:

    对输入的格式进行处理,使其输入格式为“sudoku.exe -c 生成数独个数”,封装在input_check函数中
    输出在outfile函数中,当输出所需个数的数独棋盘后结束
    枚举试数字的方法(回溯)在sudoku函数中 

4.代码说明

int input_check(int argc, char *argv[])
{
	if (argc != 3)
	{
		cout << "invaild input" << endl;
		return -1;
	}
	if (argc == 3 && strcmp(argv[1], "-c") != 0)
	{
		cout << "please input -c" << endl;
		return -1;//如果输入第二个参数不是-c 不输出
	}
	if (atoi(argv[2]) == 0)
	{
		cout << "please enter a value greater than 0" << endl;
		return -1;//如果输入第三个参数不是数字 不输出
	}
	return atoi(argv[2]);
}
//用递归生成数独,nrow表示当前行,ncol表示当前列,表示当前正在处理第nrow行第ncol列的格子。
void shudu(int nrow, int ncol, ofstream &savefile)
{
	//计算该格子在哪个九宫格中
	int nowbox = ((nrow - 1) / 3) * 3 + ((ncol - 1) / 3 + 1);
	//对该格子进行1-9的数字尝试,如果nownum==num则说明棋盘已经够了,就不用再进行下去了,循环退出
	for (int i = 1; i <= 9 && nownum<num; i++)
	{
		//如果数值i在该行该列没有出现过,则进行下一步操作
		if (row[nrow][ran_num[i]] == 0 && column[ncol][ran_num[i]] == 0 && box[nowbox][ran_num[i]] == 0)//判定数值i在该行该列该九宫格有没有出现过
		{
			result[nrow][ncol] = ran_num[i];//把数值i填写入最终棋盘
			row[nrow][ran_num[i]] = column[ncol][ran_num[i]] = box[nowbox][ran_num[i]] = 1;//记录下i这个值在该行该列和该九宫格出现了
			//如果这个格子是最后一个格子了,说明已经找到一个数独棋盘
			if (nrow == 9 && ncol == 9)
			{
				nownum++;//已找到的数独棋盘数量+1
				if (nownum == num) outfile(savefile, true);//这个是最后一个棋盘
				else outfile(savefile, false);//这不是最后的棋盘
			}
			//如果这个格子不是最后一个格子,则对下一个格子进行枚举
			else
			{
				if (ncol == 9) shudu(nrow + 1, 1, savefile);//如果这个格子是该行最后一个格子,则换行
				else shudu(nrow, ncol + 1, savefile);//如果这个格子不是该行最后一个格子,则处理该行下一个格子
			}
			row[nrow][ran_num[i]] = column[ncol][ran_num[i]] = box[nowbox][ran_num[i]] = 0;//递归完后复原,为下一个数字的尝试做准备
		}
	}
}

//把当前的数独棋盘输出到文件,savefile为输出文件流,islast表示当前输出的棋盘是否为最后一个棋盘
void outfile(ofstream &savefile, bool islast)
{
	string temp = "";//用来临时保存需要输出的文字
	for (int i = 1; i <= 9; i++)
	{
		for (int j = 1; j <= 9; j++)
		{
			if (j != 1) temp += " ";//每个数字之间需要一个空格
			temp += result[i][j] + '0';//把每个数字转换成字符
		}
		temp += "\r\n";//输出完一行需要换行
	}
	if (!islast) temp += "\r\n";//如果这个不是最后一个棋盘,棋盘间需要再次换行。
	savefile << temp;//把文字输入到文件中
}

5.测试运行


6.效能分析

n=1000时

7.PSP

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

8.心得体会

这是第一次尝试使用Github工具,以及在markdown的排版上也花了一定时间。从拿到题目百度到后期自己思考、请教同学,也花了很多时间。希望以后的项目自己可以越做越顺利!

posted @ 2017-10-09 17:29  林逗号  阅读(168)  评论(3编辑  收藏  举报