軟體工程基礎 個人專案 數獨(5)

2021-10-02 06:55:24 字數 4175 閱讀 6101

1.生成終局時,加入2,3;4,5,6;7,8,9行交換的情況以增加不重複的終局數量

原情況下,第2~9行為第一行左移固定數量得到,移動量由陣列move陣列儲存,行交換的實現只需交換對應的移動量。

將move陣列設為二維陣列,每一行對應乙個移動量的情況,共72行。

將原**中move的使用方式:

num[i]

[j]= num[0]

[(j + move[i -1]

)%9]

;

轉化為:

num[i]

[j]= num[0]

[(j + move[moven]

[i -1]

)%9]

;moven++

;moven %=72

;

其中moven為新設定類的整形私有變數。

2.生成多個終局的實現

從使用者處獲取生成數量m

對生成單個數獨方法(newone函式)進行m次呼叫

呼叫時傳遞引數:生成終局所需全排列數對應的序號x

x的修改應在此排列數所能生成的72種全部輸出後

故將newone函式設為int型別,當執行結束時moven若為0則返回0,此時x加1

保證x在範圍0~40319中

3.時間複雜度的優化

原**中排列數儲存在硬碟檔案中,每次從中取出所需排列數都需要呼叫一次fopen和fclose函式,此外向檔案中寫終局時,我所採用的方法同樣是在每次寫入時呼叫一次fopen與fclose函式,最終在測試時1分鐘的時間大約只能生成5000個左右的終局,而在分析報告中顯示與開關檔案相關的操作佔據了百分之九十多的時間。

對此的問題的優化:

排列數以全域性變數的形式儲存在主存中,以空間換時間

寫入檔案僅開啟和關閉一次,將檔案指標作為引數在各函式間傳遞

最終相關**

//排列數的生成

int pailieshu[

40320][

8];void

pailie()

;int n =0;

dowhile

(std:

:next_permutation

(a, a +8)

);return;}

//寫檔案方法

void

write

(file *fp)

else

for(

int i =

0; i <

9; i++

)fprintf

(fp,

"\n");

}}//生成單個終局方法

intnewone

(int n, file *fp)

//主函式中的呼叫

intmain

(int argc,

char

*ar**)

fclose

(fp);}

}

概要講述

設定類的私有資料:

num[9][9]儲存數獨資料資訊

left[9][9]每乙個資料的後9位儲存該資料的可取值

trynum[9][9]儲存需填項嘗試取的值

judge判斷解數獨是否結束,用於遞迴呼叫繼續或返回的標誌。

設定私有方法:

writesolve因引入了trynum陣列,設定新的寫檔案方法

bittonum通過對傳入的int值後九位進行處理轉化為對應1~9值

change對傳入數獨位置所在行、列、九宮格進行處理,使這些位置的left值與傳入的值互斥

restore為change函式的逆操作,將傳入值加到獲取位置的left值中

standard通過對每乙個有確定值或嘗試值的位置呼叫change函式使left值保持正確

solve函式遞迴呼叫解數獨

設定公有方法:

solveshudu讀取資料,呼叫solve函式解數獨,寫入資料

詳細實現

writesolve函式:對傳入的檔案進行格式化的寫操作,若num不為零則寫入num值,否則寫入trynum值

void

writesolve

(file *fp)

else

for(

int i =

0; i <

9; i++

)else

}fprintf

(fp,

"\n");

}}

bittonum函式:對傳入值進行switch判斷,返回相應值

int

bittonum

(int bit)

}

change函式:迴圈遍歷相應位置,所得left值與傳入值的非相與

void

change

(int m,

int n,

int bit)

for(

int i = m /3*

3; i <

(m /3+

1)*3

; i++

)for

(int j = n /3*

3; j <

(n /3+

1)*3

; j++

) left[i]

[j]&

=~bit;

}

restore函式:迴圈遍歷相應位置,所得left值與傳入值相或

void

restore

(int m,

int n,

int bit)

for(

int i = m /3*

3; i <

(m /3+

1)*3

; i++

)for

(int j = n /3*

3; j <

(n /3+

1)*3

; j++

) left[i]

[j]|

= bit;

}

standard函式:迴圈遍歷所有位置,若有確定值或嘗試值,則呼叫change函式,傳入值為位置與該位置的確定值或嘗試值

在這裡插入**片void

standard()

}

solve函式:

傳入引數為當前處理的位置,大小為0~81。

若為81則解數獨結束,設定judge為1,返回。

若該位置已有確定值,則引數加一呼叫下一層遞迴。

否則,對於該位置的left值進行操作。

取該位置的left值為leftnow。

對leftnow所表示的可取值進行遍歷。

設定trynum值為可取值,呼叫change函式。

遞迴呼叫下一位置。

遞迴結束時若judge仍為0,則將trynum置為0,呼叫呼叫restore函式,標準化left陣列。否則解數獨結束,直接返回。

void

solve

(int position)

int m = position /9;

int n = position %9;

int bit, leftnow;

if(num[m]

[n]>0)

solve

(position +1)

;else

for(leftnow = left[m]

[n]; leftnow; leftnow &

=(leftnow -1)

)}

solveshudu函式:對於要讀的檔案以81為週期進行讀取,直到讀到設定的結束識別符號-1為止,通過讀取值對num,trynum,left陣列進行初始化,呼叫函式實現對陣列的標準化和解數獨的功能。最後向目標檔案中寫入內容。

void

solveshudu

(file *fpr, file *fpw)

standard()

;solve(0

);writesolve

(fpw);}

}

main函式中內容:以讀的方式開啟數獨檔案,向檔案末尾寫入識別符號-1。關檔案。以唯讀開啟數獨檔案,以只寫開啟目標檔案,呼叫解數獨函式,最後關檔案。

軟體工程基礎 個人專案 數獨

任務 實現乙個能夠生成數獨局並且能求解數獨問題的控制台程式。1 github 2 時間耗費 psd2.1 personnal software process stages 預估耗時 分鐘 實際耗時 分鐘 planning 計畫40 40.estimate 估計這個任務需要多長時間 developm...

軟體工程個人專案 數獨

專案位址 github倉庫 psp 2.1 personal software process stages 預計耗時 分鐘 實際耗時 分鐘 planning 計畫50 60estimate 估計這個任務需要多久 300360 development 開發240 270analysis 需求分析 2...

軟體工程基礎 個人專案 數獨(2)

第乙個數字為 9 6 9 1 7 其餘八個數字為1 6,8,9的隨機排序,共8!種 1 從網上查閱資料得知,如果從第二行開始,每行為第一行左移3 6 1 4 7 2 5 8的結果,則生成的結果為合格的數獨終局 2 隨意交換數獨的1 2 3行,4 5 6行,7 8 9行,或者交換1 2 3列,4 5 ...