Github 項目地址:https://github.com/zjwml4581792/Software-engineeringhtml
第一次的真軟工實踐做業就是這種題目,想一想還有點小激動,終於又要敲代碼啦。看着本身如今的編程的「紙飛機階段」,想完成,仍是等待~並心懷但願吧!git
先看題目。github
我是題目算法
度娘說:數獨(百度百科)編程
數獨(Sudoku,Crosswords)是源自18世紀瑞士的一種數學遊戲。是一種運用紙、筆進行演算的邏輯遊戲。玩家須要根據9×9盤面上的已知數字,推理出全部剩餘空格的數字,並知足每一行、每一列、每個粗線宮(3*3)內的數字均含1-9,不重複。
數獨盤面是個九宮,每一宮又分爲九個小格。在這八十一格中給出必定的已知數字和解題條件,利用邏輯和推理,在其餘的空格上填入1-9的數字。使1-9每一個數字在每一行、每一列和每一宮中都只出現一次,因此又稱「九宮格」。數組
看到的第一眼就是,這個題目跟程序語言綜合設計的那個馬踏棋盤和N皇后問題好像啊,一百度,果真三個題目常常綁定出現,用的不少都是回溯。markdown
然而本身並非很懂回溯,因而本身找了找不是回溯算法的大神寫的博客。惋惜大神寫的算法我基本看不懂。dom
各類各樣的問題顯示了本身的功力不足,函數何時開始回溯啊,調用函數本身的那行到底寫在哪裏啊,比較好的想法究竟是哪種啊……編程語言
本身什麼都不懂,直接開始寫是不現實的,因而開始問學長。編輯器
先問了個直系老鄉研究生谷歌(仍是微軟)大佬,說「數獨問題用 dancing links 算法來寫」,,一百度好像dancing links 真的很厲害的樣子,可是好像這麼複雜的雙向鏈表我真的寫不出來。
本身百度「數獨生成算法」吧,看看前輩們都用的是什麼算法,用的思想是否是太超前本身能不能接受。
找到的比較看得懂本身印象比較深有啓發的:
因而本身嘗試了生成 9 個隨機數組一行一行填進矩陣,一個一個數字地填,一個九宮填一個九宮地填等等各類方法。
最後採用了 0~9 輪流逐行地填的方法,即從1開始填,從第0行填到第8行,1填完了填2,直到9。
事實證實採用了某種方法若是理論沒問題必定要堅持到底,若是不斷地嘗試別的方法真的沒有效率,就跟《構建之法》裏的畫扇面同樣,過早想着優化,都還沒完成必要功能和需求就不要考慮太多。先寫出來了再說。
從 【1】 中汲取了「按九宮格從左到右從上到下,從 1-9 輪流填,填完了再填下一個數」的思想並改造;
從 【2】 中獲得了先把無依賴的主對角線上的三個小九宮填滿,再填其餘九宮的思想(可是最終並無用到這方法)
從 【3】 中瞭解了怎麼寫回溯算法。
本身的搜索能力暴漲,code能力小幅升,熬夜能力MAX,泡麪技巧infinite
。拖延症已病入膏肓
習慣看到題目就先建立個類,這個數獨類至少須要有構造函數、析構函數、建立矩陣、打印矩陣四個函數,數獨矩陣二維數組,而後根據須要添加了初始化函數,判斷函數,文件變量等,詳見代碼註釋。
class Sudo { public: Sudo(int id); //構造函數 ~Sudo(); //析構函數 void createSudoku(int id);//建立數獨矩陣 void print(); //打印 void init(); //初始化 private: ofstream outfile; //輸出文件 int arr[9][9]; //數獨矩陣數組 int flag; //是否把每一行的該數都填好的標誌 int firstNumber; //題目要求的跟學號有關的數 bool isRight(int row, int column, int num);//判斷row行column列是否能夠填num vector<int> randVector(); //生成隨機數組 void fillNumber(int num, int row); //從row開始每一行開始填充num void clean(int i); //填充失敗,把i數清除,從新填過 };
看到題目想到要寫的第一個函數就是判斷函數,在寫的時候先分別寫了行判斷、列判斷、九宮判斷三個函數,以及調用三個函數的isRight原始版,後來整合到一塊兒了就成了下面的新生版。因爲是逐行填充的,只須要檢查列和九宮符不符合要求便可。
後來思考若是按照每一個九宮來填數,只須要判斷行和列會不會更快,可是按九宮來填數,填數就麻煩了,根據第一個博客裏的來看,應該按九宮來會快些。
bool Sudo::isRight(int row, int column, int num) {//判斷所在位置是否可行 for (int i = 0; i < 9; i++) {//檢查列可不能夠 if (arr[i][column] == num) return false; } int northwestX = row / 3 * 3;//算小九宮的第一個位置 int northwestY = column / 3 * 3; //檢查九宮 for (int i = 0; i < 3; i++)//橫向檢查 { for (int j = 0; j < 3; j++)//豎向檢查 { if (arr[i + northwestX][j + northwestY] == num) return false; } } return true; }
若是是普通的隨機數的生成的話,必定會生成重複的隨機數,因而生成一個0-8的隨機數組,須要用的時候遍歷數組。
如何生成隨機數組的方法是網上找的,C++下數組隨機shuffle的方法解
vector<int> Sudo::randVector()//生成隨機數組 { vector<int> result; result.clear(); for (int i = 0; i < 9; i++) result.push_back(i); random_shuffle(result.begin(), result.end()); return result; }
建立數獨,先填要求的數,再從1-9填,無法填了就退回上一個數從新填過。
void Sudo::createSudoku(int hhhhhh)//建立數獨 { fillNumber(firstNumber, 1); //先把要求的那個數填進去 for (int i = 1; i < 9; i++) //從1到9開始填充 { if (i == firstNumber)//若是是要求的那個數 continue; //則跳過 fillNumber(i, 0); //逐行填充數i if (flag) //若是填充好了 flag = false; //將flag置false,準備下一個數 else //若是沒填好 { clean(i);//把上一個數清掉,重填 i -= 2; //先-2,待會+1,從上一個數從新開始 } } for (int i = 0; i < 9; i++)//發現上面填完了以後9是空的 { for (int j = 0; j < 9; j++)//就寫一個循環把9補上 { if (arr[i][j] == 0) arr[i][j] = 9; } } }
最重要的填數,不過這個回溯挺最簡單,從第0行開始填num。
void Sudo::fillNumber(int num, int row)//從row行開始填充num { if (row > 8) //若是0-8行都填完了 { flag = true; //將填好的標誌flag置true return; //返回 } vector<int>temp = randVector(); //生成隨機數組, for (int i = 0; i < 9; i++) //從數組第一個數開始測試第row行temp[i]列行不行 { if (arr[row][temp.at(i)] != 0)//若是這個位置填過了 continue; //跳過這列 if (isRight(row, temp.at(i), num))//若是這個位置能夠 { arr[row][temp.at(i)] = num; //填上去 fillNumber(num, row + 1); //填下一個行 if (flag) //若是填好了 return; //返回 arr[row][temp.at(i)] = 0;//若是這個數這行填不成,把上一行該數置0,換temp下一個數試試 } } }
程序運行截圖
圖中的運行時間是測試用的,暴露了本身這個算法有待改進,很大的改進。
效能分析
摘要
調用關係樹
從中能夠看出,主要是填充數函數佔了最多時間,所以算法自己有很大的改進空間,好比判斷函數,從周同窗的做業中,能夠看出本身和TA的差距;也能夠把fillNumber函數的返回值設爲Bool,也能少個變量flag。另外vector系列也是比較耗時的,用的很少的話,本身寫個隨機生成數組的函數,藉助庫函數是比較耗時。
百毒百科說
執行力是指有效利用資源、保質保量達成目標的能力,指的是貫徹戰略意圖,完成預約目標的操做能力。是把企業戰略、規劃、目標轉化成爲效益、成果的關鍵。
執行力包含完成任務的意願,完成任務的能力,完成任務的程度。對我的而言執行力就是辦事能力;對團隊而言執行力就是戰鬥力;對企業而言執行力就是經營能力。
簡單來講就是行動力。
個人理解就是,在拿到任務以後,用本身最專一的熱情去完成這件事,最及時地完成,對待任務當機立斷、雷厲風行,以秋風掃落葉之勢,腳踏實地、貫徹始終,知行合一。
其實上面的這段話就是泛泛而談,沒有什麼針對性,就好比創新創業比賽上,上臺的不少學生都是侃侃而談,對於本身的產品自己的介紹並很少,就算是客觀的場面話,也沒有講到針對於自身產品最大的痛點。
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | 20 | 10 |
· Estimate | · 估計這個任務須要多少時間 | 20 | 10 |
Development | 開發 | 1775 | 1820 |
· Analysis | · 需求分析 (包括學習新技術) | 60 | 73 |
· Design Spec | · 生成設計文檔 | 30 | 沒有作 |
· Design Review | · 設計複審 (和同事審覈設計文檔) | 30 | 單幹,不須要 |
· Coding Standard | · 代碼規範 (爲目前的開發制定合適的規範) | 15 | 7 |
· Design | · 具體設計 | 120 | 120 |
· Coding | · 具體編碼 | 1440 | 1560 |
· Code Review | · 代碼複審 | 60 | 20 |
· Test | · 測試(自我測試,修改代碼,提交修改) | 20 | 40 |
Reporting | 報告 | 155 | 78 |
· Test Report | · 測試報告 | 30 | 30 |
· Size Measurement | · 計算工做量 | 15 | 15 |
· Postmortem & Process Improvement Plan | · 過後總結, 並提出過程改進計劃 | 120 | 33 |
合計 | 1960 | 1908 |
第 N 周 | 新增代碼(行) | 累計代碼(行) | 學習耗時(小時) | 累計學習耗時(小時) | 重要成長 |
---|---|---|---|---|---|
第 0 周 | 192 | 192 | 31 | 31 | 複習C++語法、學習VS2017操做、瞭解回溯 |