首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件开发 >

斗地主算法的设计与实现-怎么比较两手牌的大小

2013-10-12 
斗地主算法的设计与实现--如何比较两手牌的大小本篇主要讲解斗地主中如何比较两手牌的大小。友情提示:本篇

斗地主算法的设计与实现--如何比较两手牌的大小

本篇主要讲解斗地主中如何比较两手牌的大小。

友情提示:本篇是接着以下两篇文章就讲解的,建议先看看下面这2篇。

/** * 比较我的牌和上家的牌的大小,决定是否可以出牌 * * @param myCards * 我想出的牌 * * @param myCardType * 我的牌的类型 * @param prevCards * 上家的牌 * @param prevCardType * 上家的牌型 * @return 可以出牌,返回true;否则,返回false。 */ public static boolean isOvercomePrev(List<Card> myCards, CardType myCardType, List<Card> prevCards, CardType prevCardType) { // 我的牌和上家的牌都不能为null if (myCards == null || prevCards == null) { return false; } if (myCardType == null || prevCardType == null) { logger.info("上家出的牌不合法,所以不能出。"); return false; } // 上一首牌的个数 int prevSize = prevCards.size(); int mySize = myCards.size(); // 我先出牌,上家没有牌 if (prevSize == 0 && mySize != 0) { return true; } // 集中判断是否王炸,免得多次判断王炸 if (prevCardType == CardType.WANG_ZHA) { logger.info("上家王炸,肯定不能出。"); return false; } else if (myCardType == CardType.WANG_ZHA) { logger.info("我王炸,肯定能出。"); return true; } // 集中判断对方不是炸弹,我出炸弹的情况 if (prevCardType != CardType.ZHA_DAN && myCardType == CardType.ZHA_DAN) { return true; } // 默认情况:上家和自己想出的牌都符合规则 CardUtil.sortCards(myCards);// 对牌排序 CardUtil.sortCards(prevCards);// 对牌排序 int myGrade = myCards.get(0).grade; int prevGrade = prevCards.get(0).grade; // 比较2家的牌,主要有2种情况,1.我出和上家一种类型的牌,即对子管对子; // 2.我出炸弹,此时,和上家的牌的类型可能不同 // 王炸的情况已经排除 // 单 if (prevCardType == CardType.DAN && myCardType == CardType.DAN) { // 一张牌可以大过上家的牌 return compareGrade(myGrade, prevGrade); } // 对子 else if (prevCardType == CardType.DUI_ZI && myCardType == CardType.DUI_ZI) { // 2张牌可以大过上家的牌 return compareGrade(myGrade, prevGrade); } // 3不带 else if (prevCardType == CardType.SAN_BU_DAI && myCardType == CardType.SAN_BU_DAI) { // 3张牌可以大过上家的牌 return compareGrade(myGrade, prevGrade); } // 炸弹 else if (prevCardType == CardType.ZHA_DAN && myCardType == CardType.ZHA_DAN) { // 4张牌可以大过上家的牌 return compareGrade(myGrade, prevGrade); } // 3带1 else if (prevCardType == CardType.SAN_DAI_YI && myCardType == CardType.SAN_DAI_YI) { // 3带1只需比较第2张牌的大小 myGrade = myCards.get(1).grade; prevGrade = prevCards.get(1).grade; return compareGrade(myGrade, prevGrade); } // 4带2 else if (prevCardType == CardType.SI_DAI_ER && myCardType == CardType.SI_DAI_ER) { // 4带2只需比较第3张牌的大小 myGrade = myCards.get(2).grade; prevGrade = prevCards.get(2).grade; } // 顺子 else if (prevCardType == CardType.SHUN_ZI && myCardType == CardType.SHUN_ZI) { if (mySize != prevSize) { return false; } else { // 顺子只需比较最大的1张牌的大小 myGrade = myCards.get(mySize - 1).grade; prevGrade = prevCards.get(prevSize - 1).grade; return compareGrade(myGrade, prevGrade); } } // 连对 else if (prevCardType == CardType.LIAN_DUI && myCardType == CardType.LIAN_DUI) { if (mySize != prevSize) { return false; } else { // 顺子只需比较最大的1张牌的大小 myGrade = myCards.get(mySize - 1).grade; prevGrade = prevCards.get(prevSize - 1).grade; return compareGrade(myGrade, prevGrade); } } // 飞机 else if (prevCardType == CardType.FEI_JI && myCardType == CardType.FEI_JI) { if (mySize != prevSize) { return false; } else { // 顺子只需比较第5张牌的大小(特殊情况333444555666没有考虑,即12张的飞机,可以有2种出法) myGrade = myCards.get(4).grade; prevGrade = prevCards.get(4).grade; return compareGrade(myGrade, prevGrade); } } // 默认不能出牌 return false; }


2.判断我所有的牌中,是否存在能够管住上家的牌,决定出牌按钮是否显示

  

 /**     * 判断我所有的牌中,是否存在能够管住上家的牌,决定出牌按钮是否显示     *     * @param myCards     *            我所有的牌 *     * @param prevCards     *            上家的牌     * @param prevCardType     *            上家牌的类型     * @return 可以出牌,返回true;否则,返回false。     */    public static boolean isOvercomePrev(List<Card> myCards,            List<Card> prevCards, CardType prevCardType) {        // 我的牌和上家的牌都不能为null        if (myCards == null || prevCards == null) {            return false;        }        if (prevCardType == null) {            System.out.println("上家出的牌不合法,所以不能出。");            return false;        }        // 默认情况:上家和自己想出的牌都符合规则        CardUtil.sortCards(myCards);// 对牌排序        CardUtil.sortCards(prevCards);// 对牌排序        // 上一首牌的个数        int prevSize = prevCards.size();        int mySize = myCards.size();        // 我先出牌,上家没有牌        if (prevSize == 0 && mySize != 0) {            return true;        }        // 集中判断是否王炸,免得多次判断王炸        if (prevCardType == CardType.WANG_ZHA) {            System.out.println("上家王炸,肯定不能出。");            return false;        }        if (mySize >= 2) {            List<Card> cards = new ArrayList<Card>();            cards.add(new Card(myCards.get(mySize - 1).id));            cards.add(new Card(myCards.get(mySize - 2).id));            if (isDuiWang(cards)) {                return true;            }        }        // 集中判断对方不是炸弹,我出炸弹的情况        if (prevCardType != CardType.ZHA_DAN) {            if (mySize < 4) {                return false;            } else {                for (int i = 0; i < mySize - 3; i++) {                    int grade0 = myCards.get(i).grade;                    int grade1 = myCards.get(i + 1).grade;                    int grade2 = myCards.get(i + 2).grade;                    int grade3 = myCards.get(i + 3).grade;                    if (grade1 == grade0 && grade2 == grade0                            && grade3 == grade0) {                        return true;                    }                }            }        }        int prevGrade = prevCards.get(0).grade;        // 比较2家的牌,主要有2种情况,1.我出和上家一种类型的牌,即对子管对子;        // 2.我出炸弹,此时,和上家的牌的类型可能不同        // 王炸的情况已经排除        // 上家出单        if (prevCardType == CardType.DAN) {            // 一张牌可以大过上家的牌            for (int i = mySize - 1; i >= 0; i--) {                int grade = myCards.get(i).grade;                if (grade > prevGrade) {                    // 只要有1张牌可以大过上家,则返回true                    return true;                }            }        }        // 上家出对子        else if (prevCardType == CardType.DUI_ZI) {            // 2张牌可以大过上家的牌            for (int i = mySize - 1; i >= 1; i--) {                int grade0 = myCards.get(i).grade;                int grade1 = myCards.get(i - 1).grade;                if (grade0 == grade1) {                    if (grade0 > prevGrade) {                        // 只要有1对牌可以大过上家,则返回true                        return true;                    }                }            }        }        // 上家出3不带        else if (prevCardType == CardType.SAN_BU_DAI) {            // 3张牌可以大过上家的牌            for (int i = mySize - 1; i >= 2; i--) {                int grade0 = myCards.get(i).grade;                int grade1 = myCards.get(i - 1).grade;                int grade2 = myCards.get(i - 2).grade;                if (grade0 == grade1 && grade0 == grade2) {                    if (grade0 > prevGrade) {                        // 只要3张牌可以大过上家,则返回true                        return true;                    }                }            }        }        // 上家出3带1        else if (prevCardType == CardType.SAN_DAI_YI) {            // 3带1 3不带 比较只多了一个判断条件            if (mySize < 4) {                return false;            }            // 3张牌可以大过上家的牌            for (int i = mySize - 1; i >= 2; i--) {                int grade0 = myCards.get(i).grade;                int grade1 = myCards.get(i - 1).grade;                int grade2 = myCards.get(i - 2).grade;                if (grade0 == grade1 && grade0 == grade2) {                    if (grade0 > prevGrade) {                        // 只要3张牌可以大过上家,则返回true                        return true;                    }                }            }        }        // 上家出炸弹        else if (prevCardType == CardType.ZHA_DAN) {            // 4张牌可以大过上家的牌            for (int i = mySize - 1; i >= 3; i--) {                int grade0 = myCards.get(i).grade;                int grade1 = myCards.get(i - 1).grade;                int grade2 = myCards.get(i - 2).grade;                int grade3 = myCards.get(i - 3).grade;                if (grade0 == grade1 && grade0 == grade2 && grade0 == grade3) {                    if (grade0 > prevGrade) {                        // 只要有4张牌可以大过上家,则返回true                        return true;                    }                }            }        }        // 上家出4带2        else if (prevCardType == CardType.SI_DAI_ER) {            // 4张牌可以大过上家的牌            for (int i = mySize - 1; i >= 3; i--) {                int grade0 = myCards.get(i).grade;                int grade1 = myCards.get(i - 1).grade;                int grade2 = myCards.get(i - 2).grade;                int grade3 = myCards.get(i - 3).grade;                if (grade0 == grade1 && grade0 == grade2 && grade0 == grade3) {                    // 只要有炸弹,则返回true                    return true;                }            }        }        // 上家出顺子        else if (prevCardType == CardType.SHUN_ZI) {            if (mySize < prevSize) {                return false;            } else {                for (int i = mySize - 1; i >= prevSize - 1; i--) {                    List<Card> cards = new ArrayList<Card>();                    for (int j = 0; j < prevSize; j++) {                        cards.add(new Card(myCards.get(i - j).grade));                    }                    CardType myCardType = getCardType(cards);                    if (myCardType == CardType.SHUN_ZI) {                        int myGrade2 = cards.get(cards.size() - 1).grade;// 最大的牌在最后                        int prevGrade2 = prevCards.get(prevSize - 1).grade;// 最大的牌在最后                        if (myGrade2 > prevGrade2) {                            return true;                        }                    }                }            }        }        // 上家出连对        else if (prevCardType == CardType.LIAN_DUI) {            if (mySize < prevSize) {                return false;            } else {                for (int i = mySize - 1; i >= prevSize - 1; i--) {                    List<Card> cards = new ArrayList<Card>();                    for (int j = 0; j < prevSize; j++) {                        cards.add(new Card(myCards.get(i - j).grade));                    }                    CardType myCardType = getCardType(cards);                    if (myCardType == CardType.LIAN_DUI) {                        int myGrade2 = cards.get(cards.size() - 1).grade;// 最大的牌在最后,getCardType会对列表排序                        int prevGrade2 = prevCards.get(prevSize - 1).grade;// 最大的牌在最后                        if (myGrade2 > prevGrade2) {                            return true;                        }                    }                }            }        }        // 上家出飞机        else if (prevCardType == CardType.FEI_JI) {            if (mySize < prevSize) {                return false;            } else {                for (int i = mySize - 1; i >= prevSize - 1; i--) {                    List<Card> cards = new ArrayList<Card>();                    for (int j = 0; j < prevSize; j++) {                        cards.add(new Card(myCards.get(i - j).grade));                    }                    CardType myCardType = getCardType(cards);                    if (myCardType == CardType.FEI_JI) {                        int myGrade4 = cards.get(4).grade;//                        int prevGrade4 = prevCards.get(4).grade;//                        if (myGrade4 > prevGrade4) {                            return true;                        }                    }                }            }        }        // 默认不能出牌        return false;    }    

3.比较2个grade的大小

/**     * 比较2个grade的大小     *     * @param grade1     * @param grade2     * @return     */    private static boolean compareGrade(int grade1, int grade2) {        return grade1 > grade2;    }    

4.检测牌的类型

    /**     * 检测牌的类型     *     * @param myCards     *            我出的牌     * @return 如果遵守规则,返回牌的类型,否则,返回null。     */    public static CardType getCardType(List<Card> myCards) {        CardType cardType = null;        if (myCards != null) {            // 大概率事件放前边,提高命中率            if (isDan(myCards)) {                cardType = CardType.DAN;            } else if (isDuiWang(myCards)) {                cardType = CardType.WANG_ZHA;            } else if (isDuiZi(myCards)) {                cardType = CardType.DUI_ZI;            } else if (isZhaDan(myCards)) {                cardType = CardType.ZHA_DAN;            } else if (isSanDaiYi(myCards) != -1) {                cardType = CardType.SAN_DAI_YI;            } else if (isSanBuDai(myCards)) {                cardType = CardType.SAN_BU_DAI;            } else if (isShunZi(myCards)) {                cardType = CardType.SHUN_ZI;            } else if (isLianDui(myCards)) {                cardType = CardType.LIAN_DUI;            } else if (isSiDaiEr(myCards)) {                cardType = CardType.SI_DAI_ER;            } else if (isFeiJi(myCards)) {                cardType = CardType.FEI_JI;            }        }        return cardType;    }

未来计划

接下来2篇将讲述 如何对牌进行排序,如何构造一副牌、洗牌、发牌。

本周日 2013年10月13日上传所有源码。


原文参见:http://FansUnion.cn/articles/2729

1楼FansUnion昨天 15:17
再写几篇就写完了。n(*^__^*) 嘻嘻

热点排行