实现一个能够生成数独终局并且能求解数独问题的控制台程序。
- GitHub地址: https://github.com/Berskerd/Sudoku.git
- 时间估计
PSP 2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 10 | 10 |
Estimate | 估计这个任务需要多少时间 | 10 | 10 |
Development | 开发 | 900 | 880 |
Analysis | 需求分析(包括学习新技术) | 40 | 35 |
Design Spec | 生成设计文档 | 20 | 10 |
Design Review | 设计复审(和同事审核设计文档) | 0 | 0 |
Coding Standard | 代码规范(为目前的开发制定合适的规范) | 10 | 10 |
Design | 具体设计 | 10 | 10 |
Coding | 具体编码 | 500 | 500 |
Code Review | 代码复审 | 30 | 35 |
Test | 测试(自我修改,修改代码,提交修改) | 300 | 300 |
Reporting | 报告 | 90 | 95 |
Test Report | 测试报告 | 60 | 60 |
Size Measurement | 计算工作量 | 5 | 5 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 30 | 30 |
合计 | 1133 | 1990 |
- 解题思路
项目要求能够实现解已经存在的数独以及生成相应数目的数独,而且是命令行程序。我使用的语言是Java。
解答数独的办法很直观想到的就是回溯,相当于暴力搜索,按顺序填写每个空格,对每个空格,可填入的数组为1-9,对1-9这9个数字,进行剪枝,剪枝函数的算法就是数独的规则,在同一行,同一列,以及所在的33小方格内,1-9的数字只能出现一次。如果遇到一个空格没有可填写的数字,就回到一直往前,回到之前的空格,修改前面填过的空格的值,在进行寻找,直到到达填完最后一个空格。因为数独题目可能存在多个解,所以我在找到一个解之后直接终止了解数独函数。
生成数独也可以使用解数独的思路,因为生成数独可以看成解一个完全空白的数独题目,也就是说对99总共81个空格进行回溯。这是一种解题的办法,但是很遗憾,这样所画的时间太过漫长,而且,这样生成的数组是全都一样的,为了生成多个不同的数组,需要引入随机数。
所以,我针对数组的第一行使用了全随机数,因为项目的要求限制了第一个数字为(4+7)%9+1=3。所以随机数的选取需要八个。生成的算法也很简单,从第一行的第二个数字开始,每次都随机生成一个随机数,判断剪枝函数(因为只需要生成第一行,所以剪枝函数得到简化,只需要判断行内是否满足即可)。
生成第一行之后,对剩下的空格进行回溯,生成所需的数独题目。
-设计实现过程
在这个项目中,我设计了三个类,输入类,输出类,和主类。
输入类负责从命令行获取命令,分析命令的类型,并处理相应的参数,判断输入是否有误。
输出类负责创建一个“sudoku.txt”,并进行写入操作,创建文件成功的话输出“win”,生成失败输出“false”,如果写入失败输出“写入失败”。
主类负责相关创建数独和解数独操作。会先根据输入的命令选择之后的操作,如果输入-c,执行创建操作,否则,执行解数独操作。
在创建数独的操作中,获取创建数独的数目,对所需的各个变量进行初始化操作,调用创建数独的方法,生成相应数量的数独。
解决数独的操作,首先获取输入文件的绝对路径,获取该路径中文件的内容,用字符串保存起来。针对字符串中的每个字符进行判断,分离出其中的数独题目,存储在int类型的数组中。初始化相应的字符串,调用数独解决方法,并调用输出类中的创建文件方法,将数独的解输出到.txt文件中。
利用这种办法,生成的数独是否相同完全取决于第一行的随机是否相同,所以,理论上最多可以生成最多的不同数独为8!个,即40320个。数目并不够。观察数独的特征发现,调换数独中的第一和第二行,可以生成两个不同的数独。针对第三到第五行,可以执行第三行和第四行交换,第四行和第五行交换,第三行和第五行交换三种,加上最初生成的,一共四种。第六到第九行同理,有四种不同的数独。总和到一起,在利用原有方法生成一个数独的同时,可以通过交换产生另外八个不同的数独,所以每执行一次生成函数,可以产生9个不同的数独,故理论上一共可以产生40320*9个数独,即362880个数独。基本达到了老师的要求。同时提高了生成的效率,降低了生成所花去的时间。
-性能分析表
因为是使用eclipse编写的Java程序,所以使用Java VisualVM插件来查看程序的性能。下面记录了生