Sudoku
2018 年秋季学期《软件工程基础》课程个人项目作业
数独终局生成与求解程序,运行于 Windows 平台,使用 C++ 开发。
Github 项目地址 :https://github.com/lytning98/sudoku
一、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 10 | 5 |
- Esitimate | 估计任务时间 | 10 | 5 |
Development | 开发 | 1,065 | 1,170 |
- Analysis | 需求分析 | 45 | 30 |
- Design Spec | 生成设计文档 | 40 | 40 |
- Design Review | 设计复审 | 20 | 10 |
- Coding Standard | 代码规范 | 20 | 20 |
- Design | 具体设计 | 180 | 200 |
- Coding | 具体编码 | 600 | 750 |
- Code Review | 代码复审 | 60 | 40 |
- Test | 测试(自我测试、修改代码、提交修改) | 100 | 80 |
Reporting | 报告 | 240 | 400 |
- Test Report | 测试报告 | 30 | 20 |
- Size Measurement | 计算工作量 | 20 | 25 |
- Postmortem & Process Improvement Plan | 事后总结并提出过程改进计划 | 190 | 355 |
合计 | 1,315 | 1,575 |
二、题目分析及解题思路
本题要求实现一个数独终局的生成器和数独解题程序,需求较为明显的分为相对独立的两大部分:终局生成与解题,可以分别进行思考、设计和实现。
1. 终局生成
数独终局指一个填满数字 1 1 1 ~ 9 9 9 的 9 × 9 9\times 9 9×9 棋盘,满足其中每一行、每一列、每一九宫格中每个数字只出现一次。一个典型的数独棋盘如图所示,粗实线标出的是九宫格的边界。
本题要求程序生成至多 1 0 6 10^6 106 种数独终局。
由数独的性质,每一行中的数字一定形成一个 1~9 的排列,所以很容易想到使用一个排列生成数独终局的方法。
先取任意一个排列 P 0 P_0 P0 ,填入数独的第一行。随后观察第二行。为了满足每一列上每个数字只出现一次的要求,第二行应该是第一行的一个错位排列,为了简单起见,可以简单的将第一行做循环移动来得到一些典型的错位排列。
此处我们记 P 0 P_0 P0 循环左移 i i i 位得到的排列为 P i P_i Pi ,如 P 0 = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } P_0 = \{1,2,3,4,5,6,7,8,9 \} P0={ 1,2,3,4,5,6,7,8,9} 时, P 3 = { 4 , 5 , 6 , 7 , 8 , 9 , 1 , 2 , 3 } P_3 = \{4,5,6,7,8,9,1,2,3\} P3={ 4,5,6,7,8,9,1,2,3}.
接下来尝试只使用循环排列填入每一行来得到数独终局。为了满足同一九宫格内的限制,属于同一九宫格的三行,其中任两行中的排列,下表之差必须为 3 3 3 的倍数,否则九宫格内另一行会与此两行冲突。因此第二、三行只能填入 P 3 P_3 P3 和 P 6 P_6 P6 ,如下表。
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|
4 | 5 | 6 | 7 | 8 | 9 | 1 | 2 | 3 |
7 | 8 | 9 | 1 | 2 | 3 | 4 | 5 | 6 |
在第四行分别尝试 P 1 P_1 P1 ~ P 8 P_8 P8