java斗地主比大小_斗地主算法的设计与实现(三)--如何比较两手牌的大小
本篇主要讲解斗地主中如何比较两手牌的大小。
友情提示:本篇是接着以下两篇文章就讲解的,建议先看看下面这2篇。
牌型比较
火箭最大;炸弹次之;再次是一般牌型(单牌、对牌、三张牌、三带一、单顺、双顺、三顺、飞机带翅膀、四带二)
一般牌型:只有牌型且张数相同的牌才可按牌点数比较大小。
其中三带一、飞机带翅膀、四带二组合牌型,比较其相同张数最多的牌点数大小。
1.比较我的牌和上家的牌的大小,决定是否可以出牌/**
* 比较我的牌和上家的牌的大小,决定是否可以出牌
*
* @param myCards
* 我想出的牌
*
* @param myCardType
* 我的牌的类型
* @param prevCards
* 上家的牌
* @param prevCardType
* 上家的牌型
* @return 可以出牌,返回true;否则,返回false。
*/
public static boolean isOvercomePrev(List myCards,
CardType myCardType, List 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 myCards,
List 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 cards = new ArrayList();
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 cards = new ArrayList();
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 cards = new ArrayList();
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 cards = new ArrayList();
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 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日上传所有源码。
相关阅读
面向对象实现斗地主程序的核心算法,包括洗牌、发牌、判断牌型、比较牌的大小、游戏规则等。
java斗地主比大小_斗地主算法的设计与实现(三)--如何比较两手牌的大小相关推荐
- 斗地主算法的设计与实现(三)--如何比较两手牌的大小
本篇主要讲解斗地主中如何比较两手牌的大小. 友情提示:本篇是接着以下两篇文章就讲解的,建议先看看下面这2篇. 斗地主算法的设计与实现--如何判断一手牌的类型(单,对子,三不带,三带一,四代二等) 斗地 ...
- java青蛙过河打字_趣味算法——青蛙过河(JAVA)
青蛙过河是一个非常有趣的智力游戏,其大意如下: 一条河之间有若干个石块间隔,有两队青蛙在过河,每队有3只青蛙,这些青蛙只能向前移动,不能向后移动,且一次只能有一只青蛙向前移动.在移动过程中,青蛙可以向 ...
- java雪花数据库长度_雪花算法(SnowFlake)Java实现
算法原理 SnowFlake算法生成id的结果是一个64bit大小的整数,它的结构如下图: 由于在Java中64bit的整数是long类型,所以在Java中SnowFlake算法生成的id就是long ...
- java每日打卡_“365算法每日学计划”:03打卡-贪心算法
自从开始做公众号开始,就一直在思考,怎么把算法的训练做好,因为思海同学在算法这方面的掌握确实还不够.因此,我现在想做一个"365算法每日学计划"."计划"的主要 ...
- 用java实现combin函数_【算法-Java实现】组合总和
[算法-Java实现]组合总和 一.问题描述: 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合.c ...
- 堆排序算法java左程云_堆排序算法以及JAVA实现
堆的定义如下: n个元素的序列{k0,k1,...,ki,-,k(n-1)}当且仅当满足下关系时,称之为堆. " ki<=k2i,ki<=k2i+1;或ki>=k2i,ki ...
- java 数据周期预测_预测算法 | Holt Winter季节性指数平滑法 附JAVA代码
import java.util.ArrayList; import java.util.List; /** * 三次指数平滑预测,最多外推一个周期 * @author Administrator * ...
- Java实现mds降维_降维算法MDS
在现实应用中,许多学习方法都涉及距离计算,而高维空间会给距离计算带来很大的麻烦.例如当维数很高时,甚至连计算内积都很不容易. 这实际上,是所有机器学习都面临的严重障碍,这被称为"维数灾难(即 ...
- java 汽车加油问题_贪心算法 汽车加油问题 | 学步园
/ //一辆汽车加满油后可行驶n公里.旅途中有若干个加油站.设计一个有效 // // // n和k个加油站位置,编程计算最少加油次数.并证明算法能产生一个最优解. // //要求: ...
最新文章
- 天空之城(君をのせて)主题曲
- VC嵌入断点中断INT3
- spring17:Bean的生命始末标签@PostConstruct,@PreDestroy和改变作用范围的@Scope标签
- 精简JRE第一步 — 精简bin目录
- 两者相差百分比怎么算_相差200元!小米11和iQOO 7谁更值得买?说说真实想法
- Perl学习笔记(六)--文件(一)
- java foreach 实现原理
- 两千字揭密 MySQL 8.0.19 三大索引新功能:隐藏索引,降序索引,函数索引
- jquery ajax 请求 封装 成事件处理
- [转]ListView滚动到底部自动加载数据
- android-activity生命周期方法
- 事务的四个属性ACID
- 谁说前端工程师不能成为全栈?
- python标准库——sys模块
- 让一个.sh文件一直运行_想做AI鉴黄工具?这有一个内含20多万张“不可描述”图片的数据集...
- 2022年各种经典java小游戏
- fit me app Android,「最美应用」国庆专题:—这些习惯养成 App,让你离更好的自己更进一步!...
- 用Python写一个Excel汇总和比对小程序
- 联想笔记本prtsc不能截图_联想笔记本截图快捷键
- [运算放大器系列]二、电压转4 - 20MA电流电路分析