開篇引言?
麻將作為一款風靡全球的策略性游戲,其復雜的規則和多變的牌局給玩家帶來了無盡樂趣。在數字化時代,運用編程技術為麻將游戲賦予智能,實現自動出牌功能,不僅能提升玩家體驗,還能深入探索算法在博弈游戲中的應用。今天,就和大家分享我如何使用 Java 編寫一個智能麻將出牌組件的過程。?
1. 麻將規則簡述?
簡單介紹麻將的基本規則,如牌型(順子、刻子、對子等)、胡牌方式、不同花色牌的作用等。強調這些規則是后續智能出牌算法設計的基礎。例如,因為有順子和刻子的牌型,所以在計算出牌策略時,需要考慮如何通過出牌來促進這些牌型的形成或完善。?
11-19為1萬-9萬,21-29為1條到9條,31-39為1筒到9筒,41-47為東西南北中發白,51-58為梅蘭竹菊春夏秋冬
2. 技術選型 - Java 的優勢?
說明選擇 Java 作為開發語言的原因。如 Java 強大的跨平臺性,方便組件能在不同操作系統的麻將游戲中集成;豐富的類庫,在處理牌的邏輯、數據結構和算法實現時能提供便捷工具;良好的面向對象特性,有利于構建清晰、可維護的代碼結構等。?
3.主要的public方法
public class MahjongIntelligentModule {private Mahjong mahjong;private volatile static MahjongIntelligentModule singleton;/*** 智能模塊控制方法** @param handCards 手牌* @param outCards 已出的牌* @param laiZiCards 癩子牌* @param handCard 本次需要出的牌* @param queYiMenValue 缺一門牌值* @param lastOutCard 上一次出的牌* @param noOutCardList 不能出的牌* @return 可以出的牌值*/public MahjongIntelligentModule(List<Integer> handCards, List<Integer> outCards, List<Integer> laiZiCards, int handCard, int queYiMenValue, int lastOutCard, List<Integer> noOutCardList) {……}/*** 通過智能算法獲取可以出的牌值,判斷出牌后聽牌最大的可能性,通過outCards判斷出這張牌是否還有可能胡的牌** @return 可以出的牌值*/public int getOutCard() {……}/*** 判斷是否可以碰牌,通過牌型判斷和outCards判斷碰后是否會影響原來的牌型,加入影響則返回false,否則返回true** @return 是否可以碰牌*/public boolean getPengCard() {……}/*** 判斷是否可以杠牌,通過牌型判斷和outCards判斷杠后是否會影響原來的牌型,加入影響則返回false,否則返回true** @return 是否可以杠牌*/public boolean getGangCard(Integer cardType) {……}}
4. 智能出牌概率計算
進張概率計算?;?拆對、刻、順概率評估;綜合出牌概率公式應用?
5. 測試與驗證?
5.1 出牌測試
List<Integer> handCards = new ArrayList<>(Arrays.asList(12,13,14,15,16,17,24,26,32,33,35,37,38,26));MahjongIntelligentModule mahjongIntelligentModule = new MahjongIntelligentModule(handCards,new ArrayList<>(Arrays.asList()),new ArrayList<>(),-1,-1,-1,new ArrayList<>());int outcard = mahjongIntelligentModule.getOutCard();System.out.println("需要出的牌:"+outcard);
CardsInformationInfo{cardsInformations=……, outCard=24, maxChance=9.79}
需要出的牌:24?
?5.2 碰牌測試
List<Integer> handCards = new ArrayList<>(Arrays.asList(11,12,12,13,13,14,17));int lastoutcard = 12;MahjongIntelligentModule mahjongIntelligentModule = new MahjongIntelligentModule(handCards,new ArrayList<>(Arrays.asList()),new ArrayList<>(),-1,-1,lastoutcard,new ArrayList<>());boolean pengcard = mahjongIntelligentModule.getPengCard();System.out.println("碰的牌為:"+lastoutcard+"\t是否能碰:"+pengcard);
?碰的牌為:12?? ?是否能碰:false
List<Integer> handCards = new ArrayList<>(Arrays.asList(11,12,12,12,13,17,17));int lastoutcard = 12;MahjongIntelligentModule mahjongIntelligentModule = new MahjongIntelligentModule(handCards,new ArrayList<>(Arrays.asList()),new ArrayList<>(),-1,-1,lastoutcard,new ArrayList<>());boolean pengcard = mahjongIntelligentModule.getPengCard();System.out.println("碰的牌為:"+lastoutcard+"\t是否能碰:"+pengcard);
?CardsInformationInfo{cardsInformations=……, outCard=17, maxChance=2.63}
出牌:17
碰的牌為:12?? ?是否能碰:true
5.3吃牌測試
List<Integer> handCards = new ArrayList<>(Arrays.asList(11,12,12,12,13,17,17));int lastoutcard = 12;MahjongIntelligentModule mahjongIntelligentModule = new MahjongIntelligentModule(handCards,new ArrayList<>(Arrays.asList()),new ArrayList<>(),-1,-1,lastoutcard,new ArrayList<>());List<Integer> chiList = mahjongIntelligentModule.getChiCard();System.out.println("上加出的牌為:"+lastoutcard+"\t能吃的牌:"+chiList);
CardsInformationInfo{cardsInformations=……, outCard=17, maxChance=-0.15000000000000002}
出牌:17
上加出的牌為:12?? ?能吃的牌:[11, 12, 13]
List<Integer> handCards = new ArrayList<>(Arrays.asList(12,13,14,15,16,17,18));int lastoutcard = 12;MahjongIntelligentModule mahjongIntelligentModule = new MahjongIntelligentModule(handCards,new ArrayList<>(Arrays.asList()),new ArrayList<>(),-1,-1,lastoutcard,new ArrayList<>());List<Integer> chiList = mahjongIntelligentModule.getChiCard();System.out.println("上家出的牌為:"+lastoutcard+"\t能吃的牌:"+chiList);
?上家出的牌為:12?? ?能吃的牌:null