1. 程式人生 > >【數獨個人專案】關鍵程式碼說明

【數獨個人專案】關鍵程式碼說明

github地址:https://github.com/Duuang/Project-Sudoku

關鍵程式碼說明

目錄

一、main.cpp

int main()

二、ConsoleParameter類:ConsoleParameter.cpp

建構函式

ExtractCommand()

ExtractOperationCode()

三、SudokuSolution類: SudokuSolution.cpp

GenerateBasicPuzzle() 

四、SudokuPuzzle類,SudokuPuzzle.cpp

SolveAll()

GetNextPuzzle()

SolveCurrentPuzzle()

dfs_solve(int depth)


一、main.cpp

int main()

先看main()函式,先用Consolepatameter類物件,獲取控制檯引數,然後判斷引數是合法的-c/合法的-s/非法的引數

如果合法-c,則新建SudokuSolution類物件,呼叫Generate生成數獨

如果合法-s,則新建SudokuPuzzle類物件,呼叫SolveAll解數獨,並輸出可解的和無解的個數(還考慮了檔案是否成功開啟)

二、ConsoleParameter類:ConsoleParameter.cpp

建構函式

ExtractCommand()

讀取控制檯的引數,並判斷第一個引數是-c還是-s還是其他,更新成員變數command的值

ExtractOperationCode()

若是-c,則先判斷字串長度是否>8,然後判斷是否字串全由數字組成,最後用sscanf_s()將字串轉換為數字,更新operationcode_c,返回0,否則返回-1

若是-s,則更新operationcode_s,返回0

其他值,返回-1

三、SudokuSolution類: SudokuSolution.cpp

GenerateBasicPuzzle() 

生成25個基礎數獨(經過1~9排列也不能重複的那種),為了之後的8!×25 的100萬個數獨做準備

第一行固定123456789

註釋的數獨即為第一個基礎數獨,在這個基礎上,第2行中的456內和789內可以進行全排列,即為不同的數獨

所以把這6*6=36種排列,用兩個sequence456[6][3]表示了,方便之後呼叫

剩下的就是按照規則生成數獨了,按後三行為前3行右移1列生成即可

 

Generate()

用來生成指定數量的數獨

先呼叫GenerateBasicPuzzle(),然後生成一個1~9的序列,對每一個序列,將basic puzzle中的值根據1~9序列替換,即得到了新數獨。

然後將數獨寫入outputstring緩衝區,一個數獨的資料全部寫入緩衝區後,將緩衝區資料寫入到檔案

寫緩衝區的過程是用的指標指示當前位置,一個個字元寫,放棄了用strcat()函式

變數定義:

根據序列替換數獨:

向緩衝區寫入數獨資料:

寫入檔案:

 

四、SudokuPuzzle類,SudokuPuzzle.cpp

SolveAll()

反覆呼叫GetNextPuzzle()和SolveCurrentPuzzle()求解

GetNextPuzzle()

從檔案中讀取下一個數獨題,成功返回0,失敗-1

SolveCurrentPuzzle()

呼叫dfs_solve(),解當前puzzle中存放的數獨

在解數獨前,先判斷,已經給的數獨題中有沒有本來就衝突的地方

數獨題目本身不矛盾,則解數獨,並輸出到檔案

...

dfs_solve(int depth)

呼叫時depth取1,回溯搜尋所有解

涉及回溯的幾行關鍵程式碼:

solution[depth - 1] = i;  //記錄當前節點解
puzzle[position_of_blanks[depth - 1][0]][position_of_blanks[depth - 1][1]] = i;//更改puzzle
dfs_solve(depth + 1);   //遞歸回溯
puzzle[position_of_blanks[depth - 1][0]][position_of_blanks[depth - 1][1]] = 0;//還原puzzle

函式程式碼及註釋說明: