[2017BUAA軟工]我的項目

軟工我的項目git



1、Github項目地址

https://github.com/Lydia-yang/2017BUAA-SoftwareEngineeringgithub


2、解題思路

在剛開始拿到題目的時候,關於生成數獨終局,個人思路是能夠隨機生成數而後選擇適合的數填滿便可獲得,後來經過上網查找一些數獨生成算法,發現能夠經過必定的順序來減小工做量,好比將1到9個數字依次隨機填入3*3的宮格里,或者記錄每次每次嘗試的數避免重複,還有初始化對角線的3個3*3的宮格,或者依次填入1到9等。最後選定了將1到9個數值依次填入3*3的宮格里這種算法,也就是這篇博客的算法。
將數獨分爲9小塊,將1-9按照必定序列填寫1-9小塊,好比先將1填入1號小塊,再填入2號小塊,知道填完9號小塊,再填2與1同樣,遍歷全部數便可獲得一個生成數獨。
至於解數獨,思路與生成數獨差很少,也是回溯,可是是對於每個沒有填的位置試全部可能的數字。算法


3、設計實現過程

實現個人算法,首先,要有一個存儲九宮格的二位數組,出於考慮,我建立了一個數獨類,這個類裏有相應的行列及3*3小塊的重複檢查,以及插入和刪除,因爲我解決數獨和生產數獨用的是不一樣的方法來插入數字的(一個是肯定數字選位置,一個肯定位置選數字),因此有兩種插入的方法,而後就是打印數獨的方法。
在處理命令行中,有判斷-c後面接的是不是正整數的函數,一樣,生成數獨和解數獨都有各自的函數,解數獨是經過文件讀入的,所以也設定了一個處理文件讀入函數,在後面優化的過程當中,又新增了輸出到文件的函數,單元測試主要是將produce和solve這兩個函數測試了一遍。下圖是函數類之間的關係:數組


4、性能改進

一開始生成數獨時,幾分鐘都沒出結果,後來通過性能分析,以下圖:
函數


發現是輸出佔了大多數時間,後來作了優化,將輸出結果先輸出到一個字符數組裏,再所有一塊兒輸出,最後的性能分析以下:
post


5、代碼說明

下面這段代碼是用來解數獨的,其中輸入表明的含義爲:性能

  • sudoku sudo, 存儲待解的數獨
  • int x[], 全部爲空位置的x值
  • int y[], 全部爲空位置的y值
  • int total, 空位子的總數
  • int & count, 用來記錄目前已經填了多少空位子
  • char *str, 字符數組用來儲存須要打印的數獨
  • int &count_s, 用來標記字符數組的元素個數

對於每一次執行,將這個空位子插入數字,並標記已經試過的數字,最後完成時輸出,每次回溯時都清空當前位置。單元測試

void solve(sudoku sudo, int x[], int y[],int total, int & count, char *str, int &count_s) {
    int marked[9] = { 0 };//用來標記數字是否已經選過
    int new_count = count;
    while (true) {

        int now = sudo.insert(1, x[new_count], y[new_count], marked);//在空位子插入數字

        if (now < 0) return;
        else marked[now-1] = 1;

        if (new_count == total - 1) {//最後一個
            sudo.printsudoku(str, count_s);//打印數獨
            return;
        }
        count = new_count + 1;
        solve(sudo, x, y, total, count, str, count_s);//下一個
        if (count == total - 1) return;
        sudo.del(1, x[new_count], y[new_count]);
    }
    
}



下面這段代碼是用來生成數獨的,其中輸入表明的含義爲:測試

  • int total, 最終須要生成數獨的總個數
  • int nums[], 1-9的序列用來規定遍歷數的順序
  • int block_num, 標記當前的3*3的塊號
  • int & count_total, 用來標記當前已經生成的數獨個數
  • int count_nums, 用來標記當前對於nums的元素位置
  • sudoku s, 當前已經填好一些空的數獨
  • char *str, 字符數組用來儲存須要打印的數獨
  • int &count_s, 用來標記字符數組的元素個數

對於每一次執行,將這個數字插入當前3*3小塊空的位置,並標記已經試過的位置,最後完成時輸出,每次回溯時都清空當前位置。優化

void produce(int total, int nums[], int block_num, int & count_total, int count_nums, sudoku s, char *str, int &count_s) {
    int marked[9] = { 0 };//標記已經試過的位置
    int new_block_num, new_count_nums;
    
    while (true) {
        new_block_num = block_num + 1;
        new_count_nums = count_nums;
    
        int now = s.insert(nums[new_count_nums], new_block_num, marked);
    
        if (now <0) return;
        else marked[now] = 1;

        if (new_block_num == 9) {
            if (new_count_nums < 8) {
                new_count_nums=count_nums+1;
                new_block_num = 0;
            }
            else {//填寫至最後一個
                count_total++;
                s.printsudoku(str, count_s);//打印數獨
                s.del(0, new_block_num, now);
                return;
            }
        }
        produce(total, nums, new_block_num, count_total, new_count_nums, s, str, count_s);
        if (count_total == total) return;
        s.del(0, new_block_num, now);
    }
}


6、PSP

Psp personal software progress stages 預估耗時 實際耗時
planning 計劃 20 30
estimate 估計這個任務須要多少時間 10 10
development 開發 480 600
analysis 需求分析 10 10
design spec 生成設計文檔 30 35
design review 設計複審 0 0
coding standard 代碼規範 10 15
design 具體設計 60 70
coding 具體編碼 240 300
code review 代碼複審 120 130
test 測試 240 300
reporting 報告 20 18
test report 測試報告 20 10
size measuring 計算工做量 5 3
postmortem & process improvement plan 過後總結,提出過程改進計劃 20 20
合計 1285 1551
相關文章
相關標籤/搜索