软件工程实践2017第二次作业


Github项目地址:https://github.com/a270331257/sudoku


PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划
· Estimate · 估计这个任务需要多少时间 2小时 4小时
Development 开发 4小时 5.5小时
· Analysis · 需求分析 (包括学习新技术)
· Design Spec · 生成设计文档 1小时 0.5小时
· Design Review · 设计复审 (和同事审核设计文档) 0小时 0小时
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 10分钟 10分钟
· Design · 具体设计 1小时 0.5小时
· Coding · 具体编码 2小时 4小时
· Code Review · 代码复审 1小时 3小时
· Test · 测试(自我测试,修改代码,提交修改) 1小时 2.5小时
Reporting 报告
· Test Report · 测试报告 0.5小时 0.5小时
· Size Measurement · 计算工作量 0.5小时 0.5小时
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 0.5小时 2小时
合计 13小时40分钟 23小时10分钟

解题思路:

刚开始看到数独的题目时,我觉得应该是挺简单的,因为从数学的角度看,也就是三个限制条件加上去生产一个矩阵。但是当我真正用代码操作起来时,我发现这三个限制条件并不好直接进行。 首先在开始写之前,我在纸上在头脑里构思了几种直接填数去生成完全随机数独矩阵的方法,一种是按行,每行先添加第一个数字1,第二遍每行添加2,但如果用代码执行的话,难以确定下一行的数字的随机位置,前三行填数后,接下来三行重置,而在前三行填数同时,每次填完后要根据填的位置去排除该列以及对应的所在3X3矩阵的三列,十分复杂。于是在构思中就放弃了这种想法。改用另一种较为容易实现的方法,也是我第一次采用的方法。即将9X9划分为3X3宫格,编号1-9,每次从1号矩阵填入一个数字到9号矩阵,直到9填完。 然而这第一次实践尝试就遇到了严重问题,第一个是srand()函数以time为seed运行后,rand()函数无法正常运行,只有以1为seed时才能成功输出矩阵,但由于srand无法使用,rand的伪随机特性使得我的代码无法在出现填数卡死的时候回溯,最多只运行到填6时,就会陷入死循环。而我对这个错误实在是毫无头绪。我查阅了许多这两个函数的相关说明,并且另外重新写了代码测试他们的使用方法,觉得在原本的代码中应该写法是没有问题的,然而就是会导致输入数据后无法输出,陷入死循环。由于时间紧张,无奈这个方法被我全盘推翻,我开始思考下一个方案,并且得尽快能完成。 这个方案也是我目前上传的方案,其实我真的感觉很惭愧,因为这是一个我自己也觉得缺点十分多的方案。这是根据矩阵行列交换不改变的性质而设计的,只要加上数独的限制,即3X3矩阵内不重复,放在9X9矩阵中就是1-3行或列任意交换,4-6行或列任意交换,7-9行或列任意交换,仍然生产一个数独矩阵。在理论上,可以通过足够多次行列的交换生成任意一个我们想要的矩阵。但是,由于题目的另一个限制,我的第一格不可被交换,因此这个算法导致一行与一列整个模式十分固定,只有行与行或列与列的互换,而没有行列的交叉,是一个伪随机的生成。除此之外,另一个致命缺陷是它只能通过先有矩阵进行生成,这个现有矩阵我称其为种子,种子越多,生成的随机数独矩阵越多,一个种子可以生成接近四百个矩阵,然而与1000000相去甚远,我得手动添加两千多个种子才可能去生成如此多随机数独矩阵,以时间与人力完全不可能,因此很惭愧,这次的作业我完成的十分不好。

设计实现过程:

主体直接以一个9X9二维数组作为输出,不使用类,每次重置数组。包含一个swap交换函数,用于行列交换,因为思路及操作都较为简单,其余操作均在main函数中完成。 因为关键函数是一个直接顺序进行的简单循环选择操作,因此流程也较为简单。 ![](http://images2017.cnblogs.com/blog/1227195/201709/1227195-20170910113831038-1966344513.png)
代码说明:
``` //代码为行交换的代码,列交换同理,仅将行变量改为列变量// for(i=0;i<9;i++)//进行九次随机的行与行、列与列交换// { chose=rand()%3;//通过chose变量选择与哪个行交换// row=rand()%3+6;//选择进行交换的随机的基行// line=rand()%3+6;//选择进行交换的随机一列,因为代码与行交换基本相同,未贴出,紧跟在行交换后,在for循环当中// if(row==6)//基行为第六行// { switch(chose) {case 0:break;//chose=0时,不交换// case 1://chose=1时,与除本行外的三行中最高行交换// for(j=0;j<9;j++) swap(soduku[6][j],soduku[7][j]); break; case 2://chose=2时,与除本行外的三行中最低行交换// for(j=0;j<9;j++) swap(soduku[6][j],soduku[8][j]); break;} } else if(row==7)//基行为第七行// { switch(chose) {case 0:break; case 1: for(j=0;j<9;j++) swap(soduku[7][j],soduku[6][j]); break; case 2: for(j=0;j<9;j++) swap(soduku[7][j],soduku[8][j]); break;} } else//基行为第八行// { switch(chose) {case 0:break; case 1: for(j=0;j<9;j++) swap(soduku[8][j],soduku[6][j]); break; case 2: for(j=0;j<9;j++) swap(soduku[8][j],soduku[7][j]); break;} } ```

测试运行:

sudoku.exe中输入测试数据

生成sudoku.txt,一组数独

重新输入数据

覆盖原先sudoku.txt,生成两组数独


总结:

写完这些已经即将到达项目截至时间,很多需要再做的工作我也已经来不及完善,很抱歉这次的作业纰漏很多,主要原因还在于我自身水平的不足,许多重复的事一遍遍做,去找一个很小或很基础的错误点,浪费了许多时间,编程能力还需要很多磨炼。不过在这段时间也通过找寻各种资料,代码的书写规范等对自己的认知有很大提升,以前觉得不是很理解其内部原理的语句现在都有了比较清晰的认识,我觉得这是我收获很大的地方。在思路上我本有许多解决这个数独问题的方法,然而一放到计算机便开始不知所措。因此我将在接下来的课程里好好学习,努力提升自己的实践水平,也感谢老师、助教们十几天来对我们不辞辛劳的帮助,定不辜负。
posted on 2017-09-10 20:23  WayneYe  阅读(172)  评论(1编辑  收藏  举报