日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

个人项目作业

發布時間:2025/3/15 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 个人项目作业 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.github項目地址

https://github.com/easylliu/gitlearning/tree/master/Sudoku

2.開發時間

PSP2.1Personal Software Process Stages預估耗時(分鐘)實際耗時(分鐘)
Planning計劃3050
Estimate估計這個任務需要多少時間1015
Development開發
Analysis需求分析 (包括學習新技術)120180
Design Spec生成設計文檔
Design Review設計復審 (和同事審核設計文檔)
Coding Standard代碼規范 (為目前的開發制定合適的規范)30
Design具體設計3060
Coding具體編碼120240
Code Review代碼復審60120
Test測試(自我測試,修改代碼,提交修改)120180
Reporting報告
Test Report測試報告3050
Size Measurement計算工作量1020
Postmortem & Process Improvement Plan事后總結, 并提出過程改進計劃3030
合計560975

3.解題思路描述

(1).數獨終局生成

開始在看到題目時想到的是通過初始點一直往后延伸推導,后來想了一會感覺有點復雜;在思考無果后通過上網查找資料了解到生成終局的兩種方法
隨機法,矩陣轉換法;但相比之下感覺矩陣轉換法更加直接,隨機法不確定性加大了難度;而由于第一個數已經確定為9,因此第一行第一列不能參與變換,這樣通過一個數獨變換能產生共計5184種;但我們的要求最多有1000000種,因此想產生200個種子數獨,從8個數中取出四位,共有70種取法,而每種取法又對應三種數字交換方式共計210種符合要求,這樣產生的數獨數就已經超過1000000種符合要求了。

(2).求解數獨

在求解數獨上,開始自己思考是想通過那些已確定的那些數字出發,沿著他們所在行列塊進行推導,但隨后感覺有點困難;通過網上查找感覺方法差不多,相對較為直接的就是回溯法求解了,從最開始點一直遞歸遍歷找到所有存在的可能性,在通過行列和3*3塊的驗證來確定是否符合條件,簡單粗暴,在實現上較為簡單,初始計劃打算就使用了這種方法。

4.設計實現過程

(1).數獨終局生成

根據思路想到,首先產生的一個種子出發,首先通過其行列變換最多產生5184個數獨,如果還不足的話從那70種取法中隨機選出先交換數字產生新的種子數獨,然后再行列變換,如此種種,在一定程度上還可以保證隨機性,直到產生夠所要的數獨數即可結束。通過這種思路構建函數也就清晰起來,在數獨產生的函數中通過種子數獨不斷調用矩陣變換函數,然后可將矩陣變換函數拆解成行變換函數和列變換函數,如此這樣,函數之間的聯系清晰明朗,實現起來目標也很明確??偟脕碚f在這一部分產生4個函數,其直接的關系也是層層調用。通過這樣的分析對函數的作用了解也清晰許多,通過他們直接的聯系和他們的用途設計單元測試就比較輕松了。

(2).求解數獨

通過暴力解法,對從0到81的所有空白進行1到9的選擇,然后判斷適合符合行列和塊的要求,然后遞歸往下延伸,當后面推不出來遞歸返回繼續延伸推導,直到求解出正確的結果結束。
相對來說這種接法也相對較為直接,從0到81,先填入數字,在判斷是否符合行列和塊的要求,然后遞歸向后延伸。如此這樣分析,相對復雜點的就是遞歸的使用,想都來說3個函數足以。主函數調用填空遞歸函數,遞歸函數在填入數字后調用檢查函數判斷是否符合行列塊的要求,如此實現。然后相對來說,對遞歸的單元測試也相對有些麻煩,通過從對函數功能的理解出發,結合和其他函數的聯系設計單元測試會更加全面。

5.性能改進

改進:由于產生數獨和求解數獨的最大值已到達1000000,在輸出到文件和讀取時的效率問題就顯得尤為重要了,因此在這方面花費時間能減就減,因此我就從每次寫入到文件的數量上做出了改進,再往文件里寫入數獨時,我改進到每次寫入兩百個數獨,這樣減少寫入的次數,提高效率。
由圖片中可以看到,調用次數最多的為檢查行列塊的合理性函數,這也是暴力求解產生的負面效果,其次在面對文件操作時話費的時間較多,仍待改善。

