2015華爲德州撲克參賽總結——軟件工程

直到6月2號晚上零點,爲期一個月的華爲德州撲克比賽也算告一段落了。我們團隊總共有3人,其中,一個同學(吳)負責算法的設計,一個同學(宋)負責消息的解析,而我則負責整個框架的設計以及具體決策算法的實現。從5月份初報名開始,到環境的搭建,框架的設計,任務的分工,算法的設計以及各個模塊代碼的編寫,從我個人的感覺來看,整個過程可以說是一個比較艱辛的歷程。

德州撲克是一種棋牌類遊戲,屬於一種博弈過程,起先我對這個遊戲沒有任何的瞭解,最多的也只是在影視題材裏面見過,但是具體的遊戲規則並不懂。而正是在這樣的條件下,我們參加了由華爲舉辦的德州撲克大賽。比賽的形式,由華爲官方提供服務端程序,這個服務端程序負責整個遊戲的控制,而參賽的隊伍則必須按照官方提供的通信協議,設計出自己的玩家程序,實現和服務器的對接,並和其他玩家進行博弈遊戲,最大限度的獲得存活場次和金幣數量。

整個德州撲克的遊戲分爲四個階段,包括了翻牌前(preflop)、翻牌(flop)、轉牌(turn)、河牌(reiver),玩家在不同的階段,根據自己的手牌信息和已知的公牌信息以及每一個玩家的動作做出對自己最有利的動作以獲得最後的獎池獎金,這裏的動作包括了蓋牌(fold)、加註(raise)、跟注(call)、讓牌(check)、全押(all In),在每一個階段裏面,只有當所有的玩家投入的金額相等,或者全押,纔會進入下一個階段,而如果是棄牌的玩家,則放棄最後的獎池獎金,不參與後面的喊注。最後遊戲的輸贏是隻剩一個玩家或者在場的玩家的兩張手牌和5張公牌組合出最大的牌型的玩家平分最後的獎池獎金。

根據官方提供的通信協議手冊,客戶端可以將整個流程進行如下劃分:


客戶端先通過initialize和服務器建立連接,並註冊,然後調用recevMsg開始接收消息,解析消息,如果接收到了遊戲結束game-over的報文,則調用destroy斷開連接釋放資源,整個流程結束,否則根據接收到的報文,解析裏面的信息,然後根據需要調用Update更新遊戲和玩家的狀態,如果服務器要求客戶端做出決策動作,則調用makeDecision根據當前收集的信息進行決策,然後把決策動作交由sendMsg返回給服務器,等待服務器的下一條報文信息,整個客戶端遊戲如此不斷循環,直到遊戲結束。

根據流程圖,可以獲得用例圖:


根據樣例用圖,進一步分析,可以得到整個系統框架所需的類圖,當然這個只是初期的一個系統框架,粒度還是比較粗,這個只是爲了便於分工合作,提前設計好藉口,後期還是根據不同的需要進行了部分的調整,初期設計的類圖如下:


在設計中,根據用例圖對模塊功能進行了劃分並封裝,最後得到了上圖的幾個類,由於設計初期,我們還不能確認在決策算法中需要什麼數據信息,所以,在Status類中只是保留了接口和引用關係,裏面具體的成員變量和函數則需要和具體的實現需求結合然後加以擴充,Action類的情況也是類似的。這裏的設計需要注意的是,爲了使整個系統的各個模塊部分有一個比較好的解耦效果,採用了設計模式中的策略模式,將決策模塊提取出來,然後在主類中保留了接口,以便後期採用不同的決策算法進行替代,而不需要去改動其他模塊。

在這次的合作中,我們採用的是敏捷開發的團隊合作方式,整個合作過程,我們的文檔部分只有一些必要的框架文檔和算法說明,剩餘的部分還是以交流居多。整個過程中,團隊交流次數3-4次左右,這樣的交流每次都要持續一個晚上的時間,大概3個小時左右,而成員之間的合作交流在4-5次左右,每次時間也都是2-3個小時。也就是說,在這次的合作過程中,我們強調的是溝通和效率,通過文檔來記錄交流一些基本信息,對於繁雜說明,我們選擇了面對面交流方式,然後輔以必要的文檔來提高共同效率。

敏捷開發出了注重溝通之外,還需要強調團隊的個人能力,在我們的團隊中,每個人都明確分工,這個得益於一開始的框架模塊劃分,其中,具有較好的數學功底的同學負責資料的收集和算法的設計,剩餘的兩個,則一個負責消息模塊的解析,一個負責框架的搭建和算法的編碼實現,每個人都各司其職。

此外,敏捷開發還注重階段性成果的實現,在這個過程中,我們團隊先從環境的搭建,然後是框架的設計,再是每個模塊的實現,在每一個階段都一定的成果進度的安排和實現,然後在上一個階段成果的基礎上進入下一個階段。雖然如此,但仍然存在一些問題與不足:

