1. 程式人生 > >【數獨個人專案】3. 設計階段

【數獨個人專案】3. 設計階段

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

日期:2018-12-15

3. 設計階段

        設計分結構化設計方法,和麵向物件的設計方法。結構化程式寫太多了,這次打算試試面向物件的。而且結構化程式總感覺程式碼多了的話就賊長,整體結構容易弄不清楚。因為還沒講後面的面向物件設計,所以自己稍微看了些後面章節內容,結合第3章的軟體設計基礎,自己嘗試做了下設計階段:

一、概要設計

     包括了:(1)體系結構設計  (2)介面設計  (3)資料設計

 (1)體系結構設計

      主要就是確定類、和類間關係。

      根據模組化設計的思想,分成了三個類:

① ConsoleParameter類,代表控制檯輸入的引數,包含了引數處理的功能

② SudokuSolution類,數獨解類(就是沒有0的數獨),能生成指定數量數獨題,用於生成數獨題

③ SudokuPuzzle類,數獨題類(有0的數獨),可以生成生成數獨解。

// 這裡我之前想錯了。。寫完前兩個類了才覺得好像名字有點不對勁。。之前把②③名字弄反了,實際上生成數獨應該是SudokuSolution類裡的方法,因為相當於生成沒有0的數獨解(但是這個感覺和這個數獨解類關係不太大。。只有一個函式)。。而第三個SudukuPuzzle類對應求解數獨功能,是SudukuPuzzle.solve()才對。。

      也想過要不要把SudokuSolution和SudokuPuzzle合併成一個類,就代表一個數獨的意思,然後空著的地方用0表示。但是這兩種還是有不同的,比如帶0的可以解,不帶0的沒法解。要區分的話也可以加個成員變數區分,不過感覺還是分開好點,可能對以後可能的擴充套件有利些。。所以就分成了這3個類。

類間關係:

     SudokuSolution和SudokuPuzzle類都能接受ConsoleParameter類,來獲取控制檯引數,並進行相應動作

                                   

(2)介面設計   

        沒有使用者介面(附加題做的時候再設計) 

(3)資料設計

       資料庫、資料檔案、全域性資料結構的定義,好像用不上

 

二、詳細設計

      還是先做一個最初版本的詳細設計吧,感覺之後可能在實現過程中還會更改這個詳細設計

      主要就是對類裡面函式和變數的定義

 

      ConsoleParamter類: 

用來獲取控制檯引數,並處理,判斷錯誤,得到兩個引數,之後可以用於生成數獨或求解數獨時的引數                                  

詳細說明:(直接寫在.h檔案裡了)

//
//用來獲取控制檯引數,並處理,判斷錯誤,得到兩個引數
//之後可以用於生成數獨或求解數獨時的引數
//
class ConsoleParameter {
public:
  // 根據argc和argv,初始化所有成員變數
  ConsoleParameter(int argc, char *argv[]);
  // 獲取-c或者-s指令,失敗返回'\0'
  char GetCommand();
  // 獲取-c或-s後面的引數,失敗返回"\0"
  string GetOperationcode();
private:
  // 向控制檯顯示錯誤資訊
  void OutputError(string errorstring);
  // argc,控制檯引數個數
  int argc;
  // argv,多個控制檯引數陣列的首地址
  char **argv;
  //存放-c或者-s,或者空
  char command;
  //存放-c或者-s後面的引數
  string operationcode;
};

其中,ExtractCommand()函式流程圖:

ExtractOperationCode()函式流程圖

 

 

SudokuSolution類:

接收ConsoleParameter物件,並生成數獨,輸出到檔案

詳細說明:

//
//接收ConsoleParameter物件,並生成數獨,輸出到檔案
//
class SudokuSolution {
public:
  //用ConsoleParameter類的parameter來初始化物件
  SudokuSolution(ConsoleParameter parameter);
  //生成parameter引數中數量的物件,並存至檔案
  void Generate();
private:
  //生成25個基礎數獨(不能通過1到9的排列使之相同的,算不同的數獨)
  //被Generate()呼叫
  void GenerateBasicPuzzle();
  //用於初始化物件
  ConsoleParameter parameter;
  //存放25個基礎數獨,下標從0開始
  int basic_puzzle[25][10][10];
};

Generate()函式流程圖:

 

 

SudokuPuzzle類:

接收ConsoleParameter物件,並求解檔案中數獨,輸出到sudoku_answers檔案

詳細說明:

//
//接收ConsoleParameter物件,並求解檔案中數獨,輸出到sudoku_answers檔案
//
class SudokuPuzzle {
public:
  //用ConsoleParameter類的引數初始化物件(無預設建構函式),並初始化所有資料成員
  SudokuPuzzle(ConsoleParameter parameter);
  //用於關閉兩個檔案
  ~SudokuPuzzle();
  //呼叫dfs_solve(),解檔案中的所有數獨題,並輸出到sudoku_answers檔案
  int SolveAll();
private:
  //用於根據puzzle[10][10]解一個數獨,把解存至solution[90]
  void dfs_solve(int depth);
  //用於構造物件
  ConsoleParameter parameter;
  //存數獨題,0代表空格,1~9行和1~9列為有效資料
  int puzzle[10][10];
  //數獨題是否符合格式要求
  bool islegal;
  //數獨題中的0個數
  int number_of_blanks;
  //數獨題中每個0的位置,從0下標開始
  int position_of_blanks[90][2];
  //存數獨的解,從0下標開始
  int solution[90];
  //數獨是否有解
  bool solvable;
  //輸入檔案的指標
  FILE *finput;
  //輸出檔案的指標
  FILE *foutput;
  //表示讀了幾個題進來,純粹是為了輸出到檔案的時候區分第一個
  int count;
};

SolveAll()流程圖: