第二次作业--数独

github地址:https://github.com/ggrcwxh/Soft-work-practice
编程语言 :java
ide:eclipse java oxygen

PSP:

Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
计划 25 10
估计这个任务需要多少时间 15 15
开发 810 1010
· 需求分析 (包括学习新技术) 100 200
· 生成设计文档 20 10
· 具体设计 60 60
· 具体编码 400 500
· 代码复审 30 40
· 测试 200 300
报告 200 300

解题思路:

《编程之美》上看到过,本来看知乎的回答(好像是java要学到什么程度可以工作)买来准备大三寒假拿块白板慢慢刷的,来学校的路上随手翻了一下,奈何c#看不懂,当小说看了。。。回来还换了台笔记本,做实践作业,考驾照,9月8号才开始做题,然后看到编程语言是c/c++/c#的时候我的内心是奔溃的。大一大二上一路划水过来加半年没用过的语言。。非常认真的搜了下如何一日内学会使用c++,答案是。。。不管了用java写不做可执行文件了反正没法用-c调用,要做可执行文件还得生成jar包加exe4j打包,不如直接导入ide,不行的话大不了开学收拾细软跑路去写接口(逃。《编程之美》上提供了两种方法。按字面意思(看不懂c#)我的理解是一种回溯,另一种我也不知道怎么称呼。搜索外加思考了一下,决定先实现第二种方法然后写gui做成游戏。第二种方法是先确定中间的九宫格,然后再交换位置确定其他八个九宫格。这样的话如果没有限定左上角是固定数的话是有9!阶乘个数独,30多万个呐。限定了左上角也有4万多个。然后加上要扣掉好多个格子,怎么算也有几百万种了,够玩了。然后再用回溯实现,因为第一题要求数独数到一百万。至于附加题第二小题,我搜索学习了一下捋了下思路,生成一个九宫格然后随机挖格子,每挖一次格子用dlx算法求解,看看是不是唯一解,不是的话重挖。我觉得以我这么烂的水平单写这个2天的时间打不住了。。先做第一第二题吧,然后看看能不能发现些更简便的方法做第三题。

设计实现:

先写游戏:这个我想法非常简单,1-9随机排序,然后加个二维数组存上面第一个图的顺序,然后按这个顺序把这9个数输出九遍就行了。。。然后加个线程按题目要求扣点空再用swing写个界面,完成。
然后做第一题随机数加递归加走不下去了回溯然后从左往右,从上往下搜下去,一个方法递归加一个方法判断就好,其他多出来方法完全是因为java的io系统对初学者不太友好。我不知道这是不是书上说的深度优先搜索,反正是解出来了。。。
然后第三题,我突然想到一种方法,按上面第二个图这样挖空,挖掉27个空后是唯一解,因为行限制只能是这三个数,列限制这三个数两两不能交换。再随机从不同行不同列没挖掉的数中挖三个空。目测是唯一解。。开学后有时间学下dlx算法解出来看看。三十多万种数独加上随机从60多个格子里砍掉三个格子,这样也有几百万个唯一解的数独了吧,至于数独太容易解,胎教数独,你值得拥有。

关键代码分析说明:

第一题的递归具体思路就和设计实现上的差不多用Vector存可供选择的数,然后生成随机数作为索引用Vector里的数给数独某个单元格赋值,如果可以赋值则修改line和col的值继续递归,如果不行的话就返回上一层,我自己认为比较难(因为整了我好久)就是某个位置走不通了返回到上一个位置的时候,得把上一个位置原本的数从备选项中排除出去,一开始写的就死在这上了,直接删了重写了后来。
		boolean CrSduku(int line ,int col)//构造一个数独
		{
			Vector<Integer> current = new Vector<Integer>(0,1);
			
			for(int i=1;i<10;i++)
			{
				current.add(i);
			}
			if(line==0&col==0)
			{
				current.remove(8);
				col++;
			}
			
			while(current.size()!=0)
			{
				Random r1 = new Random();
				int r=Math.abs(r1.nextInt())%current.size();//生成一个小于Vector当前组件数量的一个随机数作为Vector的index;
				suduku[line][col]=current.get(r);
				current.remove((Integer)current.get(r));
				if(Suitable(line,col)==false)
				{
					continue;
				}
				if(line==8&col==8)
				{
					return true;//一个数独构建完成
				}
				if(col==8)
				{
					//一行填满下一行
					col=0;
					line++;
				}
				else
				{
					col++;
				}
				if(CrSduku(line,col)==true)
				{
					return true;
				}
				
			}
			suduku[line][col] = 0;//如果找不到合适的数返回上一层递归,即本位置的上一个位置
			return false;
			
			
		}

测试运行:

数独游戏,功能应该实现了吧,玩了半个小时暂时还没有发现bug,至于界面,Java写界面好尴尬,要不再导个substance包?(逃。

第一题1000000测试了一遍好像可以。

这个。。。都不知道是不是唯一解。

性能测试图:

用的JProfiler,莫名奇妙char[]的调用率很高,整个程序都没有使用过char,看来String只不过是基于char封装一些方法。老师要的看函数(方法)使用情况查了下应该要用tptp这个插件吧,至于为什么不使用tptp,37g。。。用先生成中间的九宫格然后改变其他九宫格应该是最快的,然后其他九宫格的排序方式应该不止《编程之美》上一种,这种方法用于实现游戏,就没写了;至于回溯那个算法想了好久,之前把用array的改成Vector,因为Vector可以直接移除组件,这样遍历的次数应该会比array少吧。改进已经新开一个随笔:http://www.cnblogs.com/wkmocr/p/7503149.html

遇到的困难及解决方法:

困难描述:io系统没人性,递归出现bug测试到腿发软。
做过哪些尝试: 《java编程思想》+《java官方入门》+《java核心技术卷一》关于io的部分看了一遍,疯狂debug。
是否解决: 是
有何收获: 现在满脑子都是字节流,字符流

第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
1 600 600 22 22 和javaio死磕了一边

执行力,泛泛而谈:

执行力就是完成需求的成度吧,泛泛而谈是谈自己的认识吧,实例:比如携程最近从.net转Java的程序员?。

收获:

先给上个随笔留言的老师道个歉,没回复,暑假跑到中朝边境去了,2m网速一栋楼用,手机信号还不好。。。实在不想上网,上一篇随笔还是跑到网吧去写的。。。另外《构建之法》刚刚到写完就看。收获最大就是梳理了一遍javaio吧,然后对回溯,和Vector有了更深的了解吧。

posted on 2017-09-10 18:14  ggrc  阅读(336)  评论(2编辑  收藏  举报

导航