1、我們在整個團隊項目中,沒有使用代碼管理軟件,這是一個潛在的弊端,由於沒有使用代碼管理軟件的經驗以及相應的條件,導致我們最後在進行代碼整合的時候出現了一些滯後的情況,另一個同學在進行代碼調試的時候,在進行交流才發現,他使用的代碼並不是我提供的最新版本,這是我們遇到的一個代碼統一問題,雖然那同學後來自己建立了SVN服務器,但是由於機器性能不足,以及IP問題,後來沒能用起來,這個是不足之處。

2、由於沒有團隊合作的經驗,在編寫代碼的時候,沒有注重代碼的排版以及代碼註釋說明,在幫助對方調試代碼的時候,發現幾乎沒有什麼註釋,對於類的成員函數或者是結構體的成員都沒有必要的說明,這個對於閱讀代碼的人來說是一個非常痛苦的,而對於函數接口的說明更是缺乏必要的功能說明,以及輸入參數以及返回值的說明,這個給閱讀和理解程序的人來說造成了很大的障礙,對於團隊的合作效率來說是一個不小的弊端。

3、在拿到對方的代碼的時候,沒有大致瀏覽對方的代碼,對別寫的代碼沒有一個整體的把握,使得沒有能夠使用別人提供好的一些接口,而是自起爐竈,這對於時間上的耗費以及潛在的bug的產生都是有相當大的代價,這在一定程度也使得項目的進展滯後。

4、在項目開發過程中,除了必要的溝通之外,對於一些重要的任務的分配應該有一些相應的反饋機制,在我們的開發過程中,就出現了這樣一個嚴重的問題,在我的算法設計部分裏面,需要一些消息解析過程中提供必要的參數信息,由於我在編寫算法模塊的過程,我不清楚另一個同學的消息解析的情況,因此我只有預留必要的變量,然後由消息解析的同學來負責補充,對於這個任務,我當時在羣裏叮囑過後,對方也給予確認答覆。然而,問題就在於,我沒有在後期對這個任務的分配進行完成度的確認,使得我們在臨近截止日期才發現最後這一塊該同學並沒有完成,使得我們到了最後一刻還在編寫代碼,調試bug,以至於沒有預留出比較充分的時間來測試程序的情況。

5、在軟件工程裏面一直強調的是,在開發過程,唯一不變的是需求是不斷改變的。是的,在我們開發過程中,算法的更新也是一而再,再而三的發生,直到最後臨近截止時間了,負責算法的同學還提出求改算法模塊的要求,對於他的這個要求,一個比較穩妥的做法就是先讓該同學把修改後的版本完整描述出來,然後再結合修改的難度以及剩餘允許時間所能做的修改考慮是否進行最後的更新或者調整。這種情況下的更新調整對於負責編碼的同學來說是一個相當大的挑戰,一個是要在有限的時間裏面快速做出響應,還有保證最後調整的代碼不會出現嚴重的bug問題。網絡上有個段子,描述的就是這個現象,說一個產品經理被程序員打是因爲到了最後還要修改需求。這次我遇到的情況也差不多是如此,所以如何很好地應對需求變化是一個比較值得思考的問題。

由於以上幾個不足,使得我們最後用來測試的時間幾乎沒有,我們只能提交能運行的代碼完成比賽,最後的結果如何應該都是可以接受的。結果也在6月5號出來了,很可惜,這次的成績不佳。

比賽的大概過程我看了一下,整體來分析的話,第一輪,我們第一局進展非常順利,拿到了第一名的成績,但是後面兩場都因爲超時次數過多被踢出去,但是勉強進了前4,進入了下一輪。但是到了第二輪之後,很幸運的是,沒有出現超時(0.5S給出答覆消息)掉線的情況,其中,第一局,一開始的情況還不錯,但是到了363局的時候,出現了我們手拿9對子,和別人的A對子加註廝殺,隨後allIn,就掛了,這個有點可惜了。而第二局的話,一開始的進展就不太順利,拿了不怎麼樣的手牌也和對手叫板,而其他牌手都相當保守,棄牌居多,在這一局裏面,我們到了第9局就掛了。第三局的話,我們排在第4,應該說是正常發揮,一開始我們是領先的,後來在256局就輸了3K多,情況也是差不多拿了KQ和別人的A對和K對叫板,然後接下來就開始處於劣勢,到399我們就掛了。

我分析的情況大體上如此,最後的時間確實比較趕,賽前沒有時間好好測測我們的程序,畢竟整體框架都搭建好了,剩下的就是算法的局部調整,由於沒有多參加幾次官方的PK來發現算法的潛在問題,這個還是比較遺憾的,不過大家都挺盡心盡力的。

通過對比賽結果和參賽過程的分析發現,對於超時問題,一個是能力上的不足,沒有充分利用多線程,因爲能力的不足所以做起來沒有把握,因此擔心出現多投入零產出的問題,還有一個是團隊合作上的進度問題,進度的滯後使得最後沒有空餘的時間做測試,沒有能夠最大程度發揮我們的算法模型,這是一個比較遺憾的事。在後面的學習過程,應多注意這次參賽過程中的諸多問題,希望下一次有一個明顯的進步和收穫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章