博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
创建随机的9x9数独游戏终盘并打印
阅读量:5230 次
发布时间:2019-06-14

本文共 3470 字,大约阅读时间需要 11 分钟。

创建随机的9x9数独游戏终盘并打印

1. 项目相关要求

1.1 要求

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

输入
数独棋盘题目个数N(0<N<=1000000)
输出
随机生成N个不重复的已解答完毕的数独棋盘,并输出到sudoku.txt中。

1.2 思路

我是个会数独的人,一看到题目我第一反应是我最喜欢用的数独解法:锁定一种特定数字进行行列摒除。显然这种方法行不通,太麻烦了。

我上网找关于数独终盘的解法,发现一种思路比较满意。先随机生成一行,然后逐个填入行,这样工作9次就可以了。所以我需要一个能够生成随机行的函数。
同时我还发现,虽然摒除很难,但是在电脑上唯余法很容易实现,检查单元所在行、列、宫,这个单元能填什么数字一目了然。写一个唯余法的函数。
理论上只要从上到下、从左到右不断判断+填入就行了。我每行弄一个随机行,排队挨个塞入行中单元。把唯余判断的结果存在一个数组里面,从随机行取数的时候作为参考,只有合法且没用过的数才能放入单元。显然,要是9个数字都放不进去,单元填入就失败了,整行都失败了,要清空重来。
实际实现的时候发现在生成几个终盘之后,程序死循环了。分析发现某些情况下不管一行怎么试,行填入都失败,显然是前面的行生成有问题。并且不仅是最后一行,后面几行都有可能有这个问题。于是我就统计行失败次数,失败次数过多就全盘推翻重来。


2. 遇到的困难及解决方法

2.1 困难描述

我代码基础差,并且很久没有打代码了,所以这个源代码花了我好几个小时的时间。但是我觉得值,因为我能一点一点地推进,每次完成一个小目标,最后终于把整个程序打出来了。那种感觉很爽。

但是单元测试就是搞不定。

2.2 做过哪些尝试

花在单元测试上的时间:173分钟。

找了很多的博客,大多都语焉不详。从来没有一个博客我能够照着每一步做完的。我的最终成果:

1070732-20170910002416241-275165527.png

我装了JetBrains,但是没有在菜单里面找到测试代码覆盖度的选项,如下图:

1070732-20170910002227319-217191059.png

能够测试,但是不能使用我打的函数,用了就会提示未声明出错,没有一个博客给出过解释。

2.3 是否解决

未解决。

2.4 有何收获

解决不了的问题不要瞎耗时间,你的时间很宝贵。

不仅要有估计时间,更要有最大时间。最大时间到了就果断放弃,完美主义要不得。后面性能分析的时候我就学聪明了。
时间应该花在刀刃上,陷在“软件使用”这种坑里面很危险,不仅没用,还会令人愤怒焦躁、损害编程创造的兴趣。

3. 代码与设计

3.1 关键代码

/* * 输入行、列位置,尝试向该单元填入数字。填入成功返回true,否则 * 返回false。 */bool filling_unit(int y, int x) {    /*     * 每次填入使用一次removeArray,所以需要初始化。排除完毕后根据     * removeArray顺序拿取randomArray中的数字,找到合适的数字,填     * 入成功;找不到,填入失败。     */    memset(removeArray, 0, sizeof(removeArray));    remove_impossible_unit(y, x);    for (int i = 0; i < 9; ++i) {        if (randomArray[i] != 0) {            if (removeArray[randomArray[i] - 1] == 0) {                sudoku[y][x] = randomArray[i];                randomArray[i] = 0;                return true;            }        }    }    return false;}/* * 填充数独盘面。 */void filling_sudoku() {    int rowDeathCount = 0;    for (int i = 0; i < 9; ++i) {        if (i == 0) {            /*             * 第一行直接填入行首为1的合法随机数组。             */            generate_random_array_special();            filling_first_row();        }        else {            /*             * 生成合法随机数组,尝试填入行。填入行即为分别填入行内9             * 个单元,其中一个单元填入失败,填入行失败;否则成功。如             * 果填入行失败,重试。             * 在一个数独盘面内,如果填入行失败超过100次,重新执行该函             * 数。             */            generate_random_array();            for (int j = 0; j < 9; ++j) {                if (!filling_unit(i, j)) {                    delete_row(i);                    j = -1;                    generate_random_array();                    rowDeathCount++;                }                if (rowDeathCount == 100) {                    memset(sudoku, 0, sizeof(sudoku));                    rowDeathCount = 0;                    i = -1;                    break;                }            }        }    }}

3.2 设计说明

1070732-20170909233031194-858837821.png

方框为函数,箭头为调用关系,绿色部分为main。不包括测试函数。

3.3 测试运行

1070732-20170909233719851-1298226846.png

1070732-20170909233726444-1743779069.png

1070732-20170909233732272-353013511.png

1070732-20170909233737851-745513419.png

1070732-20170909233743741-1292014267.png

1070732-20170909233748538-1224160901.png

1070732-20170909233806101-676169004.png

1070732-20170909233813569-1120952484.png

1070732-20170909233818335-628646142.png

1070732-20170909233822897-558126656.png

1070732-20170909233828147-1412713015.png

1070732-20170909233833397-657299877.png

3.4 性能分析

  • 使用CPU采样-以项目为目标进行分析,出错:

    1070732-20170910000710835-1212555280.png

  • 使用CPU采样-以可执行文件为目标进行分析:

    1070732-20170910000957429-368250658.png

  • 使用检测分析方法:

    1070732-20170910001117882-1837640705.png

很奇怪,没有达到预期的效果。无法分析性能,但是我使用命令行运行exe,生成10000数独终盘大概花了7s时间。

4. PSP

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 10 6
· Estimate · 估计这个任务需要多少时间 10 6
Development 开发 450 908
· Analysis · 需求分析 (包括学习新技术) 240 263
· Design Spec · 生成设计文档 20 40
· Design Review · 设计复审 (和同事审核设计文档) 3 49
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 7 5
· Design · 具体设计 30 53
· Coding · 具体编码 60 175
· Code Review · 代码复审 30 15
· Test · 测试(自我测试,修改代码,提交修改) 60 308
Reporting 报告 50 144
· Test Report · 测试报告 20 18
· Size Measurement · 计算工作量 10 0
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 20 126
合计 510 1058

“单元测试”算在“测试”里面。

5. 记录自己的学习进度条(每周追加)

第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
0 415 415 19 19 学会使用VS2017、PSP流程

转载于:https://www.cnblogs.com/Metak/p/7499628.html

你可能感兴趣的文章
浅谈vue的生命周期
查看>>
[codevs 1017]乘积最大
查看>>
在iOS端如何使用Charles用作http调试
查看>>
ThinkPHP 5.0 控制器-》请求-》数据库
查看>>
记录Centos7搭建ftp服务器以及遇到的各种坑
查看>>
SQLServer 存储过程
查看>>
牛客多校Round 8
查看>>
js不经过提示,直接关闭窗口
查看>>
线程阻塞释放的5种方法
查看>>
无锁编程笔记
查看>>
c实现ls功能-王喜燕
查看>>
jquery mobile
查看>>
方法引用
查看>>
sql 技巧
查看>>
CF1015F Bracket Substring(dp+Trie图)
查看>>
在Windows环境下使用短信猫收发短信的简单配置:
查看>>
如何在vue单页应用中使用百度地图
查看>>
Ubuntu 下安装Go语言
查看>>
Application对象
查看>>
命令查看当前电脑安装所有版本.NET Core SKD
查看>>