github連結:
15061085石奇川:https://github.com/qwellk/project1/tree/product2/WindowsFormsApp1
15061080劉亞洲: https://github.com/qwellk/project1/tree/product2/WindowsFormsApp1
psp時間估計:
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
Planning | 計劃 | 30 | 40 |
· Estimate | · 估計這個任務需要多少時間 | 15 | |
Development | 開發 | ||
· Analysis | · 需求分析 (包括學習新技術) | 60 | |
· Design Spec | · 生成設計文檔 | ||
· Design Review | · 設計複審 (和同僚稽核設計文檔) | ||
· Coding Standard | · 代碼規範 (為目前的開發制定合适的規範) | ||
· Design | · 具體設計 | 80 | |
· Coding | · 具體編碼 | 240 | 480 |
· Code Review | · 代碼複審 | 120 | |
· Test | · 測試(自我測試,修改代碼,送出修改) | 180 | |
Reporting | 報告 | ||
· Test Report | · 測試報告 | ||
· Size Measurement | · 計算工作量 | 10 | 20 |
· Postmortem & Process Improvement Plan | · 事後總結, 并提出過程改進計劃 | 30 | |
合計 | 715 |
看教科書和其它資料中關于Information Hiding, Interface Design, Loose Coupling的章節,說明你們在結對程式設計中是如何利用這些方法對接口進行設計的。
information Hiding :資訊隐藏是一種重要的軟體開發手段,它與對象的封裝與子產品化密切相關。在這次結對程式設計中,我們把計算核心和輸入輸出處理全部封裝在core子產品中,通過接口将core子產品和外界聯系起來,但具體的實作和錯誤處理都被隐藏在子產品中。 Interface Design:由于和結對隊友所用語言不同,我們之間的對接至關重要,通過數獨計算和求解功能設計接口,然後通過gui功能增加簡化接口,使得計算子產品和ui子產品的對接更加容易;然後通過前面的規範化程式設計使得我們對程式設計的格式規範也有了統一意見,以此設計接口; Loose Coupling:改變或者供應者或者服務的問題不能影響到使用者----或者使用者的問題不應影響到供應者或者服務。相對來說,這次的計算子產品和ui子產品松耦合就不錯,通過子產品的封裝減少通過接口連接配接的各個子產品的影響,例如對core子產品和ui子產品的對接,當計算核心出現問題時,在core子產品内部錯誤處理,減少對ui的影響,以此實作接口設計。
計算子產品接口的設計與實作過程:
設計包括代碼如何組織,比如會有幾個類,幾個函數,他們之間關系如何,關鍵函數是否需要畫出流程圖?說明你的算法的關鍵(不必列出源代碼),以及獨到之處。首先,通過思考分析計算子產品所包括的範圍,有些是計算資料的(生成數獨,求解數獨),有些是控制輸入的(檔案讀入,控制台讀入),有些是資料可視化的(檔案輸出),是以主要子產品接口就是實作數獨的生成,求解,檔案讀出,檔案寫入和控制台讀入等等幾個大塊。然後相對來說生成數獨和求解數獨又可以分成幾個小塊,檔案讀出,檔案寫入和控制台讀入等等可以分别用一個函數實作;就生成來說,數獨難易度的劃分(-m),挖空數量的多少(-r),是否唯一(-u)等等就可以具體到函數;如此分析下來,計算子產品接口的大體架構就已經出來了。我感覺我算法的關鍵就是實作數獨生成函數這個大塊,相對來說就是實作那三個接口:生成一定數量數獨終盤,生成一定數量區分難易度的數獨,生成挖去一定數量空的數獨;将三個函數實作,剩下的就是小塊了。獨到之處并沒有感覺特别有特别之處,正常實作吧。在數獨的難易度劃分上,我根據挖空數來區分,因為相對來說在随機分布的情況下挖空數量多的相對更加困難。然後簡單的挖空數範圍[11,29),中等[29,47),困難[47,65);對于每種難度的數獨在範圍内随機生成要挖空數量,然後随機挖去那麼多數量的空,由于初始17個空就已确定唯一解,是以最終還會是唯一解。
讀有關UML的内容:
https://en.wikipedia.org/wiki/Unified_Modeling_Language。畫出UML圖顯示計算子產品部分各個實體之間的關系(畫一個圖即可)。
相對來說,因為我是所有的計算函數實作全部用一個core類子產品搞定,是以各實體關系也在core子產品内部表現,關系基本表現在計算與輸入輸出的聯系。
計算子產品接口部分的性能改進:
結對項目-數獨程式擴充

