Sudoku 小项目
Sudoku 小项目 - 软工第二次作业
Part 1 · 项目相关
- Github 地址: https://github.com/TheSkyFucker/Sudoku
项目的更多信息以及所有开发文档见 README.md
整体过程,Todolist工具: Teambition
- 部分动态
- 撰写该文时 SourceTree 结构如下:
Part 2 · PSP 表格
Statu | Stages | 预估耗时 | 实际耗时 |
---|---|---|---|
Accept | 【计划】Planning |
60 | 100 |
Accept | —— 估计时间 Estimate |
60 | 100 |
Accept | 【开发】Development |
345 | 1550 |
Accept | —— 需求分析 Analysis |
20 | 15 |
Accept | —— 设计文档 Design Spec |
60 | 130 |
Accept | —— 设计复审 Design Review |
15 | 20 |
Accept | —— 代码规范 Coding Standard |
20 | 25 |
Accept | —— 具体设计 Design |
30 | 300 |
Accept | —— 具体编码 Coding |
180 | 1000 |
Accept | —— 代码复审 Code Review |
20 | 30 |
Accept | —— 测试 Test |
60 | 30 |
Accept | 【记录用时】Record Time Spent |
10 | 10 |
Accept | 【测试报告】Test Report |
40 | 20 |
Accept | 【算工作量】 Size Measurement |
10 | 10 |
Accept | 【总结改进】 Postmortem |
60 | 45 |
Accept | 【合计】Summary |
585 | 1735 |
Part 3 · 解题思路
- 先按做acm题的心态思考了1~2小时,没想到什么比较优秀的做法;
- 然后疯狂搜索,因为一开始打算做附加题所以搜了不少附加题相关的内容。
- 先是搜到了:矩阵交换法的做法,觉得很机智很快,但是因为所有生成矩阵是等价矩阵所以不想采用这个做法
- 然后搜到了搜索法,这个比较直观,除了拉斯维加斯比较有心意,但是普遍效率都不是很好,基本都存在简单回溯的话确实本来随机性的意义。
- 然后搜到了一个不断随机每一行的做法,觉得很棒,博主也测试说很高效,结果实现了一下发现根本做不了,冷静下来分析了一下才发现是个假算法。。浪费了好多时间。
- 最后还是采取了矩阵交换法,虽然也在项目中实现了所有终盘随机质量很好的回溯法,但是没有在指令<-c>中实装,因为测试发现除非只有几k的数据要求量,不然时间要好几十秒乃至若干分钟。
- 当时想做附加题所以继续思考怎么做终盘,搜到的资料多是在挖空的位置上做文章。
Part 4 · 设计实现
(一)类之间的关系:
(二)代码组织
- 类:Sudoku、SudokuGenerator、SudokuChecker 在项目 Sudoku 里
- 类:SudokuTest、SudokuGeneratorTest、SudokuCheckerTest 在单元测试项目 SudokuTest 里
- 类:ParamChecker、CommandWorker 在项目 Command 里
- 类:ParamCheckerTest 在单元测试项目 CommandTest 里
- 主程序 main.cpp 在项目 Main 里
- 项目 Sudoku,Command 均设为静态
Part 5 · 代码说明
(一)内部函数:快速生成
- 主代码
- 主要思路:通过重编码数字、行、列从已有的终盘快速生成其它终盘。
- 注释:逻辑比较简单,就是找下一个行编码,列编码,数字编码,代码中有简单的英文短语注释。
(二)内部函数:高质量生成
- 主代码
- 主要思路:通过深搜,每次随机能当前格子合法的数字集合中随机一个数字放到当前行、列。
- 注释:传统深搜,短语注释了几个逻辑块。
(三)外部框架:指令系统
- 指令系统分为两个类,一个类是封装所有指令的参数校验,另一个类是实现所有指令的功能
- 从而做到能 高效的拓展指令,笔者搭建好框架后在添加指令<-check>以及<-help>途中感觉非常畅通,其它的代码都被隔开,那种仿佛在一张白纸上工作的感觉相当的棒。
- 整个框架:
- 主程序 根据
argv[1]
判断指令,调用 主程序中相关指令函数段,并负责整个过程中抛出的 exception
- 相关指令函数段:调用 参数校验,接着调用 指令执行。
- 参数校验 框架:
- 指令执行 框架:
(四)程序运行
- 基本上所有的不合法输入都被 单元测试 和 指令系统框架的参数校验代码 ban掉了,所以只展示成功的界面。
<-help> 指令
<-c> 指令
:测试100w的数据量,笔者本地运行时间大概 1s,CPU为 I7-4720HQ。
<-check> 指令
:检验100w的数据量是否有重复,笔者本地运行时间大概6s,CPU为 I7-4720HQ。
(五)改进性能过程
生成改进一
- 最原本的判法是暴力判合法性,但是效率太低了。
- 编写的复杂的 Sudoku 类是主要为质量最好的 回溯法(SudokuGenerator::BestGenerate) 准备的,内部采用了维护每行、每列、每宫的状态来维护整个棋盘;
- 可以做到动态维护数独棋盘是否合法,每次修改格子都只要花几个常数的时间,O(1)查询当前终盘是否有冲突、是否合法等等。
生成改进二
- 一开始 矩阵转换法 习惯性的用了sudoku 存生成的方案,生成100w数据大概要60秒。
- 性能分析工具分析出Sudoku维护函数调用太多。
- 但是矩阵转换法由于是直接重编码,所以不需要维护合法性,换了一下生成100w大概要10秒,提速6倍左右。
生成改进三
- 输出一开始采取一个个输出,效率太低。
- 后面把每个棋盘弄成一个字符串然后puts输出,改进完后生成100w数据大概在 1 秒左右。
校验改进一
- 把每个棋盘压成一个string,然后扔进set来判重复。
- 改进后判定100w个棋盘速度大概在 6s左右。
(六)性能分析图
- 由于设计时就不打算提供非命令行运行,所以性能分析时采用输入信息嵌入主代码的方式。
- 性能分析图
- 分析数据量 1w,测试结果较理想。
- 按调用数排序,核心函数 std::next_permutation 调用次数 1w 多次,理论上生成1w的数据调用次数无法低于 1w
- 次数最高的函数为系统函数,其次是输出函数,函数如下:
(六)总结
- 偏工程方面的总结在 README.md 的文档里。
- 感觉几天内学到了好多东西吧,搜了不少东西,从一开始的把自己弄得手忙脚乱,commit的时候一堆东西揉在一起,代码习惯性的会往打acm题目的风格靠,git里还有100m+的输出文件就commit最后push崩溃才察觉到这个问题,设计了改改了再设计,时常写不出单元测试偷偷先去写主代码最后砸了自己的脚。
- 到后来慢慢熟悉了整个过程,回档fix bug,先写单元测试再写代码,检验文件无异常再commit和merge,每个功能新开一条git 分支编写然后merge回dev分支,VS又报错了也淡定了,exe崩溃了也知道自己可能有野指针或者内存泄漏,慢慢感觉到了一丝丝的秩序,虽然这一切还是按照自己临时搜的一堆资料构建出来的自以为的软件开发应有的流程Orz..但还是觉得学到了很多吧,也研究了一下怎么处理异常好一点,最后学了下try throw的那一套逻辑,但是可能姿势不太对还是搜的信息还不够所以也是按照自己的理解构建了目前项目的整个异常系统,函数声明也会留意要不要const 和throw等等。
- 然后突然发现不会打题了。
End。
Sudoku 小项目的更多相关文章
- 用struts2标签如何从数据库获取数据并在查询页面显示。最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变量。
最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变 ...
- IOS-小项目(饿了么 网络部分 简单实现)
在介绍小项目之前,在此说明一下此代码并非本人所写,我只是随笔的整理者. 在介绍之前先展现一下效果图. 看过效果图大家应该很熟悉了,就是饿了么的一个界面而已,值得注意的是,实现时并没有采用本地连接,而是 ...
- Andriod小项目——在线音乐播放器
转载自: http://blog.csdn.net/sunkes/article/details/51189189 Andriod小项目——在线音乐播放器 Android在线音乐播放器 从大一开始就已 ...
- 模拟XShell的小项目
不知道大家有没有用过XShell这款工具,这款工具通过windows可以远程操作处于开机状态的linux操作系统,也就是说把你的电脑和一台服务器连入网络,你通过输入服务器所在的IP地址建立一个会话就可 ...
- 小项目特供 贪吃蛇游戏(基于C语言)
C语言写贪吃蛇本来是打算去年暑假写的,结果因为ACM集训给耽搁了,因此借寒假的两天功夫写了这个贪吃蛇小项目,顺带把C语言重温了一次. 是发表博客的前一天开始写的,一共写了三个版本,第一天写了第一版,第 ...
- 【PHP小项目使用MVC架构】
小项目名称是雇员管理系统. mvc是一种项目的开发模式,中文名称为模式视图控制器,是强制程序员将数据的输入.处理.输出分开的一种开发模式. 在这个小项目中,控制器使用service作为后缀名. 项目u ...
- MOGRE学习笔记(3)--MOGRE小项目练习
学习OGRE有一段时间了,领导为了检测学习效果,根据已有C++项目,弄一个类似的用c#语言编写的小项目. 配置:win7,DirectX2009,vs2010. 项目要求: 1.有Ogre窗口(尺寸1 ...
- Web前端开发:SQL Jsp小项目(一)
Jsp的学习算是告一段落,针对这段时间的学习,写了一个Jsp小项目来巩固学到的知识. 框架示意图 User list process UserAdd process 需要的界面效果: 需要工具:Ecl ...
- Ado.Net小练习02(小项目CUID
前台界面: 后台代码: namespace ado.net小项目cuid { public partial class Form1 : Form { //连接字符串 ...
随机推荐
- C#集合。
集合命名空间: using system.collections. 非泛型集合 using system.collections.Generic. 泛型集合 为什么要用集合: 1.数组一旦声明长度就 ...
- ____利用C#特性Attribute完成对sql语句的拼接
//定义 特性类: public class MyAttribute : Attribute//自定义注解类判断是否是主键 { public bool PrimaryKey = false; publ ...
- Bean实例化的三种方式
1. 构造器实例化 spring容器通过bean对应的默认的构造函数来实例化bean. 2. 静态工厂方式实例化 首先创建一个静态工厂类,在类中定义一个静态方法创建实例. 静态工厂类及静态方法: pu ...
- 2; HTML 基本结构
1. HTML 的基本结构 2. HTML 控制标记的格式 3. 最常用的控制标记 本章讲解最基本的 HTML 元素,也就是创建文档结构所需的元素.例如:标题.段落. 页面分隔.注释等等. 2.1 H ...
- frontpage 2010.2003绿色版
基本简介 frontpage网页设计软件是微软公司出品的一款网站制作入门级软件.frontpage制作网站软件使用方便简单,会用Word就能做网页,微软在2006年年底前将停止提供FrontPage软 ...
- BZOJ2655: calc(dp 拉格朗日插值)
题意 题目链接 Sol 首先不难想到一个dp 设\(f[i][j]\)表示选了\(i\)个严格递增的数最大的数为\(j\)的方案数 转移的时候判断一下最后一个位置是否是\(j\) \[f[i][j] ...
- CentOS7 离线安装MySQL
1.删除原有的mariadb 不然安装报错 rpm -qa|grep mariadb rpm -e --nodeps mariadb-libs 2. 下载RPM安装包 在https://dev.mys ...
- Python对象相关内置函数
针对一个对象,通过以下几个函数,可以获取到该对象的一些信息. 1.type() ,返回某个值的类型 >>> type() <class 'int'> >>&g ...
- g4e基础篇#5 创建分支和保存代码
章节目录 前言 1. 基础篇: 为什么要使用版本控制系统 Git 分布式版本控制系统的优势 Git 安装和设置 了解Git存储库(Repo) 起步 1 – 创建分支和保存代码 起步 2 – 了解Git ...
- centos7安装jdk环境
有时候安装一些软件或者服务都需要jdk环境,今天就在centos上安装最新的jdk环境. 检测历时安装 1.查看Linux自带的JDK是否已安装 # java -version 2.查看JDK信息 # ...