天天看點

軟體工程實踐2017第二次作業-----個人項目實戰之數獨

軟體工程實踐2017第二次作業-----個人項目實戰之數獨

最後一門考試2017.9.16

github位址:https://github.com/ssuo/shudu####

題目位址:http://www.cnblogs.com/vertextao/p/7472376.html####

解題思路####

題目要求有1000000中不同數組,在首位數字确定的情況下,第一行還剩下8個空位,将剩下的8個數字随機排列組合,就會産生8!=40320種不同的可能性。是以第一行數相同的情況下還要能生成25個不同數獨才能達到個數要求。補考九号才結束,之前一直沒做,臨時想不出方法來,隻好用固定套路,根據第一行數生成完整的數獨,是以我的程式所能做到的最大不同個數為40320個。

設計實作####

數獨的要求是每一行,每一列,每一宮的數字都不能重複,當第一行的數由1~9排列着組合,剩下的行可以由第一行平移得到(平移格數n取值不重複且不為0),這樣就能保證所有行數字不重複,所有列數字不重複。為了使每個宮(3行*3列)的數字也不重複,每三行内的平移數依次相差3,如【第二行平移3,第三行平移6】【第四行平移2,第五行平移5,第六行平移8】【第七行平移1,第八行平移4,第九行平移7】。

第一行進行19排列組合時花特别久時間,最開始的想法是使用回溯法,生成取值範圍内的随機數放入,與之前生成的相比較,如果發現重複,則撤回重新生成,但這種做法生成重複資料的機率大,回溯次數多,生成效率太低,很有可能超過題目所要求的1000個60s。生成效率低的原因,主要是每個數都隻需要出現一次,但用随機數卻會重複出現,要提高生成效率,就要解決這個問題。再回歸最初的目的,是要将19排列合,那麼,不如就直接這麼做?建立數組b[8],存放{1,3,4,5,6,7,8,9},生成随機數,将數組b對應位置的數放入數獨第一行,被選擇中的數字之後的數依次向前挪一位将該數覆寫掉,用srand%(9-i)來限制随機數大小,這樣每生成一次随機數取走一個b數組元素,随機數的取值範圍都将減小1直至減到0.

代碼說明####

代碼分為兩個部分,一是函數shudu,主要功能是生成1~9的排列組合後按統一模式暴力求解出數獨并輸出;二是主函數部分,功能是輸入生成個數n後使用for循環多次調用shudu函數。

生成随機數的代碼

int i,j,x,m;
 int a[9][9]={{2}};             //a[9][9]為數獨數組 
 int b[8]={1,3,4,5,6,7,8,9};    //b[8]存放除1~9(除去首位數字2),後續從b中取出數放入a,防止重複出現 
 for(i=0;i<8;i++)           // 用i做for循環共做8次,填滿第一行剩下的8個數 
 {x=rand()%(8-i);           // 限制随機數的取值範圍[0,8-i)
  a[0][i+1]=b[x];           //将随機數指向的b中的元素放入a; 
  for(j=x;j<8-i;j++ ) 
  b[j]=b[j+1];   }          //将b中被取出的元素後的 數依次向前挪一位,覆寫住被取出的數,避免重複。随着随機數取值範圍每次減1,最後一位數下次将不會被取到,避免重複。 
           

生成數獨的算法

for(m=0;m<9;m++)         
  {
  a[1][m]=a[0][(m+3)%9] ;   //根據已有的第一行,按照固定規則生成數獨。 
  a[2][m]=a[0][(m+6)%9] ;
  a[3][m]=a[0][(m+1)%9] ;
  a[4][m]=a[0][(m+4)%9] ;
  a[5][m]=a[0][(m+7)%9] ;
  a[6][m]=a[0][(m+2)%9] ;
  a[7][m]=a[0][(m+5)%9] ;
  a[8][m]=a[0][(m+8)%9] ;
 }	
           

測試運作####

軟體工程實踐2017第二次作業-----個人項目實戰之數獨

總結####