在計算子產品上,因為生成數獨的方法我們是利用已有數獨生成的,是以主要性能改進花在了求解數獨上,由開始的純暴力周遊回溯在面對17提示數獨求解上花費時間過久,随後改進通過每次找最少可選集回溯比原來純暴力解決提高了不少,但由于沒有精準覆寫的問題導緻解一些困難數獨花費時間很久,仍有待提高。如圖時求解200多個17提示數獨性能分析,由于性能上面沒有知道具體函數,通過函數實作可知消耗最大的是回溯函數deal().
看Design by Contract, Code Contract的内容,描述這些做法的優缺點, 說明你是如何把它們融入結對作業中的。
契約式設計就是按照某種規定對一些資料等做出約定,如果超出約定,程式将不再運作,例如要求輸入的參數必須滿足某種條件;優點是保證了調用者和被調用者雙方的品質,缺點就是在生産中無法自由地把這些契約disable; 在我們的結對作業中,對于子產品間使用了契約的思想,一人負責core子產品,一份負責gui,保證雙方地位的平等。調用者的傳入參數必須是正确的,否則責任不在被調用者,而在傳入者。
計算子產品部分單元測試展示。
generate()
測試三個generate接口,分别對應-c,-m,-r;
通過調用函數生成數獨,對最終生成的數獨進行有效性判斷和重複性判斷。
```
TEST_METHOD(generate1)
{
// TODO: 在此輸入測試代碼
core core0;
int result[100][81];
int sudo[9][9];
core0.generate(100, result);
for (int i = 0; i < 100; i++)
{
memcpy(sudo, result[i], sizeof(sudo));
Assert::AreEqual(core0.isvalid(sudo), true);
}
Assert::AreEqual(core0.isunique(100, result), true);
}
TEST_METHOD(generate2)
{
// TODO: 在此輸入測試代碼
core core0;
int result[100][81];
int sudo[9][9];
for (int i = 1; i <= 3; i++)
{
core0.generate(100, i, result);
for (int k = 0; k < 100; k++)
{
memcpy(sudo, result[k], sizeof(sudo));
Assert::AreEqual(core0.isvalid(sudo), true);
int count = 0;
for (int j = 0; j < 81; j++)
{
if (result[k][j] == 0) count++;
}
if (i == 1)
{
Assert::AreEqual(count >= 11 && count<29, true);
}
if (i == 2)
{
Assert::AreEqual(count >= 29 && count <47, true);
}
if (i == 3)
{
Assert::AreEqual(count >= 47 && count <65, true);
}
}
}
}
TEST_METHOD(generate3)
{
// TODO: 在此輸入測試代碼
core core0;
int result[100][81];
int sudo[9][9];
int lower = 22, upper = 45;
core0.generate(100, lower, upper, false, result);
for (int i = 0; i < 100; i++)
{
memcpy(sudo, result[i], sizeof(sudo));
Assert::AreEqual(core0.isvalid(sudo), true);
int count = 0;
for (int j = 0; j < 81; j++)
{
if (result[i][j] == 0) count++;
}
Assert::AreEqual(count >= lower&&count <= upper, true);
}
core0.generate(100, lower, upper, true, result);
for (int i = 0; i < 100; i++)
{
memcpy(sudo, result[i], sizeof(sudo));
Assert::AreEqual(core0.isvalid(sudo), true);
int count = 0;
for (int j = 0; j < 81; j++)
{
if (result[i][j] == 0) count++;
}
Assert::AreEqual(count >= lower&&count <= upper, true);
}
}
```
結對項目-數獨程式擴充
計算子產品部分異常處理說明
對各種輸入錯誤的測試,定義6種類型的輸入錯誤,每種分别測試一個看傳回錯誤是否一緻 包括,-c num錯誤,-s 檔案錯誤,-n num錯誤,-m mode錯誤,-r num錯誤和-r -m同時出現錯誤
TEST_METHOD(input_deal)
{
// TODO: 在此輸入測試代碼
core core0;
char *s_c0[2] = { "-c","dgh" };//-1 -C num
char *s_c1[2] = { "-c","1000001" };//-1
char *s_s[2] = { "-s","fhdfjh" };//-2 -S file
char *s_n[4] = { "-n","10001","-m","1" };//-3 -n num
char *s_m[4] = { "-n","1","-m","4" };//-4 -m num
char *s_r[4] = { "-n","1","-r","20~56" };//-5 -r num
char *s_rm[6] = { "-n","1","-r","20~56","-m","1" }; //-6 -m -r
Assert::AreEqual(core0.input_deal(2, s_c0), -1);
Assert::AreEqual(core0.input_deal(2, s_c1), -1);
Assert::AreEqual(core0.input_deal(2, s_s), -2);
Assert::AreEqual(core0.input_deal(4, s_n), -3);
Assert::AreEqual(core0.input_deal(4, s_m), -4);
// Assert::AreEqual(core0.input_deal(4, s_r), -5);
// Assert::AreEqual(core0.input_deal(6, s_rm), -6);
}
UI子產品的設計:
分别實作4個功能:計時功能、難度選擇功能、提示功能、數獨遊戲功能
計時功能:用單獨的label和timer實作,美國一段時間改變label的值。
難度選擇功能:設定全局變量:難度,當選擇難度時,對label進行操作并對這個全局變量進行修改,當以後點選開始時,就可以調用特定的函數進行根據不同難度生成數獨了。
提示功能:能夠根據生成的矩陣找到答案矩陣,并将滑鼠上次停留的位置上的數獨答案顯示出來。
數獨遊戲功能:初始化時會根據選擇難度的不同生成數獨,并用藍色标記這些格子,且不能修改,在某個格子填過數後,格子顔色變為綠色,標明格子時,格子顔色變為黃色,并每次填數後對填的數進行判斷操作,并判斷熟讀是否已經完全填對。
UI的接口實作
結對項目-數獨程式擴充
隻調用了兩個接口,分别對應生成數獨和求解數獨,生成兩個具體的generate和solve函數。
團隊合作照片
說明結對程式設計的優點和缺點。結對的每一個人的優點和缺點在哪裡 (要列出至少三個優點和一個缺點)。
結對程式設計的優點:
能夠互相督促,加快進度,減少一方的缺點。
處理困難問題的速度變快。
增強互相的責任心,能夠對項目的品質有保證。
結對程式設計的缺點:
有的時候會造成一方等一方的情況,大大減速進度。
有點不适應,或者說造成寫代碼的一方分心。
優點:有責任心,對時間的把握的好,寫代碼快。
缺點:沒有