Sudoku项目流程(心路历程)
项目地址 github仓库
主要内容
- PSP 2.1 表格
- 项目的准备过程
- 项目实现过程
- 项目的分析改进过程
PSP 2.1表格
PSP 2.1 | Personal Software Process Stages | 预计耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 50 | 60 |
Estimate | 估计这个任务需要多久 | 300 | 360 |
Development | 开发 | 240 | 270 |
Analysis | 需求分析 | 25 | 25 |
Design Spec | 生成设计文档 | 60 | 60 |
Design Review | 设计复审 | 10 | 10 |
Coding Standard | 代码规范 | 5 | 5 |
Design | 具体设计 | 20 | 20 |
Coding | 具体编码 | 240 | 240 |
Code Review | 代码复审 | 5 | 5 |
Test | 测试 | 30 | 30 |
Reporting | 报告 | 60 | 60 |
Test Report | 测试报告 | ||
Size Measurement | 计算工作量 | ||
Postmortem & Process Improvement Plan | 事后总结,提出过程改进意见 |
项目准备过程
-
碎碎念
在刚知道个人作业是写一个数独小项目时,我的内心是崩溃的。因为我从来就没有玩过数独,看见老师发的pdf里生成终局的示例那一长串的数字,我的内心感到十分抗拒。。。
所以这个作业一直拖着没有做直到今天。。。(12.27)
我的动手能力较差,而且也没有相关的经验,所以在预估时间时,心里很没底,基本每一项都是往大了填
-
在大概了解整个项目后,我认为自己需要学习的技能有以下几点:
- git命令的使用 (用于项目的版本控制)
- markdown语法的使用(用于写这篇博客)
- 回溯法等算法的复习(用于生成数独和解决数独)
- 代码质量分析工具的使用
- 性能分析工具的使用
P.S. ORZ 我是真的好菜啊,都大三了这些东西居然还不会用
-
需求分析
实现一个命令行程序,程序能:
- 生成不重复的数独终局至文件
- 读取文件内的数独问题,求解并将结果输出到文件
生成终局
-
在命令行中使用-c参数加数字N(1<=N<=1000000)控制生成数独终局的数量,例如下述命令将生成20个数独终局至文件中:
sudoku.exe -c 20
-
将生成的数独终局用一个文本文件(假设名字叫做 sudoku.txt)的形式保存起来,每次生成的txt文件需要覆盖上次生成的txt文件,文件内的格式如下,数与数之间由空格分开,终局与终局之间空一行,行末无空格
-
程序在处理命令行参数时,不仅能处理格式正确的参数,还能处理各种异常的情况,如:
shudoku.exe -c abc
-
在生成数独矩阵时,左上角第一个数为:(学号后两位相加)%9+1。例如学号后俩位是63,则该数字为(6+3)%9+1 = 1,那么生成的数独棋盘的第一个数字应为1。
求解数独
-
在命令行中使用-s参数加文件名的形式求解数独,并将结果输出至文件,如:
sudoku.exe -s absolute_path_puzzlefile
程序将从路径中读取数独题目并将数独题目的一个可行解输出至与sudoku.exe同目录的sudoku.txt中,要求与生成终局相同。
-
格式如下,其中0代表空格,题目与题目之间空一行,行末无空格,最后一个数独题目后无空行。
-
sudoku.txt的格式与生成终局的要求相同。
-
数独题目个数N(1<=N<=1000000),保证文件中数独格式正确。
-
什么是数独
数独(shù dú)是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,不重复
项目实现过程
-
生成数独终局
数独是一个9*9的矩阵,矩阵中每一行、每一列、每一宫的数字都只能出现一次。
-
搜索 + 剪枝 (没有采用)
第一行按照要求以学号后2位确定第一个数字,剩下8个数字随意写出一个排列,第2行到第9行通过搜索产生。即第2行到第9行的每一个空格都从19逐个放入看是否合法(同一行同一列同一宫没有相同数字出现过),若合法则尝试放入,然后递归地搜索下一个位置上的数字,若19中没有数字合法,则退回上一层递归尝试下一个数字,直到填满9*9矩阵中的所有位置。这样我们可以通过变换第一行的排列顺序得到 8!= 40320 个数独,然后再通过交换2、3行,46行,79行再乘以3!*3!,可以生成的终局数量大于需求要求的1000000。但是考虑到通过这种算法生成终局在搜索过程中每个位置都要进行判断,耗费时间,经过网上资料查询发现了下一种方法。
-
通过数独模板生成数独终局
数独模板:
a b c d e f g h i d e f g h i a b c g h i a b c d e f b a d c f d h i g c f d h i g b a d h i g b a d c f d e c a f d b i g h f d b i g h e c a i g h e c a f d b 我们可以发现这个数独模板是从第二行开始,每行分别是第一行右移3、6、1、4、7、2、5、8列的结果。我们还可以发现,对于任何一个数独终局的13行,我们任意交换这三行的顺序,得到的仍然是一个合法的终局,46行和79行同理,列也同理。我们还可以发现,对于任何一个数独终局的13行,我们任意交换这三行的顺序,得到的仍然是一个合法的终局,46行和79行同理,列也同理。由于需求中要求生成的终局数量N(0<=N<=1e6),而且数独的第一个数字是确定的,所以我们通过变换第一行的数字可以得到8!= 40320个数独,再通过交换2、3行,456行、789行可以得到823!*3!个数独,大于1e6满足需求,不需要再进行列变换。
-
类图
-
来源:CSDN
作者:yuanyuanyuan08
链接:https://blog.csdn.net/yuanyuanyuan08/article/details/104033843