軟件工程實踐2019第三次作業


Github項目地址:https://github.com/huarangmeng/031702142


PSP表格如下:

PSP2.1 Personal Software Process Stages 預估耗時(分鍾) 實際耗時(分鍾)
Planning 計划 20 20
Estimate 估計這個任務需要多少時間 20 20
Development 開發 340 300
Analysis 需求分析(包括學習新技術) 40 60
Design Spec 生成設計文檔 20 10
Design Review 設計復審 10 10
Coding Standard 代碼規范(為目前的開發制定合適的規范) 10 5
Design 具體設計 30 30
Coding 具體編碼 160 120
Code Review 代碼復審 30 45
Test 測試(自我測試,修改代碼,提交修改) 50 60
Reporting 報告 30 30
Test Report 測試報告 10 10
Size Measurement 計算工作量 10 10
Postmortem & Process Improvement Plan 事后總結,並提出改進計划 10 10
合計 390 350

思路歷程

  1. 之前沒有玩過數獨,只能查詢數獨的解法,看了一部分“唯一解”法,發現不太能理解,之后尋找到了回溯解法。
  2. 嘗試先對九階標准數獨進行求解,完成主體思路
    • 對數獨數組matrix[][] 從左至右,從上至下依次遍歷,matrix[][]==0,代表可填寫部分
    • 對可填寫部分,進行填數檢測 check(row,line,num) ,如果通過,則martrix[row][line]=num, 進入下一個位置 backTrace(row,line+1),最關鍵點,要將matrix[row][line]=0,恢復原狀,如果下一次填數失敗,要回溯重新試下一個數字
    • check(row,line,num)函數,需要檢測當前行列宮均與Num不同,否則返回false
  3. 主體思路結束后,發現需要使用命令行輸入輸出文件,不會,嗯,就是不會。開始學,從JAVA輸入輸出文件開始還行,命令行參數獲取有點懵逼,靠着@衡與墨 助教在微信群里的代碼才運行了。
  4. 之后才對3-9階進行區分,唯一需要改動的地方就是check()函數
    • 將3,5,7階分為一類,即只需要檢測行與列是否相同
    • 4,9階分為一類,即行、列宮數均為sqrt(階)
    • 6單獨,8單獨,需要檢測宮的方法與其他不同

函數關聯


代碼改進

原本代碼只針對存在解的數獨進行求解,不存在報錯機制。
改進增加這一部分,增加是否存在解判斷 flag ,flag初始化為false,若有解 flag =true.
代碼如下:

//Judging Solvability
        if(flag) {
            System.out.println("Success!!!!");
        } else{
           System.out.println("The test is insoluble!!!!!!");
           printf();
        }

代碼讀取文件部分:

File file = new File(inputFileName);

        int x[][] = new int[9][9];
        int row = 0;
        int line = 0;
        String str = "";
        if(! file.exists()){
            System.out.println("對不起,不包含指定路徑的文件");
        }else{
            try{
                FileReader fr = new FileReader(file);

                char[] data = new char[23];
                int length = 0;

                while((length = fr.read(data)) >0){
                    str = new String(data,0,length);
                    for(int j = 0; j < str.length(); j++){
                        if(str.charAt(j) >47 && str.charAt(j)<58){
                            char c = str.charAt(j);
                            x[row][line++] = Character.getNumericValue(c);
                            if(line == phraseWordNum){
                                //Line feed
                                row++;
                                line = 0;
                            }
                        }
                        if(row == phraseWordNum){
                            //A disk is well stored
                            Lib lib = new Lib(x,phraseWordNum,outputFileName);
                            lib.Initialization();
                            row = 0;
                            line = 0;
                        }
                    }
                }
                //Close the read stream
                fr.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }

回溯解法主體:

 public void backTrace(int i, int j){
        //End of Arrival Output
        if(i == (rank-1) && j == rank){
            printf();
            flag = true;
            return;
        }

        //Arrive at the end of the column, wrap
        if(j == rank){
            i++;
            j = 0;
        }

        //If the lattice is empty, the judgement is entered.
        if(matrix[i][j] == 0){
            for(int k = 1; k <= rank; k++){
                //Check whether the requirements are met
                if(check(i,j,k)){
                    //Give the value K to the lattice
                    matrix[i][j] = k;
                    backTrace(i,j+1);
                    //Initialize the lattice
                    matrix[i][j] = 0;
                }
            }
        }else {
            backTrace(i,j+1);
        }
    }

檢測所填數字合理性代碼:

private boolean check(int row, int line, int k){
        //Query whether rows or columns have duplicate numbers
        for(int i = 0 ;i < rank; i++){
            if(matrix[row][i] == k || matrix[i][line] == k)
                return  false;
        }

        //Query if there are duplicate numbers in the Nine-palace grid
        if(rank == 4 || rank == 9){
            int gong = (int)sqrt(rank);
            int _row = row / gong;
            int _line = line / gong;
            for(int i = 0; i < gong; i++){
                for(int j = 0; j < gong ;j++){
                    if(matrix[_row*gong + i][_line*gong + j] == k)
                        return false;
                }
            }
        }else if(rank == 6){
            int _row = row / 2;
            int _line = line / 3;
            for(int i = 0; i < 2; i++){
                for(int j = 0; j < 3 ;j++){
                    if(matrix[_row*2 + i][_line*3 + j] == k)
                        return false;
                }
            }
        }else if(rank == 8){
            int _row = row / 4;
            int _line = line / 2;
            for(int i = 0; i < 4; i++){
                for(int j = 0; j < 2 ;j++){
                    if(matrix[_row*4 + i][_line*2 + j] == k)
                        return false;
                }
            }
        }

        return true;
    }

單元測試樣例:

  1. 四階數獨

  2. 五階數獨

  3. 六階數獨

  4. 七階數獨

  5. 八階數獨

  6. 九階數獨

  7. 運行截圖


性能分析

byte[], String ,類運行的最多,遠大於其他,應該是參數輸入,文件讀取數字存為矩陣時使用過多
(JProfiler 不會用,參數看不太懂)

心路歷程與收獲

最開始心中完全對數獨的陌生,尋找了很多關於數獨解法的文章,看得頭疼。
最大的收獲應該是JAVA的文件輸入輸出,以及命令行運行JAVA項目吧,之前一直沒有機會嘗試過,這次終於接觸了。
github上傳代碼,自己之前就試過一次,失敗了,這次陰差陽錯成功了?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM