【软件工程基础】个人项目报告|数独终局生成及解决
项目简介
[github]链接: https://github.com/kindoms214/Sudoku.
1、项目要求
- 能够生成1-1e6个不一样的数独终局并输出到文件(命令:sudoku.exe -c abc)
- 读取文件中的数独问题,求解并将结果输出到文件(命令:sudoku.exe -s path)
- 附加题要求:为数独游戏生成一个GUI界面,能够生成任意数量的数独题目并依次显示,9*9棋盘上挖空数目30<=n<=60。用户可以在界面上方点击或输入完成数独题目。用户完成数独题目后可以得到反馈,知道自己的题目是否做对。
2、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planing | 计划 | ||
Estimate | 估计这个任务需要多少时间 | ||
Development | 开发 | ||
Analysis | 需求分析(包括学习新技术) | ||
Design Spec | 生成设计文档 | ||
Design Review | 设计复审(和同事审核设计文档) | ||
Coding Standard | 代码规范(为目前的开发制定合适的规范) | ||
Design | 具体设计 | ||
Coding | 具体编码 | ||
Code Review | 代码复审 | ||
Test | 测试(自我测试,修改代码,提交代码) | ||
Reporting | 报告 | ||
Test Report | 测试报告 | ||
Size Measurement | 计算工作量 | ||
Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | ||
合计 |
3、解题思路及过程
拿到题目后感觉难度并不会特别大所以并没有去考虑结队项目。而且之前也比较喜欢玩数独,基础形式的数独也玩了不少,所以感觉题目难度并不会太大,最主要的是明确相应的数独生成及求解算法。至于附加题,因为有认识的同学会使用QT,所以到时候遇到具体问题也不是没有办法解决。
3.1数独终局生成解决过程
- 题目思路
首先,我们应该明确一点的是,9*9数独中的每一行、每一列及每一宫都必须无重复的出现0-9的每一个数字。生成数独终局,很容易想到的是全排列,因为数独中的每一行都是数字0-9的一个排列,因此每一行的数字的排列方式一定是9!中的一种。当然由于题目条件的限制,数独第一行的数字是8!中的一种。但需要注意的是,数独游戏的限制要求每一列及每一宫也不能出现0-9中的重复数字。所以我想到了通过第一行数字平移特定位数来生成其他行数的方法。
最开始映入脑海中的想法是,第二行通过第一行移动一位来产生,第三行通过第一行移动两位来产生……这个想法显然不行,因为它只满足了行和列的要求,并没有满足每一宫中的要求。那么既然每次移动一位不行,那我每三行划分成一组,然后通过三列三列的移动,是否有效?在进行验证之前我先简单的阐述一下具体的过程。方便起见,我们先用数组a[1]-a[9]表示第一行的数。第二行通过第一行移动三位得到,第三行通过第二行移动三位得到,那么第四行呢?因为第四行中没有和第一行的数处于同一宫的可能,只需满足行与列上的关系,所以只需要按照最开始的想法通过第一行移动一位即可!然后4~6行按照1~3行的变换获取。第7行再利用第4行右移一位获得然后同样按照1~3行的变换生成7~9行的变换即可完成整个数独的生成。
可以看到,这样生成的数独矩阵是满足每一行、每一列及每一宫无重复出现a[1]~a[9]中每个数的条件。因此,按照这种生成数独的话,一共能生成8!个(第一行第一位固定为4)有效的数独。但8!=40320<1e6,不及题目要求的数量。但仔细思考后我发现,对于每个数独终局来说,交换2、3行,交换4、5、6行,或者交换7、8、9行的数据便可以生成新的数据终局(不用管具体的数,只需要观察上面的“代号”数组a[1]-a[9]即可)。这样终局生成总数就来到了8!*2*3!*3!=2903040种结果,这也就意味着1e6的条件能够满足。