Github 项目地址:https://github.com/zjwml4581792/Software-engineeringhtml
第一次的真软工实践做业就是这种题目,想一想还有点小激动,终于又要敲代码啦。看着本身如今的编程的“纸飞机阶段”,想完成,仍是等待~并心怀但愿吧!git
先看题目。github
我是题目算法
度娘说:数独(百度百科)编程
数独(Sudoku,Crosswords)是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家须要根据9×9盘面上的已知数字,推理出全部剩余空格的数字,并知足每一行、每一列、每个粗线宫(3*3)内的数字均含1-9,不重复。
数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出必定的已知数字和解题条件,利用逻辑和推理,在其余的空格上填入1-9的数字。使1-9每一个数字在每一行、每一列和每一宫中都只出现一次,因此又称“九宫格”。数组
看到的第一眼就是,这个题目跟程序语言综合设计的那个马踏棋盘和N皇后问题好像啊,一百度,果真三个题目常常绑定出现,用的不少都是回溯。markdown
然而本身并非很懂回溯,因而本身找了找不是回溯算法的大神写的博客。惋惜大神写的算法我基本看不懂。dom
各类各样的问题显示了本身的功力不足,函数何时开始回溯啊,调用函数本身的那行到底写在哪里啊,比较好的想法究竟是哪种啊……编程语言
本身什么都不懂,直接开始写是不现实的,因而开始问学长。编辑器
先问了个直系老乡研究生谷歌(仍是微软)大佬,说“数独问题用 dancing links 算法来写”,,一百度好像dancing links 真的很厉害的样子,可是好像这么复杂的双向链表我真的写不出来。
本身百度“数独生成算法”吧,看看前辈们都用的是什么算法,用的思想是否是太超前本身能不能接受。
找到的比较看得懂本身印象比较深有启发的:
因而本身尝试了生成 9 个随机数组一行一行填进矩阵,一个一个数字地填,一个九宫填一个九宫地填等等各类方法。
最后采用了 0~9 轮流逐行地填的方法,即从1开始填,从第0行填到第8行,1填完了填2,直到9。
事实证实采用了某种方法若是理论没问题必定要坚持到底,若是不断地尝试别的方法真的没有效率,就跟《构建之法》里的画扇面同样,过早想着优化,都还没完成必要功能和需求就不要考虑太多。先写出来了再说。
从 【1】 中汲取了“按九宫格从左到右从上到下,从 1-9 轮流填,填完了再填下一个数”的思想并改造;
从 【2】 中获得了先把无依赖的主对角线上的三个小九宫填满,再填其余九宫的思想(可是最终并无用到这方法)
从 【3】 中了解了怎么写回溯算法。
本身的搜索能力暴涨,code能力小幅升,熬夜能力MAX,泡面技巧infinite
。拖延症已病入膏肓
习惯看到题目就先建立个类,这个数独类至少须要有构造函数、析构函数、建立矩阵、打印矩阵四个函数,数独矩阵二维数组,而后根据须要添加了初始化函数,判断函数,文件变量等,详见代码注释。
class Sudo { public: Sudo(int id); //构造函数 ~Sudo(); //析构函数 void createSudoku(int id);//建立数独矩阵 void print(); //打印 void init(); //初始化 private: ofstream outfile; //输出文件 int arr[9][9]; //数独矩阵数组 int flag; //是否把每一行的该数都填好的标志 int firstNumber; //题目要求的跟学号有关的数 bool isRight(int row, int column, int num);//判断row行column列是否能够填num vector<int> randVector(); //生成随机数组 void fillNumber(int num, int row); //从row开始每一行开始填充num void clean(int i); //填充失败,把i数清除,从新填过 };
看到题目想到要写的第一个函数就是判断函数,在写的时候先分别写了行判断、列判断、九宫判断三个函数,以及调用三个函数的isRight原始版,后来整合到一块儿了就成了下面的新生版。因为是逐行填充的,只须要检查列和九宫符不符合要求便可。
后来思考若是按照每一个九宫来填数,只须要判断行和列会不会更快,可是按九宫来填数,填数就麻烦了,根据第一个博客里的来看,应该按九宫来会快些。
bool Sudo::isRight(int row, int column, int num) {//判断所在位置是否可行 for (int i = 0; i < 9; i++) {//检查列可不能够 if (arr[i][column] == num) return false; } int northwestX = row / 3 * 3;//算小九宫的第一个位置 int northwestY = column / 3 * 3; //检查九宫 for (int i = 0; i < 3; i++)//横向检查 { for (int j = 0; j < 3; j++)//竖向检查 { if (arr[i + northwestX][j + northwestY] == num) return false; } } return true; }
若是是普通的随机数的生成的话,必定会生成重复的随机数,因而生成一个0-8的随机数组,须要用的时候遍历数组。
如何生成随机数组的方法是网上找的,C++下数组随机shuffle的方法解
vector<int> Sudo::randVector()//生成随机数组 { vector<int> result; result.clear(); for (int i = 0; i < 9; i++) result.push_back(i); random_shuffle(result.begin(), result.end()); return result; }
建立数独,先填要求的数,再从1-9填,无法填了就退回上一个数从新填过。
void Sudo::createSudoku(int hhhhhh)//建立数独 { fillNumber(firstNumber, 1); //先把要求的那个数填进去 for (int i = 1; i < 9; i++) //从1到9开始填充 { if (i == firstNumber)//若是是要求的那个数 continue; //则跳过 fillNumber(i, 0); //逐行填充数i if (flag) //若是填充好了 flag = false; //将flag置false,准备下一个数 else //若是没填好 { clean(i);//把上一个数清掉,重填 i -= 2; //先-2,待会+1,从上一个数从新开始 } } for (int i = 0; i < 9; i++)//发现上面填完了以后9是空的 { for (int j = 0; j < 9; j++)//就写一个循环把9补上 { if (arr[i][j] == 0) arr[i][j] = 9; } } }
最重要的填数,不过这个回溯挺最简单,从第0行开始填num。
void Sudo::fillNumber(int num, int row)//从row行开始填充num { if (row > 8) //若是0-8行都填完了 { flag = true; //将填好的标志flag置true return; //返回 } vector<int>temp = randVector(); //生成随机数组, for (int i = 0; i < 9; i++) //从数组第一个数开始测试第row行temp[i]列行不行 { if (arr[row][temp.at(i)] != 0)//若是这个位置填过了 continue; //跳过这列 if (isRight(row, temp.at(i), num))//若是这个位置能够 { arr[row][temp.at(i)] = num; //填上去 fillNumber(num, row + 1); //填下一个行 if (flag) //若是填好了 return; //返回 arr[row][temp.at(i)] = 0;//若是这个数这行填不成,把上一行该数置0,换temp下一个数试试 } } }
程序运行截图
图中的运行时间是测试用的,暴露了本身这个算法有待改进,很大的改进。
效能分析
摘要
调用关系树
从中能够看出,主要是填充数函数占了最多时间,所以算法自己有很大的改进空间,好比判断函数,从周同窗的做业中,能够看出本身和TA的差距;也能够把fillNumber函数的返回值设为Bool,也能少个变量flag。另外vector系列也是比较耗时的,用的很少的话,本身写个随机生成数组的函数,借助库函数是比较耗时。
百毒百科说
执行力是指有效利用资源、保质保量达成目标的能力,指的是贯彻战略意图,完成预约目标的操做能力。是把企业战略、规划、目标转化成为效益、成果的关键。
执行力包含完成任务的意愿,完成任务的能力,完成任务的程度。对我的而言执行力就是办事能力;对团队而言执行力就是战斗力;对企业而言执行力就是经营能力。
简单来讲就是行动力。
个人理解就是,在拿到任务以后,用本身最专一的热情去完成这件事,最及时地完成,对待任务当机立断、雷厉风行,以秋风扫落叶之势,脚踏实地、贯彻始终,知行合一。
其实上面的这段话就是泛泛而谈,没有什么针对性,就好比创新创业比赛上,上台的不少学生都是侃侃而谈,对于本身的产品自己的介绍并很少,就算是客观的场面话,也没有讲到针对于自身产品最大的痛点。
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 10 |
· Estimate | · 估计这个任务须要多少时间 | 20 | 10 |
Development | 开发 | 1775 | 1820 |
· Analysis | · 需求分析 (包括学习新技术) | 60 | 73 |
· Design Spec | · 生成设计文档 | 30 | 没有作 |
· Design Review | · 设计复审 (和同事审核设计文档) | 30 | 单干,不须要 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 15 | 7 |
· Design | · 具体设计 | 120 | 120 |
· Coding | · 具体编码 | 1440 | 1560 |
· Code Review | · 代码复审 | 60 | 20 |
· Test | · 测试(自我测试,修改代码,提交修改) | 20 | 40 |
Reporting | 报告 | 155 | 78 |
· Test Report | · 测试报告 | 30 | 30 |
· Size Measurement | · 计算工做量 | 15 | 15 |
· Postmortem & Process Improvement Plan | · 过后总结, 并提出过程改进计划 | 120 | 33 |
合计 | 1960 | 1908 |
第 N 周 | 新增代码(行) | 累计代码(行) | 学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
第 0 周 | 192 | 192 | 31 | 31 | 复习C++语法、学习VS2017操做、了解回溯 |