6.代碼說明

主要分做兩個部分,一個是產生終局數獨,一個是求解數獨。
這四個為生成終局數獨的四個關鍵函數:
主要就是sudo_create產生種數獨通過調用矩陣變換得到擴展的數獨,矩陣變換由行變換和列變換組成;

void sudo_create(int sudo_count, char sudo[9][10], char changenum_array[70][5]); //生成數獨int matrix_change(int count, int sudo_count, char sudo[9][10], char output[1000000]); //矩陣變換void line_range(int init, int n, char mid_sudo[9][10], char sudo[9][10]); //行交換void column_range(int init, int n, char mid_sudo[9][10], char sudo[9][10]); //列變換

其中最為關鍵一個:產生種子,調用擴展

void sudo_create(int sudo_count, char sudo[9][10], char changenum_array[70][5]) {int index_changenum[70] = { 0 }; //是否隨機到標識符 char sudo_middle[9][10]; //中間種子數獨int randnum = 0, i, j;int count = 0; //已生成的數獨數char a, b, c, d;for (i = 0; i<9; i++) { //初始化strcpy_s(sudo_middle[i], sudo[i]);}count = matrix_change(count, sudo_count, sudo_middle, output); //根據一個種子轉換輸出while (count < sudo_count) {if (count == -1) break;randnum = rand() % 70 + 0;if (index_changenum[randnum] == 0) { //未隨機到a = changenum_array[randnum][0];b = changenum_array[randnum][1];c = changenum_array[randnum][2];d = changenum_array[randnum][3];for (i = 0; i < 9; i++) {for (j = 0; j < 9; j++) {if (sudo[i][j] == a) {sudo_middle[i][j] = b;}else if (sudo[i][j] == b) {sudo_middle[i][j] = a;}else if (sudo[i][j] == c) {sudo_middle[i][j] = d;}else if (sudo[i][j] == d) {sudo_middle[i][j] = c;}elsesudo_middle[i][j] = sudo[i][j];}}count = matrix_change(count, sudo_count, sudo_middle, output);if (count == -1) break;for (i = 0; i < 9; i++) {for (j = 0; j < 9; j++) {if (sudo[i][j] == a) {sudo_middle[i][j] = c;}else if (sudo[i][j] == b) {sudo_middle[i][j] = d;}else if (sudo[i][j] == c) {sudo_middle[i][j] = a;}else if (sudo[i][j] == d) {sudo_middle[i][j] = b;}elsesudo_middle[i][j] = sudo[i][j];}}count = matrix_change(count, sudo_count, sudo_middle, output);if (count == -1) break;for (i = 0; i < 9; i++) {for (j = 0; j < 9; j++) {if (sudo[i][j] == a) {sudo_middle[i][j] = d;}else if (sudo[i][j] == b) {sudo_middle[i][j] = c;}else if (sudo[i][j] == c) {sudo_middle[i][j] = b;}else if (sudo[i][j] == d) {sudo_middle[i][j] = a;}elsesudo_middle[i][j] = sudo[i][j];}}count = matrix_change(count, sudo_count, sudo_middle, output);if (count == -1) break;}}//cout << output; }

這三個為求解數獨的主要函數:
主要就是solve_sudo函數調用填空進行遞歸,填入一個數后就判斷其合理性

int solve_sudo(char output[], int count);//求解數獨 bool solve_blank(int sudo_num);//填空 bool matrix_judge(int line, int column, int choose);//判斷合理性

關鍵一個函數:遞歸調用,逐步展開

//填數 bool solve_blank(int sudo_num) {int line, column, i;line = sudo_num / 9;column = sudo_num % 9;if (sudo_num >= 81)return true;if (sudo1[line][column] == 0) {for (i = 1; i <= 9; i++) {sudo1[line][column] = i;if (matrix_judge(line, column, i)) {if (solve_blank(sudo_num + 1)) return true;}sudo1[line][column] = 0;}}else {return solve_blank(sudo_num + 1);}return false; }

轉載于:https://www.cnblogs.com/easyliu/p/7596316.html

總結

以上是生活随笔為你收集整理的个人项目作业的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。