- 浏览: 153356 次
- 性别:
- 来自: 北京
最新评论
-
jingjing0907:
我是IT菜鸟,看到这篇文章很受启发,以后再学习和工作中多多注意 ...
IT人都很忙(茫) -
tantian189:
你想的大家都想,可是只是想了还不行,只有做出来才行,不拼搏,不 ...
IT人都很忙(茫) -
xouou_53320:
上有老 下有小 不加班 只能直接跳河
IT人都很忙(茫) -
alwaysperfect:
可以找个甲方工作,但是工资平平,上升也慢
IT人都很忙(茫) -
pyzheng:
miao19880124 写道看过你们的网站,没有突出ITFr ...
第二次当面试官
斗地主算法的设计与实现(三)--如何比较两手牌的大小
本篇主要讲解斗地主中如何比较两手牌的大小。
友情提示:本篇是接着以下两篇文章就讲解的,建议先看看下面这2篇。
斗地主算法的设计与实现--如何判断一手牌的类型(单,对子,三不带,三带一,四代二等)
牌型比较
火箭最大;次之;再次是一般牌型(单牌、对牌、三张牌、三带一、单顺、双顺、三顺、飞机带翅膀、四带二)
一般牌型:只有牌型且张数相同的牌才可按牌点数比较大小。
其中三带一、飞机带翅膀、四带二组合牌型,比较其相同张数最多的牌点数大小。
1.比较我的牌和上家的牌的大小,决定是否可以出牌
/** * 比较我的牌和上家的牌的大小,决定是否可以出牌 * * @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
相关推荐
斗地主项目的主要实现了,斗地主中的洗牌、发牌、判断牌型、排序等一系列算法,但这并不是一个完整的项目。 界面操作部分,功能很有限,仅供参考,有兴趣的同学自行完善。 我的CSDN博客还有很多优质原创文章,有...
基于Unity3D的多人网络斗地主游戏的设计与实现.pdf
基于安卓的斗地主游戏课程设计论文--大学毕业设计论文.doc
斗地主残局算法python,输入地主与农名的牌。自动计算地主出牌
斗地主算法类 适合初学者. 可以实现斗地主的洗牌发牌 无JFrame 简单易懂.
斗地主算法完整版,包含二人三人四人玩法天地癞子玩法,如有修改意见,一起学习交流进步
java斗地主的算法实现,实现了输出一幅新牌,发牌、和叫地主的功能算法
包括(Android_1.0_eBook_by_tom_kao_2008_10_15,andbook,何庆君Android手机下的斗地主游戏的设计与实现-设计文档,McGraw.Hill.Android.A.Programmers.Guide.Jul.2008.eBook-DDU,andbook中文教程[Publish],...
12 4.2.2 基于C/S模式的客户端设计流程图 12 4.3 游戏逻辑程序结构 13 4.3.1 数据层 13 4.3.2 控制层 13 4.3.3 显示层 14 4.4 游戏设计流程图 14 4.5 数学建模 15 第5章 详细设计与系统实现 16 5.1 斗地主洗牌算法 ...
本算法用C#编写,根据斗地主出牌规则.对玩家出的牌进行检验.判断是否符合出牌规则。
Android应用源码开发Demo,主要用于毕业设计学习。
易语言斗地主算法模块源码,斗地主算法模块,GetCardType,GetCardValue,GetCardColor,RandCardList,SortCardList,RemoveCardList,GetCardLogicValue,CompareCard,MakeCardData,AnalysebCardData,AnalysebDistributing
lua实现斗地主中的牌型判断,牌的比较,出牌提示的算法
Java斗地主发牌课程设计--附源码
基于python的强化学习斗地主设计与实现
斗地主的核心相关算法,机器人和出牌提示可以在此基础上继续完善
微信小游戏-斗地主,包含nodejs-服务器-nodejs-server-wechat-landLordGame
本算法采用Java语言编写,是网页FLASH版斗地主客户端的核心程序!
斗地主核心算法源码讲解 1、定义构造一张牌 2、如何判断一手牌的类型(单,对子,三不带,三带一,四代二等) 3、如何比较两手牌的大小 4、对牌进行排序 5、洗牌和发牌