軟體工程實踐2017第二次作業

wujunyi發表於2017-09-10

Githubsudoku

專案相關要求

利用程式隨機構造出N個已解答的數獨棋盤 。

輸入

數獨棋盤題目個數N(N在0和1000000之間)

輸出

隨機生成N個不重複的已解答完畢的數獨棋盤,並輸出到sudoku.txt中。在生成數獨矩陣時,左上角的第一個數為:(學號後兩位相加)% 9 + 1。

思路與程式碼

一暑假沒碰過程式碼的我,在暑假結束前一週看到了這個作業題目,腦子裡想起來的就是大一的時候敲得八皇后和馬遍歷的題目,比較類似,都是關於遞迴回溯的演算法。大致思路就是給每個格子試不同的數,找到符合條件的填下,如果不可以的就回到前一個,換一個數再試試,不行再回溯,於是有了下面的程式碼:

int count=0;//統計輸出了多少數獨 
void sudoku(int i,int j)
{
    for(int x=1;x<=9;x++)//給每個格子都試9個數 
    {
        if(check(i,j,x)==1)//如果可以 
        {
            board[i][j]=x;//就賦值 
            if(i==8&&j==8)//如果填滿了,就輸出 
            {
                print();
                count++;
                if(count>=N) exit(-1);
                return;//輸出還沒到N個,就繼續返回試其他數 
            }
            if(j==8)//如果當前位置是某一行最後一個,就跳到下一行第一個 
            {
                sudoku(i+1,0);
            }
            else//不然就跳到下一個 
            {
                sudoku(i,j+1);
            }
        }
    }
    board[i][j]=0;
    return ;//這個格子沒有一個數符合,就返回上一個格子 
} 

下面是判斷這個格子是否可以這個數的check函式:

int check(int row,int col,int num)//判斷是否能放 
{
    for(int i=0;i<9;i++)//判斷列有沒相同的 
    {
        if(board[i][col]==num)return 0;
    }
    for(int j=0;j<9;j++)//判斷行有沒相同的 
    {
        if(board[row][j]==num)return 0;
    }
    int x=row/3,y=col/3;
    x=3*x;
    y=3*y;
    for(int i=0;i<3;i++)//檢查小九宮格 
    {
        for(int j=0;j<3;j++)
        {
            if(board[x+i][y+j]==num)return 0;
        }
    }
    return 1;
}

生成100W個數獨大概要52秒左右
生成的結果輸出到sudoku.txt
軟體工程實踐2017第二次作業

效能分析

用VS自帶的效能分析器進行分析,測試的生成的數獨為10W個:
軟體工程實踐2017第二次作業
軟體工程實踐2017第二次作業
軟體工程實踐2017第二次作業

PSP

PSP2.1 Personal Software Process Stages 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃
· Estimate · 估計這個任務需要多少時間 800 1000
Development 開發
· Analysis · 需求分析 (包括學習新技術) 120 130
· Design Spec · 生成設計文件 0 0
· Design Review · 設計複審 (和同事稽核設計文件) 0 0
· Coding Standard · 程式碼規範 (為目前的開發制定合適的規範) 60 60
· Design · 具體設計 90 120
· Coding · 具體編碼 270 330
· Code Review · 程式碼複審 60 60
· Test · 測試(自我測試,修改程式碼,提交修改) 90 90
Reporting 報告
· Test Report · 測試報告 120 110
· Size Measurement · 計算工作量 30 30
· Postmortem & Process Improvement Plan · 事後總結, 並提出過程改進計劃 60 60
合計 900 1050

反思與總結

這次程式碼雖然思路簡單,但是遞迴實現起來理解的意思確實很複雜,因為好久沒敲這類題,已經忘記了當時如何理解遞迴。經過一番痛苦掙扎(把之前八皇后和馬遍歷的程式碼翻出來溫習了一下),總算有點想明白,遞迴就是層層遞迴,就像一顆樹一樣,從根節點遞迴到子節點,子節點行不通,return會根節點從旁路走。其實我還想了一種方法(其實是網上看到的),就是把九宮格分成九個獨立的宮,因為每個宮都會有1-9九個數字,所以就按數字來放,比如先把1排進每個宮,接著放2,以此類推,而且在放頭尾兩個數的時候完全不用回溯,我覺得應該會減少程式碼執行復雜度,我也嘗試的敲了下,奈何學藝不精沒有成功,於是就選了這種普通的方法。這很反映了我現在的程式碼能力很弱,需要加強咯。

相關文章