软件工程个人项目— 数独
软件工程个人项目— 数独
1120173032 王晗
Github:https://github.com/lion-han/sudoku
目录
软件工程个人项目— 数独
PSP2.1 表格
个人日报:
程序功能简介:
结题思路:
生成终局
生成题目
求解数独
设计实现过程(另一篇博客)
代码组织
代码说明
单元测试(另一篇博客)
性能分析(另一篇博客)
PSP2.1 表格
PSP2.1 | Personal Software ProcessStages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 55 |
Estimate | 估计这个任务需要多少时间 | 20 | 20 |
Development | 开发 | 700 | 700 |
Analysis | 需求分析 (包括学习新技术) | 380 | 450 |
Design Spec | ·生成设计文档 | 100 | 60 |
Design Review | 设计复审 (和同事审核设计文档) | 50 | 30 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范 | 30 | 30 |
Design | · 具体设计 | 80 | 60 |
Coding | 具体编码 | 750 | 1200 |
Code Review | 代码复审 | 60 | 80 |
Test | 测试(自我测试,修改代码,提交修改) | 250 | 1160 |
Reporting | 报告 | 240 | 480 |
Test Report | 测试报告 | 60 | 120 |
Size Measurement | 计算工作量 | 30 | 30 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 40 | 50 |
合计 | 2850 | 4520 |
个人日报:
日期 | 工作情况 | 耗时 |
---|---|---|
12.23 | 分析并选题 | 60min |
12.24 | 创建博客、github仓库、需求分析、解题思路 | 90min |
12.25 | 解题思路 | 50min |
12.26 | 学习DLX算法、生成数独终局,github托管调试 | 190min |
12.27 | 完成数独题目生成部分,github托管成功 | 170min |
12.28 | 完成解数独部分(暴力解),加入命令行分析与报错,进行代码结构化调整 | 250min |
12.29 | vs项目出错,修改bug,重建项目,push | 180min |
1.14 | 发现没有进行行的交换,修改代码,实现生产1200000个不同的数独 | 150min |
1.15 | 学习单元测试工具之间的区别,学习安装使用gtest进行单元测试 | 200min |
1.16 | 优化数独生成时间,尝试不同文件读写方式 | 240min |
1.17 | 学习vs性能分析工具,进行string字符串处理的优化,文件读写的优化 | 300min |
1.18 | 继续学习单元测试,完成单元测试,进行覆盖率,进行代码分析,修改错误 | 360min |
1.19 | 补充单元测试,组织博客内容 | 300min |
程序功能简介:
实现一个命令行程序,具有以下功能:
生成不重复的N个数独终局至文件(1<=N<=1000000)
读取文件内的数独问题,求解并将结果输出到文件
具体需求详见软件工程基础-个人项目文档
结题思路:
生成终局
最开始的想法是一位一位的产生数独的每位数字,但是总也想不出高效的解决方法。于是上网查了些资料,并通过自己画图研究数独时发现,想要生成数目庞大的数独终局,不能通过随机的分配或者一位一位产生,必须通过一定规律的变化得到。
我发现通过确定第一行的数,后面7行通过对第一行不同的移位可产生一个数独终局。由于每个3*3的方块内不能有重复的数,所以1、2、3行,4、5、6行,7、8、9行内位移必须大于等于3,不然会出现重复。
通过变化第一行的数顺序,其余7行移位规律不变(),可产生8!=40320个终局(第一位固定,后面7行移位规律相同)
之后可以通过2、3行,4、5、6行,7、8、9行内交换任意两行可得到不同的矩阵,共2*6*6=72种变化
通过上述变化可产生 8! *(2*6*6)=2903040>1e6 可满足条件,并且分析后不会产生相同的数独。
但是如何进行第一行的全排列是一个问题,首先我想到的是,通过遍历来解决,但是9个数字需要9^9 的时间消耗来解决,显然不可行,然后我想到类似于桶排序的方法确定每位是否被用过,但是并不能提升效率。然后上网搜索,发现一种康托展开的方法,它是一个全排列到一个自然数的双射,可以把一个自然数转换成一个对应的全排列,也可以把一个全排列转换成一个对应的自然数,使用逆康托展开可以在O(N*N)的时间复杂度下形成一个全排列。效率有了很大的提升。实现个小模块之后,通过与ACM室友的交流,我了解到c++里有一个产生全排列的函数 next_permutation 可以产生全排列。于是我去网上搜索它的实现原理,next_permutation 通过分析全排列的规律来交换数字反向操作实现下一个全排列,时间复杂度可达O(N),已经非常好了。
全排列问题解决了,如何进行第一行的移位呢,首先顺序移位是有点慢的O(N),使用链表可达到O(1),但是链表比较麻烦,最终想出了将第一行数字再连接一个第一行数字,通过每次取不同位置的9个数即可,可达到O(1)。
然后便是交换数独的行,形成新的数独,由于要求第一行首为与学号有关的特定数,所以第一行不动,交换其他行。首先我想到的是实现一个函数用来交换特定行的内容,但是这不仅要求交换两行,而且要求交换3行,且交换的规律是特定的很难通过递归循环来实现。于是我想到根据上面形成的初始数独,对他的行的排列写一个30*9的数组,规定行的顺序,然后按照顺序进行数独的生成。
生成题目
由于上一步已经产生了许多数独终局,所以数独问题的产生就可以依靠产生的数独终局文件了。读取数独终局文件,通过输入参数n,可以生成n个数独题目。题目的生成通过随机给数独的位置赋值0来解决。也可以加入一个空白比例参数实现题目的难度级别。再写入文件。
求解数独
开始时感觉数独求解应该很费时间,所以先去网上搜索了一下数独的求解问题。发现了一个DLX算法用来解决精准覆盖的问题,刚好可以用在解数独上,它通过一种双向十字链表的数据结构加上搜索来解决问题。但是把它用来解数独实践起来还是有点难度。毕竟是一个软件工程项目,不仅仅是程序设计问题,所以我就先使用简单的DFS(深度优先搜索)进行数独的求解。在实现后发现挖空率在60%都可以非常快的求解出来,所以就先使用DFS来解数独了。分析挖空率为50%的数独,发现实际上求解还是挺简单的,每个空可填的数字都非常有限。所以决定使用DFS来实现数独求解。
其他博客:
设计实现过程(另一篇博客)
单元测试(另一篇博客)
性能分析(另一篇博客)
软件工程个人项目— 数独相关推荐
- BIT软件工程个人项目——数独sudoku
BIT软件工程个人项目--数独sudoku 目录: (点击可页内跳转) 1. 项目地址 2. PSP表格 3. 解题思路描述 --3.1初期思考 --3.2数独终局生成 --3.3求解数独 4. 设计 ...
- 软件工程基础-个人项目-数独游戏
软件工程基础-个人项目-数独游戏 ----------------------------------------------------------------------------------- ...
- 软件工程基础个人项目——数独(5)
软件工程基础个人项目--数独 点击这里可看github上的具体代码 本次个人项目关于数独的生成与求解 PSP表格 PSP2.1 Personal Software Process Stages 预估耗 ...
- 软件工程基础——个人项目——数独(1)
软件工程基础--个人项目--数独(1) 一.实现目标 1.生成数独终局 命令行输入如下: sudoku.exe -c 20 sudoku.exe为最终实现程序,-c确定活动为生成数独终局,20为生成结 ...
- 软件工程基础-个人项目-数独
个人项目–数独 目录) 个人项目--数独 1 项目地址 2 PSP表格 3 思路描述 3.1 数独终局生成 3.1.1. 暴力法 3.1.2. 全排列及行变换 3.2 功能实现思路 3.2.1. 数独 ...
- 软件工程个人项目——买书的最低价格
软件工程个人项目--买书的最低价格 题目要求: 书店针对<哈利波特>系列书籍进行促销活动,一共5卷,用编号0.1.2.3.4表示,单独一卷售价8元, 具体折扣如下所示: 本数 ...
- 大三软件工程小项目-小技术集合总结
大三软件工程小项目-小技术集 此篇文章是给出了此小项目用到的技术的总结: 方便自己有忘记的知识点后方便查阅. 也方便有需要的博友看. 下面是各个计算的链接 大家点击了进能进去 大三软件工程小项目-小技 ...
- 现代软件工程团队项目贝塔阶段_大规模测试结果_2018.02.08
现代软件工程团队项目贝塔阶段_大规模测试结果_2018.02.08 经过课程全班同学测试后,将收集到的所有BUG和建议汇总如下 BUG按照状态.严重程度.优先级进行了基本的分类 目前打算的BUG修改顺 ...
- JavaWeb项目-快递代领-需求分析(二)-软件工程-小组项目
快递带领-需求分析 1.项目简介 1.1项目背景 快递又称速递或快运,是指物流企业(含货运代理) 通过自身的独立网络或以联营合作(即联网)的方式,将用户委托的文件或包裹,快捷而安全地从发件人送达收件人 ...
- 软件工程小组项目——单词计数
软件工程小组项目--单词计数 项目地址 PSP表格 解题思路 实现过程 1.字符数 2.单词数 3.行数 4.各段行数统计 5.对子目录文件进行操作 6.图形界面 性能优化 实验总结 项目地址 Git ...
最新文章
- Kaggle经典数据分析项目:泰坦尼克号生存预测!
- 婚姻是唯一没有领导者的联盟
- Java学习 第三章 数组(二)多维数组
- 前端学习(1933)vue之电商管理系统电商系统之优化树形控件
- emacs中安装markdown-mode
- 作者:李雪梅(1984-),女,烟台中科网络技术研究所研发工程师。
- Dart 3-Day
- win7·64bit+VS2013+opencv的简单配置
- Linux内核漏洞精准检测如何做?SCA工具不能只在软件层面
- C/C++ 最易受攻击、70% 漏洞无效,揭秘全球开源组件安全现状
- 用友U8审批流相关开发
- Firefox中强制复制粘贴的插件
- stm32+ESP8266实现最简单的手机控制LED灯
- [全网首发]坚果Pro3 root教程 Magisk
- C语言伽罗华域乘法,伽罗瓦域上的乘法
- java 某年某月的天数_1160-C语言实验——某年某月的天数-JAVA
- 做了3年单片机工程师,如果工资还是3-5千,那你就看过来
- MyBatis自带的缓存配置(Cache)
- c语言求数字b在a中出现次数,编写一个函数void fun(char *tt,int pp[]),统计在tt字符中a到z26各字母各自出现的次数,并依次放在pp所指的数组中。...
- 回顾Win10自带表情包快捷键
热门文章
- mysql根据日周月分组计算
- SQL语句中case、when、then的使用
- 快速搭建基于《搜狗微信》的公众号爬虫---搜狗微信公众号爬虫教程
- 台式计算机麦说不了话,耳机有声音麦克风没声音怎么办?解决电脑耳机有声音麦不能说话...
- 第一次训练----跳房子
- 数字逻辑——七段数码管
- 修改win10搜索框(Cortana)调用默认浏览器(edge)和搜索引擎
- VSCODE一个阴坑
- java生成eml_用Java创建一个.eml(email)文件
- 【python】给excel加密