软件工程第三次作业---数独

≡放荡痞女 提交于 2019-11-30 11:29:10

软件工程第三次作业---数独


一.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);
      }
}

未完。。。。。。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!