数独终盘实践

第二次软工实践

项目github地址

项目需求

利用程序随机构造出N个已解答的数独棋盘 。

输入

数独棋盘题目个数N(0<N<=1000000)

输出

随机生成N个不重复已解答完毕的数独棋盘,并输出到sudoku.txt中,输出格式见下输出示例。[2017.9.4 新增要求] 在生成数独矩阵时,左上角的第一个数为:(学号后两位相加)% 9 + 1。例如学生A学号后2位是80,则该数字为(8+0)% 9 + 1 = 9,那么生成的数独棋盘应如下(x表示满足数独规则的任意数字):

9 x x x x x x x x
x x x x x x x x x
x x x x x x x x x
x x x x x x x x x
x x x x x x x x x
x x x x x x x x x
x x x x x x x x x
x x x x x x x x x
x x x x x x x x x

输入示例

3

输出示例(输出文件示例戳我

 
 
 
 
 
2 6 8 4 7 3 9 5 1
3 4 1 9 6 5 2 7 8
7 9 5 8 1 2 3 6 4
5 7 4 6 2 1 8 3 9
1 3 9 5 4 8 6 2 7
8 2 6 3 9 7 4 1 5
9 1 7 2 8 6 5 4 3
6 8 3 1 5 4 7 9 2
4 5 2 7 3 9 1 8 6
4 5 1 7 8 2 3 6 9
7 8 6 4 9 3 5 2 1
3 9 2 1 5 6 4 8 7
5 2 7 6 4 9 8 1 3
9 6 8 5 3 1 2 7 4
1 3 4 2 7 8 6 9 5
8 1 5 3 6 7 9 4 2
6 7 3 9 2 4 1 5 8
2 4 9 8 1 5 7 3 6
9 5 8 3 6 7 1 2 4
2 3 7 4 5 1 9 6 8
1 4 6 9 2 8 3 5 7
6 1 2 8 7 4 5 9 3
5 7 3 6 1 9 4 8 2
4 8 9 2 3 5 6 7 1
7 2 4 5 9 3 8 1 6
8 9 1 7 4 6 2 3 5
 
3 6 5 1 8 2 7 4 9
 

遇到的问题

  • c++ io文件操作是性能的主要瓶颈,最后改为c的io操作快了很多。

PSP分析

    
PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 15 10
· Estimate · 估计这个任务需要多少时间 15 10
Development 开发 400 425
· Analysis · 需求分析 (包括学习新技术) 40 35
· Design Spec · 生成设计文档 30 35
· Design Review · 设计复审 (和同事审核设计文档) 0 0
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 10 15
· Design · 具体设计 110 90
· Coding · 具体编码 100 160
· Code Review · 代码复审 20 30
· Test · 测试(自我测试,修改代码,提交修改) 90 60
Reporting 报告 55 62
· Test Report · 测试报告 15 20
· Size Measurement · 计算工作量 15 12
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 25 30
合计   470 500

 

 

解题思路

想法应该就是dfs去搜索满足行、列、块三个互斥条件的终盘,至于附加需求就只需在找到一个可行的棋盘后将左上角的数字全盘和自己需要的数字调换位置。每个dfs调用里,先取出需要放置的数,遍历判断行是否满足,满足的话判断那行对应的三个小块是否满足,最终判断那一行那一块的三个列是否满足,都满足的话就将数字放置进去,进行下一个数字的dfs。最终生成终盘。

 

设计实现

由于这次实践涉及的主要是算法,其次加了个文件操作,c++也挺长时间没写了,所以我封装了一个文件输出类(最终没用到),大部分代码写到了主类里。

 

代码说明

for (int row = 0; row < 9; row++)//从第一行开始往下扫描
{
    if (!rows[t][row]) {
        int b = row / 3;
        for (int block = b*3; block < b*3+3; block++)//每行会有3块九宫格可以扫描
        {
            if (!blocks[t][block])
            {
                int k = block % 3;
                for (int cloumn = k*3; cloumn < (k + 1) * 3; cloumn++)//每行每块会有3列可以扫描
                {
                    if (!cloumns[t][cloumn]&&!sudoku[row][cloumn])
                    {
                        sudoku[row][cloumn] = t;
 
                        blocks[t][block]  = 1;
                        rows[t][row] = 1;
                        cloumns[t][cloumn] = 1;
                        find(index + 1);
                        blocks[t][block] =0;
                        rows[t][row] = 0;
                        cloumns[t][cloumn] = 0;
                        sudoku[row][cloumn] = 0;
                    }
                }
            }
        }
        break;
    }
}
 

 

测试运行

 

 结果:

  

性能分析

代码覆盖率的插件CoverageValidator安装了之后运行闪退,最终还是没有测出代码覆盖率

单元测试: 10万条数据 加输出共耗时9秒

 

 

posted @ 2017-09-10 21:44  CoderQiang  阅读(666)  评论(4编辑  收藏  举报