第二次作业--数独
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有了更深的了解吧。