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日上传所有源码。

相关阅读

面向对象实现斗地主程序的核心算法,包括洗牌、发牌、判断牌型、比较牌的大小、游戏规则等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值