第二週作業 - 黃金點結對程式設計總結
第一次結對程式設計的專案是黃金點遊戲的比賽,我們從討論到實現只用了大約不到一天的時間,而且全程都是兩人一起程式設計,全部程式碼都在get_numbers.py
一個檔案中,因此沒有使用 github 來管理程式碼。
PSP 表格
我覺得由於這次專案的結構簡單,程式碼量也不大, PSP 表格並不是很適用,但是,我還是給一個簡單的 PSP 表格,因為我們事先也預估過專案所需的時間。
PSP 各個階段 | 預估的時間 |
---|---|
計劃: 討論我們的大致策略 | 2h |
開發:實現我們的策略,給出最初版本 V1.0 | 2h |
測試:測試V1.0, 並根據測試結果提出改進想法 | 1h |
開發:實現V2.0 | 1h |
測試:測試V2.0 | 1h |
介面設計
我們的程式碼結構非常簡單,基本沒有涉及需要設計介面的部分,我們所有的資料都以 numpy
進行傳遞。
演算法實現和UML圖
首先, UML 圖並不適用於我們的專案,我們沒有使用物件,只把一些很簡單的基礎功能放到函式中,並在主函式中呼叫這些基礎的功能,下面介紹一下演算法的實現:
首先,演算法開始我們會從標準輸入流讀取比賽的歷史資料 history
, 並且判斷這一輪是否需要搗亂操作:判斷標準是最後兩輪的黃金點的差值是否小於 GATE * 前 N 輪黃金點歷史差值的平均。如果是,那麼採取搗亂策略,反之就不採取搗亂策略。這裡的 GATE 是一個固定的引數,我們調整為 0.3。
接下來,根據選擇的策略返回我們輸出的兩個值。如果不採取搗亂策略,我們會以隨機的方式輸出兩個值,但是,隨機的範圍並不是隨便設定的,而是根據上一輪黃金點的值來判斷的。如果採取搗亂策略,我們會提交一個較大的值 (>=80) 和另一個擬合值,較大值是所有超過80的歷史資料中的最小值(防止自己扣分),擬合值是上一輪黃金點的值加上 Lambda * (較大值 - 上一輪黃金點),這裡, Lambda 是一個動態調整的引數。
最後,演算法會根據歷史的反饋,來動態調整引數。一個需要調整的引數是搗亂策略時的 Lambda,如果發現在歷史資料中,搗亂人數較多,導致我們演算法的擬合值小於那一輪的黃金點,那麼演算法就會增加 Lambda ,反之,當擬合值比黃金點大太多時,演算法就會減小 Lambda。另一個引數是不搗亂時,隨機點的範圍,如果檢測到歷史資料中搗亂的隊伍較多,就會使得一個隨機點的範圍上調,反之就不做調整。
Design by contract
這個做法的思想是精確的限定介面和資料,保證程式執行和軟體的質量。我們的程式碼中,各個函式的功能都非常明確,資料介面也很簡單,因此函式的介面本身就已經十分精確。
程式程式碼和設計規範
程式的邏輯我們是事先討論好的,程式碼的一些規範(比如變數命名,註釋一類)會在結對程式設計的時候實時指出並改進。由於程式的比較簡單,函式功能也很明確,除了一些很明顯的異常處理(檔案讀取異常),沒有發生其它異常的情況。
介面模組
我們的程式沒有介面模組。
結對的過程和照片
我們在開始實現的前一天,討論出了我們演算法的大體思路。在實現的那一天,先按照原先的計劃,很快實現出了第一個版本,然後經過測試,討論,繼續改進,實現了第二個版本。全程都是結對程式設計。(但是沒有人給我們拍照)
合作方式,結對程式設計的優點和缺點
方式就是很傳統的領航員+駕駛員的方式。
優點:效率很高,程式碼思路很清晰,在有一個人不知道怎麼寫的時候,另一個人能補充;有錯誤的地方也能指出;有程式碼寫法可以優化的地方也可以及時優化。
缺點: 這個專案有點小,只能是結對程式設計的一次小體驗,暫時沒有發現什麼缺點。
PSP 表格
PSP 各個階段 | 實現的時間 |
---|---|
計劃: 討論我們的大致策略 | 2h |
開發:實現我們的策略,給出最初版本 V1.0 | 1.5h |
測試:測試V1.0, 並根據測試結果提出改進想法 | 1h |
開發:實現V2.0 | 1.5h |
測試:測試V2.0 | 0.5h |
基本上和預估的一致,第一個版本實現的較快,第二個版本實現時間稍長,總時間和預估差不多,一天不到就完成了。
其它收穫
這是一個比賽,我們總分取得了第三名。我們的演算法的確很簡單,但是實際上策略還是十分有效的。演算法的缺點也比較明顯,一些引數的自動學習和調整非常依賴經驗和資料,我們沒有能夠很好的掌握。
不過,我也切身體會到了結對程式設計的好處,效率非常高,對兩個人的鍛鍊也很明顯,結對程式設計是從自我監督到互相監督的一種轉換,某種程度上依賴隊友,同時又需要監督隊友,需要更集中的精神,另一方面,結對也是與人溝通的過程,對錶達自己的想法也是一種鍛鍊。