数独终盘实践

第二次软工实践

项目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.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划1510
· Estimate· 估计这个任务需要多少时间1510
Development开发400425
· Analysis· 需求分析 (包括学习新技术)4035
· Design Spec· 生成设计文档3035
· Design Review· 设计复审 (和同事审核设计文档)00
· Coding Standard· 代码规范 (为目前的开发制定合适的规范)1015
· Design· 具体设计11090
· Coding· 具体编码100160
· Code Review· 代码复审2030
· Test· 测试(自我测试,修改代码,提交修改)9060
Reporting报告5562
· Test Report· 测试报告1520
· Size Measurement· 计算工作量1512
· Postmortem & Process Improvement Plan· 事后总结, 并提出过程改进计划2530
合计 470500

 

 

解题思路

想法应该就是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秒

 

 

转载于:https://www.cnblogs.com/zhengshiqiang47/p/7502457.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值