软件工程实践2017第二次作业-----个人项目实战之数独
最后一门考试2017.9.16
github地址:https://github.com/ssuo/shudu####
题目地址:http://www.cnblogs.com/vertextao/p/7472376.html####
解题思路####
题目要求有1000000中不同数组,在首位数字确定的情况下,第一行还剩下8个空位,将剩下的8个数字随机排列组合,就会产生8!=40320种不同的可能性。所以第一行数相同的情况下还要能生成25个不同数独才能达到个数要求。补考九号才结束,之前一直没做,临时想不出方法来,只好用固定套路,根据第一行数生成完整的数独,所以我的程序所能做到的最大不同个数为40320个。
设计实现####
数独的要求是每一行,每一列,每一宫的数字都不能重复,当第一行的数由1~9排列着组合,剩下的行可以由第一行平移得到(平移格数n取值不重复且不为0),这样就能保证所有行数字不重复,所有列数字不重复。为了使每个宫(3行*3列)的数字也不重复,每三行内的平移数依次相差3,如【第二行平移3,第三行平移6】【第四行平移2,第五行平移5,第六行平移8】【第七行平移1,第八行平移4,第九行平移7】。
第一行进行19排列组合时花特别久时间,最开始的想法是使用回溯法,生成取值范围内的随机数放入,与之前生成的相比较,如果发现重复,则撤回重新生成,但这种做法生成重复数据的概率大,回溯次数多,生成效率太低,很有可能超过题目所要求的1000个60s。生成效率低的原因,主要是每个数都只需要出现一次,但用随机数却会重复出现,要提高生成效率,就要解决这个问题。再回归最初的目的,是要将19排列合,那么,不如就直接这么做?建立数组b[8],存放{1,3,4,5,6,7,8,9},生成随机数,将数组b对应位置的数放入数独第一行,被选择中的数字之后的数依次向前挪一位将该数覆盖掉,用srand%(9-i)来限制随机数大小,这样每生成一次随机数取走一个b数组元素,随机数的取值范围都将减小1直至减到0.
代码说明####
代码分为两个部分,一是函数shudu,主要功能是生成1~9的排列组合后按统一模式暴力求解出数独并输出;二是主函数部分,功能是输入生成个数n后使用for循环多次调用shudu函数。
生成随机数的代码
int i,j,x,m;
int a[9][9]={{2}}; //a[9][9]为数独数组
int b[8]={1,3,4,5,6,7,8,9}; //b[8]存放除1~9(除去首位数字2),后续从b中取出数放入a,防止重复出现
for(i=0;i<8;i++) // 用i做for循环共做8次,填满第一行剩下的8个数
{x=rand()%(8-i); // 限制随机数的取值范围[0,8-i)
a[0][i+1]=b[x]; //将随机数指向的b中的元素放入a;
for(j=x;j<8-i;j++ )
b[j]=b[j+1]; } //将b中被取出的元素后的 数依次向前挪一位,覆盖住被取出的数,避免重复。随着随机数取值范围每次减1,最后一位数下次将不会被取到,避免重复。
生成数独的算法
for(m=0;m<9;m++)
{
a[1][m]=a[0][(m+3)%9] ; //根据已有的第一行,按照固定规则生成数独。
a[2][m]=a[0][(m+6)%9] ;
a[3][m]=a[0][(m+1)%9] ;
a[4][m]=a[0][(m+4)%9] ;
a[5][m]=a[0][(m+7)%9] ;
a[6][m]=a[0][(m+2)%9] ;
a[7][m]=a[0][(m+5)%9] ;
a[8][m]=a[0][(m+8)%9] ;
}
测试运行####
总结####
这次实验做的并不好,没有达成规定要求个数。刚开始想的太复杂,循环多了,被绕的有点乱。也曾尝试将历史首行组合存入一个大小c【40320】【8】的数组中,每次生成的随机数组和都与之比较,但是回溯一直实现的很差,逻辑混乱,最后放弃了。在作业中,也学到了许多新内容,如用srand生成个随机数,生成的时候要把时间种子放在主函数里,如果放在自己写的函数里,产生的随机数排列会一模一样,这个错改了很久没找到,最后在小可爱舍友的帮助下才发现。这次作业也让我深刻感受到自己对语言很不熟悉,思路有了之后,敲代码敲了特别久,写的磕磕碰碰的,语言不熟悉,一直在翻书,感觉自己就像《构建之法》书中写的一边翻书一边做手术的医生,到头来还是有错误,也改很久。翻一翻自己的代码,只有五六十行,逻辑也很简单却写了那么久,感觉还是要每天写一个小时左右代码让自己有个手感。很不常写代码,虽然功能不完善,但写出来了还是很开心,会继续努力的!
PSP表格####
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 30 |
· Estimate | · 估计这个任务需要多少时间 | ||
Development | 开发 | 0 | 0 |
· Analysis | · 需求分析 (包括学习新技术) | 40 | 60 |
· Design Spec | · 生成设计文档 | 0 | 0 |
· Design Review | · 设计复审 (和同事审核设计文档) | 0 | 0 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 20 | 20 |
· Design | · 具体设计 | 60 | 50 |
· Coding | · 具体编码 | 180 | 300 |
· Code Review | · 代码复审 | 90 | 90 |
· Test | · 测试(自我测试,修改代码,提交修改) | 60 | 180 |
Reporting | 报告 | 0 | 0 |
· Test Report | · 测试报告 | 180 | 0 |
· Size Measurement | · 计算工作量 | 0 | 0 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 30 |
合计 | 780 | 760 |
对泛泛而谈和执行力的理解####
执行力
执行力,我认为应该是有效率的完成既定的目标或任务的能力。按时交作业交任务是一种执行力,按计划吃饭睡觉也是一种执行力。接到一个新任务、或者一个新阶段开始(比如开学)的时候,我会有很多雄心壮志,给自己立无数Flag。最后熬夜压deadline,期末通宵复习,被啪啪打脸,这大概就是执行力不足的问题。对我来说,自己能发现的原因有四个:一是三分钟热度,刚开始的时候很激情很认真,一开始做别的事情,注意力就整个分散开了,等下次想起最初的任务,已不知今夕何夕。每学期开学第一周,课前预习,课后复习,中午看书,晚上做作业,整个人都散发着勤劳的光。过完第一个周末 ,发现一部好剧,打开一个好玩的游戏,学霸日程表就走远了。二是没有做好时间规划,定好每个小阶段的任务。经过大学前两年的惨痛经历,我深刻认识到学霸课程表是不适合我的,相信也有很多人不能一直坚持学习少娱乐。但并不是所有人都需要最后熬夜赶任务。平时不想做,拖着拖着,总觉得截止日期还远着呢远着呢,猝不及防有一天它就到了。所以我觉得可以自己将任务分成很多很多小阶段,弄个截止日,一次做一点,做完了就去耍,不会太累太烦太多然后不想动。细化计划表,可能会好些。(这一点就是泛泛而谈了,我还没试过。嗯,下次作业出来了,计划表还没弄,难道要先为定计划表这件事再弄个表我才会想起来去做它orz)。三是期望过高,没有认清自己的能力。总想着这个不大好那个不大好等我再弄弄搞个大事情然后发现嗨呀这个好难那个也超出能力范围十万八千里,眼高手低的结果就是最基础的都做不好。四是兴趣。这个听起来很虚,但我觉得是真的有的,喜欢的话,没事儿自己就会想去做,不喜欢的东西才会需要弄计划表那一大堆东西(囧。。)
泛泛而谈
泛泛而谈,是喊口号吧,乱立flag,还有不给事情定一个准确的时间去做。我说我要考驾照,天知道是明天还是十年后呢......