這次實驗做的并不好,沒有達成規定要求個數。剛開始想的太複雜,循環多了,被繞的有點亂。也曾嘗試将曆史首行組合存入一個大小c【40320】【8】的數組中,每次生成的随機數組和都與之比較,但是回溯一直實作的很差,邏輯混亂,最後放棄了。在作業中,也學到了許多新内容,如用srand生成個随機數,生成的時候要把時間種子放在主函數裡,如果放在自己寫的函數裡,産生的随機數排列會一模一樣,這個錯改了很久沒找到,最後在小可愛舍友的幫助下才發現。這次作業也讓我深刻感受到自己對語言很不熟悉,思路有了之後,敲代碼敲了特别久,寫的磕磕碰碰的,語言不熟悉,一直在翻書,感覺自己就像《建構之法》書中寫的一邊翻書一邊做手術的醫生,到頭來還是有錯誤,也改很久。翻一翻自己的代碼,隻有五六十行,邏輯也很簡單卻寫了那麼久,感覺還是要每天寫一個小時左右代碼讓自己有個手感。很不常寫代碼,雖然功能不完善,但寫出來了還是很開心,會繼續努力的!

PSP表格####

PSP2.1 Personal Software Process Stages 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃 30
· Estimate · 估計這個任務需要多少時間
Development 開發
· Analysis · 需求分析 (包括學習新技術) 40 60
· Design Spec · 生成設計文檔
· Design Review · 設計複審 (和同僚稽核設計文檔)
· Coding Standard · 代碼規範 (為目前的開發制定合适的規範) 20
· Design · 具體設計 50
· Coding · 具體編碼 180 300
· Code Review · 代碼複審 90
· Test · 測試(自我測試,修改代碼,送出修改)
Reporting 報告
· Test Report · 測試報告
· Size Measurement · 計算工作量
· Postmortem & Process Improvement Plan · 事後總結, 并提出過程改進計劃
合計 780 760

對泛泛而談和執行力的了解####

執行力

執行力,我認為應該是有效率的完成既定的目标或任務的能力。按時交作業交任務是一種執行力,按計劃吃飯睡覺也是一種執行力。接到一個新任務、或者一個新階段開始(比如開學)的時候,我會有很多雄心壯志,給自己立無數Flag。最後熬夜壓deadline,期末通宵複習,被啪啪打臉,這大概就是執行力不足的問題。對我來說,自己能發現的原因有四個:一是三分鐘熱度,剛開始的時候很激情很認真,一開始做别的事情,注意力就整個分散開了,等下次想起最初的任務,已不知今夕何夕。每學期開學第一周,課前預習,課後複習,中午看書,晚上做作業,整個人都散發着勤勞的光。過完第一個周末 ,發現一部好劇,打開一個好玩的遊戲,學霸日程表就走遠了。二是沒有做好時間規劃,定好每個小階段的任務。經過大學前兩年的慘痛經曆,我深刻認識到學霸課程表是不适合我的,相信也有很多人不能一直堅持學習少娛樂。但并不是所有人都需要最後熬夜趕任務。平時不想做,拖着拖着,總覺得截止日期還遠着呢遠着呢,猝不及防有一天它就到了。是以我覺得可以自己将任務分成很多很多小階段,弄個截止日,一次做一點,做完了就去耍,不會太累太煩太多然後不想動。細化計劃表,可能會好些。(這一點就是泛泛而談了,我還沒試過。嗯,下次作業出來了,計劃表還沒弄,難道要先為定計劃表這件事再弄個表我才會想起來去做它orz)。三是期望過高,沒有認清自己的能力。總想着這個不大好那個不大好等我再弄弄搞個大事情然後發現嗨呀這個好難那個也超出能力範圍十萬八千裡,眼高手低的結果就是最基礎的都做不好。四是興趣。這個聽起來很虛,但我覺得是真的有的,喜歡的話,沒事兒自己就會想去做,不喜歡的東西才會需要弄計劃表那一大堆東西(囧。。)

泛泛而談

泛泛而談,是喊口号吧,亂立flag,還有不給事情定一個準确的時間去做。我說我要考駕照,天知道是明天還是十年後呢......