软件工程第三次作业---数独
一.GitHub地址
二.PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) |
---|---|---|
Planning | 计划 | 60 |
Estimate | 估计这个任务需要多少时间 | 2100 |
Development | 开发 | 2100 |
Analysis | 需求分析(包括学新技术) | 480 |
Design Spec | 生成设计文档 | 30 |
Design Review | 设计复审 | 30 |
Coding Standard | 代码规范(为目前的开发指定合适的规范) | 30 |
Design | 具体设计 | 60 |
Coding | 具体编码 | 900 |
Code Review | 代码复审 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 120 |
Reporting | 报告 | 240 |
Test Repor | 测试报告 | 120 |
Size Measurement | 计算工作量 | 30 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 240 |
合计 | 2100 |
三.解题思路
拿到这道题,首先想到的是我长到这么大竟然没有做过一张数独?(小羞耻。。)那么我首先要做的一步就是了解数独规则。
1.了解规则
百度百科简介:
数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。
2.思路
考虑到如果从三宫格开始的话,代码中缺少不对宫的判断,不利于后续阶数的扩展,我想直接从常规九宫格的解题开始。
首先开始阶段.
要先初始化数独盘,在题目已经填写的数字基础上对我们要填的格子进行填充限制,如下图所示:
然后是数字填充阶段.
思路比较常规,回溯法,就是在已有的限制条件下,按顺序尝试1-9在格子中的填充,如果在尝试过程中填写到了数独盘的最后一格,则代表数独已经解出来了(此方法仅限提供的数独盘只有唯一解,如果有多解也只能输出一个),如果到达某格无法继续填充后续数字,需要移除之前放置的数字,然后继续尝试,如下图所示:
四.代码组织
五.关键代码
回溯方法:
/** * 回溯填充方法 * @param row * @param col */ public void backtrack(int row, int col) { if(shudoPan[row][col] == 0) { for(int d = 1; d <= m; d++) { int idx = 0; if(boxRow > 0) { idx = (row / boxRow ) * boxRow + col / boxCol; } if(couldPlace(d, row, col)) { //填充数字,并设置填充限制 boxOccupied[idx][d]++; rowOccupied[row][d]++; colOccupied[col][d]++; shudoPan[row][col] = d; //是否填充到最后一格 if ((col == m-1) && (row == m-1)) { sudokuSolved = true; } else { //当到达最后一列的格子,下一个格子跳转到下一行 if (col == m-1) { backtrack(row + 1, 0); }else { backtrack(row, col + 1); } } if(!sudokuSolved) {//移除填充后无法进行后续填充的数 boxOccupied[idx][d]--; rowOccupied[row][d]--; colOccupied[col][d]--; shudoPan[row][col] = 0; } } } }else { if ((col == m-1) && (row == m-1)) { sudokuSolved = true; } else { //当到达最后一列的格子,下一个格子跳转到下一行 if (col == m-1) { backtrack(row + 1, 0); }else { backtrack(row, col + 1); } } } }
解数独方法---用于初始化和调用回溯方法
/** * 解数独方法 */ public void solveSudoku(int[][] shudoPan) { setBox();//调用设置宫的行列数方法 //System.out.println("boxRow,boxCol:"+boxRow+" "+boxCol); // 初始化某数所在行、列、宫 for (int i = 0; i < m; i++) { for (int k = 0; k < m; k++) { int num = shudoPan[i][k]; if (num != 0) { int d = num; if(boxRow > 0) { int idx = (i / boxRow ) * boxRow + k / boxCol; boxOccupied[idx][d]++; } rowOccupied[i][d]++; colOccupied[k][d]++; } } } backtrack(0, 0); } }
未完。。。。。。