个人github项目连接:https://github.com/54zhazhahui/131700114css
实现一个命令行程序,不妨称之为Sudoku。git
数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出必定的已知数字和解题条件,利用逻辑和推理,在其余的空格上填入1-9的数字。使1-9每一个数字在每一行、每一列和每一宫中都只出现一次,因此又称“九宫格”。github
如今咱们想一步一步来,完成从三宫格到九宫格的进阶;完成三宫格和其余博客任务,就算过了初级考核,其余的算升级。具体各阶规则以下:函数
三宫格:盘面是33。使1-3每一个数字在每一行、每一列中都只出现一次,不考虑宫; 四宫格:盘面是22四个宫,每一宫又分为22四个小格。使1-4每一个数字在每一行、每一列和每一宫中都只出现一次; 五宫格:盘面是55。使1-5每一个数字在每一行、每一列中都只出现一次,不考虑宫; 六宫格:盘面是23六个宫,每一宫又分为32六个小格。使1-6每一个数字在每一行、每一列和每一宫中都只出现一次; 七宫格:盘面是77。使1-7每一个数字在每一行、每一列中都只出现一次,不考虑宫; 八宫格:盘面是42八个宫,每一宫又分为24八个小格。使1-8每一个数字在每一行、每一列和每一宫中都只出现一次; 九宫格:盘面是33九个宫,每一宫又分为3*3九个小格。使1-9每一个数字在每一行、每一列和每一宫中都只出现一次; 性能
<style type="text/css"> .tg {border-collapse:collapse;border-spacing:0;} .tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;} .tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;} .tg .tg-0pky{border-color:inherit;text-align:left;vertical-align:top} </style>学习
<table class="tg"> <tr> <th class="tg-0pky">PSP2.1</th> <th class="tg-0pky">Personal Software Process Stages</th> <th class="tg-0pky">预估耗时(分钟)</th> <th class="tg-0pky">实际耗时(分钟)</th> </tr> <tr> <td class="tg-0pky">Planning</td> <td class="tg-0pky">计划</td> <td class="tg-0pky">10分钟</td> <td class="tg-0pky">5分钟</td> </tr> <tr> <td class="tg-0pky">Estimate</td> <td class="tg-0pky">估计这个任务须要多少时间</td> <td class="tg-0pky">36小时</td> <td class="tg-0pky">48小时</td> </tr> <tr> <td class="tg-0pky">Development</td> <td class="tg-0pky">开发</td> <td class="tg-0pky">4小时</td> <td class="tg-0pky">6小时</td> </tr> <tr> <td class="tg-0pky">Analysis</td> <td class="tg-0pky">需求分析 (包括学习新技术)</td> <td class="tg-0pky">2小时</td> <td class="tg-0pky">6小时</td> </tr> <tr> <td class="tg-0pky">Design Spec</td> <td class="tg-0pky">生成设计文档</td> <td class="tg-0pky">2小时</td> <td class="tg-0pky">4小时</td> </tr> <tr> <td class="tg-0pky">Design Review</td> <td class="tg-0pky">设计复审</td> <td class="tg-0pky">2小时</td> <td class="tg-0pky">1小时</td> </tr> <tr> <td class="tg-0pky">Coding Standard</td> <td class="tg-0pky">代码规范 (为目前的开发制定合适的规范)</td> <td class="tg-0pky">1小时</td> <td class="tg-0pky">4小时</td> </tr> <tr> <td class="tg-0pky">Design</td> <td class="tg-0pky">具体设计</td> <td class="tg-0pky">1小时</td> <td class="tg-0pky">1小时</td> </tr> <tr> <td class="tg-0pky">Coding</td> <td class="tg-0pky">具体编码</td> <td class="tg-0pky">2小时</td> <td class="tg-0pky">1小时</td> </tr> <tr> <td class="tg-0pky">Code Review</td> <td class="tg-0pky">代码复审</td> <td class="tg-0pky">2小时</td> <td class="tg-0pky">30分钟</td> </tr> <tr> <td class="tg-0pky">Test</td> <td class="tg-0pky">测试(自我测试,修改代码,提交修改)</td> <td class="tg-0pky">2小时</td> <td class="tg-0pky">8小时</td> </tr> <tr> <td class="tg-0pky">Reporting</td> <td class="tg-0pky">报告</td> <td class="tg-0pky">1小时</td> <td class="tg-0pky">1小时</td> </tr> <tr> <td class="tg-0pky">Test Repor</td> <td class="tg-0pky">测试报告</td> <td class="tg-0pky">30分钟</td> <td class="tg-0pky">10分钟</td> </tr> <tr> <td class="tg-0pky">Size Measurement</td> <td class="tg-0pky">计算工做量</td> <td class="tg-0pky">10分钟</td> <td class="tg-0pky">20分钟</td> </tr> <tr> <td class="tg-0pky">Postmortem & Process Improvement Plan</td> <td class="tg-0pky">过后总结, 并提出过程改进计划</td> <td class="tg-0pky">30分钟</td> <td class="tg-0pky">45分钟</td> </tr> <tr> <td class="tg-0pky">合计</td> <td class="tg-0pky"></td> <td class="tg-0pky">19.2小时</td> <td class="tg-0pky">33.2小时</td> </tr> </table> # 解题思路 看完题目要求以后,我就本身动手画了了一个九宫格。在作题目的过程当中,我慢慢体会到解题的思路。基本上就是,排查一个空可能填的数,当只剩下一种可能的时候就能够填了。可是有时候可能有两种或者更多的可能值,这就须要咱们去试探了。由于题目比较简单,思路也很快就出来了。用正常的搜索+递归,就能把题目要求的惟一解(标准)数独算出来。比较难的就须要咱们去试探了。据说有道史上最难的数独,只有最聪明的人才能解出来,但愿个人程序能够算出来。 # 源代码 先看一下主函数吧。这个文件输入输出我整整搞了两天,最后发现两个问题。一个是vs2017创建项目的时候,应该选择创建Windows控制台应用程序。还有一个问题就是input.txt和output.txt写成input.txt.txt和output.txt.txt。讲真的,我自闭了,心态被搞崩了。看了好多资料,用了无数的方法都不行。最后能够实现的那一刻,内心舒服了好多。 **主函数** ``` int main(int argc, char** argv) { int i, j; ifstream ifp; ofstream ofp; m = atoi(argv[2]);//宫阶数 n = atoi(argv[4]);//盘面数 choosemn(); ifp.open(argv[6]); if (!ifp.is_open())//判断文件是否成功打开 cout << "文件打开失败" << endl; ofp.open(argv[8]); if (!ofp.is_open()) cout << "文件打开失败" << endl; while (n > 0) { resetmay(); for (i = 0; i < m; i++)//输入数独盘面 { for (j = 0; j < m; j++) { ifp >> a[i][j].num; } } inputsign(); scansign();测试
for (i = 0; i < m; i++)//输出解出的数独 { for (j = 0; j < m; j++) { if (j < (m - 1)) ofp << a[i][j].num << " "; else ofp << a[i][j].num; } ofp << endl; } ofp << endl; n--; } return 0;
}ui
**结构体定义数据**
struct number //每一个数的结构体 sa { int sign;//定义一个标记,表示这个数还有几种可能的取值 int maybe[9] = { 1,2,3,4,5,6,7,8,9 };//定义num的可能取值 int num;//定义num的肯定值 }a[9][9];编码
### 核心代码 核心代码是两个函数,一个**惟一值函数**,一个**排查函数**。 **惟一值函数**
void onlyone(int i, int j)//这个函数是把惟一解求出来; { for (int k = 0; k < line; k++) //惟一解在maybe里面 { if (a[i][j].maybe[k] != 0) { a[i][j].num = a[i][j].maybe[k]; a[i][j].maybe[k] = 0; a[i][j].sign = 0; del(i, j); break; } } }spa
**排查函数**
void deletehl(int i, int j) { for (int k = 0; k < line; k++)//把同一行的sign减一,把maybe的可能取值变零 { if (a[i][k].maybe[a[i][j].num - 1] != 0)//若是不等0,说明还没去掉这个可能; //等0的话,说明前面已经去掉了,sign不用再减一了; { a[i][k].maybe[a[i][j].num - 1] = 0; a[i][k].sign--; if (a[i][k].sign == 1) { onlyone(i, k); } }//把同一行的相同可能值删掉
if (a[k][j].maybe[a[i][j].num - 1] != 0) { a[k][j].maybe[a[i][j].num - 1] = 0; a[k][j].sign--; if (a[k][j].sign == 1) { onlyone(k, j); } }//把同一列的相同可能值删掉 }
}
void deletegong(int i, int j) { //宫的首地址计算 //x,y;这个宫的首个数的地址为a[x][y] ; int x, y; x = (i / gongrow) * gongrow; y = (j / gongline) * gongline; for (int gi = 0; gi < gongrow; gi++) for (int gj = 0; gj < gongline; gj++)//把同一宫的sign减一,把maybe【num】的取值变零 { if (a[gi + x][gj + y].maybe[a[i][j].num - 1] != 0) { a[gi + x][gj + y].maybe[a[i][j].num - 1] = 0; a[gi + x][gj + y].sign--; if (a[gi + x][gj + y].sign == 1) { onlyone(gi + x, gj + y); } } } }
惟一值函数就是当一个空的可能性只有一种的时候,就能够填入了。 排查函数就是把同一列或同一行或同一宫的,已存在的值的可能性排除掉。 ### 数据测试 下面是5和6宫格的数据测试结果   ### 性能分析    ###总结 此次做业花了我很长的时间,可是也是收获满满。好比说学会了在github上传代码,还有vs2017的使用,还有文件输入输出!!!在写做业的过程当中遇到了不少困难,不少bug,不少意想不到的问题,当是经过本身的努力,一步步攻克过来,最后成功解决。我以为这个过程才是最重要的,也是我此次最大的收获。