一、團隊課程設計博客鏈接
二、個人負責模塊或任務說明
- 實體類的設計
- 斗地主規則的實現
- 人機自動出牌的算法
- 實現數據庫的DAO模式
三、自己的代碼提交記錄
注:這里只有部分提交記錄,詳細的提交記錄在團隊課程設計博客里有
四、自己負責模塊或任務詳細說明
1、實體類的設計的代碼分析
游戲設計需要用到卡片類(Card)
正反面,還有牌型(CardType)
的設計,以及各種牌的組合
,還要設計在游戲中的搶地主、出牌倒計時、出牌和不出牌等等以及需要判斷是否能夠出牌和人機自動出牌等。
整體的設計需要用戶類(User)
用於存儲用戶的賬號密碼,以及用戶信息類(UserInformation)
用於存儲用戶的賬號、昵稱、積分等等個人信息。
2、斗地主規則的實現的代碼分析
既然是一個游戲,那就要有規則,其中最主要的就是,判斷所選的牌型是否正確,即是否符合規則。在牌型符合規則時,需要判斷是否能夠出牌。
在判斷所選的牌型是否符合規則的設計中,因為規則中的牌型是固定的,所以設計了一個常量CardType類,這個常量類中包括了符合斗地主規則的所有可選牌型以及不允許出牌的常量。
判斷牌型的時候,需要根據所選的牌的數量,以及各個牌型的特征,如:連對的基本特征為,需要連續3對,並且這三對的數值是連續的等等,來判斷用戶所選的牌是否為規則內的牌型,是的話返回相應的牌型,供后面的算法判斷,如果不是則返回c0,服務器就會給客戶端相應的反饋,禁止用戶出所選的牌。
判斷完牌型后,如果返回的不是c0,則需要判斷用戶是否能夠出所選的牌。在這個判斷中,首先就需要判斷用戶是主動出牌還是跟牌,如果為主動出牌,則服務器就會給客戶端相應的反饋,同意用戶出牌;如果為被動出牌,則需要判斷當前用戶所選的牌,與前面的用戶出的最大的牌進行比較。
當前面出的牌不是炸彈,而用戶選的牌型為炸彈時,既可以出牌。當用戶選的牌型不為炸彈時,需要判斷該用戶所選的牌是否與前面用戶所出的牌型相符合,若符合,則判斷該用戶所選的牌是否比前面用戶所出的牌大,若符合則允許出牌,否則禁止用戶出牌。
3、人機自動出牌的算法的代碼分析
本次課程設計實現的是單人單機游戲,則需要電腦自動判斷除用戶外的另外兩幅牌該如何出。
判斷人機如何出牌時,首先先判斷人機為主動出牌還是被動出牌,若為主動出牌,則把人機的牌進行拆分,拆分成符合規則的相關牌型,然后按先出單牌,再出對子,在出連對等等的順序,按序選擇該輪人機所要出的牌。
如果為被動出牌,則將人機的牌進行拆分,拆分成符合規則的相關牌型,然后通過判斷目前所出的最大的牌的牌型,根據該牌型判斷目前該人機手中是否擁有符合條件的牌,若有,再判斷該人機的下一個出牌人是否為地主,如果是,則選擇最大的出,如果不是則選擇最小的出。如果沒有符合條件的牌,則該人機就不出牌。
由於兩個操作都涉及到對人機牌的拆分,在拆分的過程中,按照炸彈優先,拆分三帶,拆分飛機等等的順序,將人機的手牌拆分成符合規則的各個種類的手牌,防止拆了規則中的大牌,如炸彈等等。
最后就是,一開始的搶地主環節,當用戶搶地主時,則地主就為用戶,當用戶不搶地主時,需要根據人機當前手牌的權重大小,來判斷是那個人機要搶地主。該權重的計算方法為,統計兩幅人機手牌中大小王、A以及2的多少來計算,權重大的獲得地主牌。
4、數據存儲DAO模式代碼分析
DAO(Data Access Object)
顧名思義是一個為數據庫或其他持久化機制提供了抽象接口的對象,在不暴露底層持久化方案實現細節的前提下提供了各種數據訪問操作。
本次課程設計的底層數據存儲為數據庫,為了以防以后使用文件等其他形式存儲數據,為了方便日后修改小量代碼,使用了DAO模式設計數據存儲。
在本次課程設計的DAO模式的設計中,使用了兩個DAO接口類,UserDAO
以及UserInformationDAO
類,里面分別包括對User以及UserInformation的操作的相關方法。
因為使用了數據庫實現數據的存儲,所以在數據庫的操作類分別實現了上面的兩個接口。由於在對數據庫的每次操作中,均需要鏈接數據庫以及斷開與數據庫的鏈接,所以將鏈接數據庫以及斷開與數據的鏈接的操作拿出來,另外寫了一個JDBCUtil工具類。
5、多人同時訪問並進行游戲(多線程)的代碼分析
本次課程設計要實現的最終目標即為該斗地主游戲可以實現多人同時進行游戲。
則涉及到了多線程,當多人同時向服務器發出請求時,服務器需要判斷該請求來自哪位玩家,該玩家所屬的牌局當前的狀態,並進行相關的計算,給瀏覽器返回相應的計算結果。
所以,我們寫了一個InitServlet,用於當Tomcat服務器啟動時,就將一個牌局組對象(CardGames)寫入application中,則這牌局組對象就會一直存在,直到Tomcat服務器關閉。
這個牌局組(CardGames)對象,包括了一個Map類型的牌局組,一個Integer類型的標志(sign),並且包括一個新建牌局的對象,在新建牌局的時候,將標志,以及新建的牌局放入Map中,並且將改標志賦值給相應的用戶中的牌局標識,在后期的數據傳輸中,后台只要從客戶端獲取該請求的用戶,即可通過該用戶對應的牌局標識來從application中獲取的牌局組的對象中,獲得相應的牌局,從而得到正確的結果。為了防止多個用戶同時向服務器發送新家牌局的請求,導致出現了錯誤,所以為創建牌局的方法添加了互斥鎖。
牌局的對象中定義了初始牌對象,地主標識符,對應角色是否出牌標識,當前的出牌,3個玩家的所分到的牌,以及地主牌。
五、課程設計感想
在本次課程設計中,我主要負責的模塊為后端的代碼。最為難忘的便是在實體類的設計中,使用了public屬性,並且最初的設計中,基本沒有涉及到對象,導致后期在實現多人同時訪問時出現了各種各樣的錯誤,最后只好對已有的代碼進行重構,花費了更多的時間,特別是在對牌型判斷的公共方法中,進行了大修改。
本次課程設計,實現了網絡web版的單人斗地主,無法支持多人同時進行游戲,可以在次基礎上進行迭代,進而實現多人游戲。在對人機自動出的牌較為簡單,對人機出牌的判斷方法較為笨拙,可以進行優化,如添加人工智能算法等使得人機更加的“聰明”。
通過本次課程設計,讓我對JAVA的面向對象設計有了更加深刻的理解,平時上課講的比較基礎,再加上有時候可能沒有認真聽課,PTA上的題目較為簡單,未能對面向對象編程有更加深入的了解,雖然花費了大量的時間(將近兩周吧),但是收獲多多。