java 炸金花_炸金花绝对大小计算 比较及排序算法(Java)

牌大小计算算法

花色不参与大小比较:

首先对到手的牌按照牌数字按照由大到小排序

牌大小按照牌型分级

对于普通牌型,每张牌视为16进制的一个数,A对应14,2对应2,以此类推。牌值即为这幅此16进制牌的大小。

比如最大的普通牌为AKJ,其16进制数值为AKJ=14x16x16+13x16+11=3803

对于对子,先将对子放在牌的前两位,则在最大普通牌大小的基础上,加上对子牌的本身大小。 对子的本身大小计算方法:比如最大的对子为AAK,则AAK=14x16+13=237,加上最大的普通牌值3803,即为4040

对于顺子,取最小的那个数,加上最大的对子牌值,比如最大的顺子AKQ=12+4040=4052。最小的顺子A32,A取1,值4041

对于同花,先按照普通牌型计算大小,再加上最大的对子牌值。

比如最大的同花AKJ=3803+4052=7855

对于同花顺,取最小的那个数,加上最大的同花牌值,比如:

AKQ=12+7855=7867,最小的同花顺A32,A取1,A32=1+7855=7856

对于炸弹,取第一个数,加上最大的同花顺牌值。

比如AAA=14+7867=7881

花色参与大小比较:

比较规则:在牌数字完全一样的情况下,从最大的牌开始比较,黑桃>红桃>梅花>方片,遇到一个较大的,则结束比较。如:红桃A+红桃Q+方片3>梅花A+黑桃Q+黑桃3。如遇顺子时,数字3最大,从3开始比较花色。

花色值设定:黑桃=3红桃=2梅花=1方片=0。

牌值计算原理:在上面花色不参与大小比较算法的基础上,增加对每副计算出来的牌值乘以64再加上对三张牌花色按照4进制进行花色值计算作为附加值。比如:不考虑花色时,红桃6+方片4+方片2的值为6x256+4x16+2=1602,考虑花色时,红桃+方片+方片对应的4进制就是200,其10进制值为32,然后这副牌的牌值即为:1602x64+32=102560。为什么乘以64?因为三个花色4进制值的范围为63~0。乘以64,就是把原来每组牌值大小相邻的牌型拉开63个的间隔,以便于让花色值有发挥的空间哈哈,用来区别数字完全相同但花色不同的牌型。

如果是炸弹,先将炸弹按花色从大到小排序,保证比如黑桃A红桃A方片A会>红桃A梅花A方片A

如此,就可得对所有的牌值进行了统一的大小计算

代码实现

主要分为四个模块

- entity 实体

- player provider 发牌器

- typevalue 牌型识别

- calculator 计算器,提供不同方式的计算方法

实体类

Card 单张牌

/*** 单张牌

*

*@authorLeon

**/

public classCard {public static final int FLOWER_SPADE = 3;//黑桃

public static final int FLOWER_HEART = 2;//红桃

public static final int FLOWER_CLUB = 1;//梅花

public static final int FLOWER_DIAMOND = 0;//方片

public static final int NUM_A = 14;public static final int NUM_K = 13;public static final int NUM_Q = 12;public static final int NUM_J = 11;public static final int NUM_10 = 10;public static final int NUM_9 = 9;public static final int NUM_8 = 8;public static final int NUM_7 = 7;public static final int NUM_6 = 6;public static final int NUM_5 = 5;public static final int NUM_4 = 4;public static final int NUM_3 = 3;public static final int NUM_2 = 2;//单张牌大小

private intnumber;//花色

private intflower;publicCard() { }public Card(int flower, intnumber) {this.flower =flower;this.number =number;

}public intgetNumber() {returnnumber;

}public void setNumber(intnumber) {this.number =number;

}public intgetFlower() {returnflower;

}public void setFlower(intflower) {this.flower =flower;

}

}

玩家

/*** 玩家,对应一副牌

*

*@authorLeon

**/

public classPlayer {public Card[] cards = new Card[3];//牌类型

private inttype;//是否为特殊牌

private boolean isSpecial = false;//A32也是顺子,比花色时,从3开始比较

private boolean isA32 = false;//牌绝对值大小

private intvalue;publicPlayer() {

}publicPlayer(Card card0, Card card1, Card card2) {this.cards[0] =card0;this.cards[1] =card1;this.cards[2] =card2;

}publicCard[] getCards() {returncards;

}public voidsetCards(Card[] cards) {this.cards =cards;

}public intgetType() {returntype;

}public void setType(inttype) {this.type =type;

}public intgetValue() {returnvalue;

}public void setValue(intvalue) {this.value =value;

}public booleanisSpecial() {returnisSpecial;

}public void setSpecial(booleanisSpecial) {this.isSpecial =isSpecial;

}public booleanisA32() {returnisA32;

}public void setA32(booleanisA32) {this.isA32 =isA32;

}

}

PlayerProvider

发牌器接口,负责发牌、洗牌

/*** 发牌器

*

*@authorLeon

**/

public interfacePlayerProvider {//产生单副牌

Player getSinglePlayer();//产生多副牌

List getPlayers(intnumber);//发一张牌

Card getCard();//洗牌

voidshuffle();

}

其具体实现有

- LimitedPlayerProvider 有限制的发牌器,从一幅牌中发牌

- UnlimitedPlayerProvider 无玩家人数限制的发牌器,随机产生牌,不考虑玩家牌完全相同的情况,但一个玩家手中不会出现完全相同的牌。

TypeValueSetter

负责对一副牌进行牌型鉴定,并根据牌型使用指定的计算器计算牌值

/*** 牌型识别器,负责鉴定牌型,并按照指定的模式计算牌大小

*

*@authorLeon

**/

public classTypeValueSetter {privateValueCalculator calculator;publicTypeValueSetter(ValueCalculator calculator) {this.calculator =calculator;

}//判断牌型、计算牌型绝对值大小

publicPlayer regPlayerType(Player player) {if(isFlush(player)) {if (isStraight(player)) {//同花顺

player.setType(PlayerType.STRAIGHT_FLUSH);

player.setValue(calculator.getStraightFlushValue(player));

}else {//同花

player.setType(PlayerType.FLUSH);

player.setValue(calculator.getFlushValue(player));

}

}else if (isStraight(player)) {//顺子

player.setType(PlayerType.STRAIGHT);

player.setValue(calculator.getStraightValue(player));

}else if(isDouble(player)) {if (isBmob(player)) {//炸弹

player.setType(PlayerType.BOMB);

player.setValue(calculator.getBombValue(player));

}else {//对子

player.setType(PlayerType.DOUBLE);//将对子放到玩家牌的前两张的位置,以便于之后的牌值计算

PlayerUtil.moveDouble2Front(player);

player.setValue(calculator.getDoubleValue(player));

}

}else {//普通牌

player.setType(PlayerType.NORMAL);

player.setValue(calculator.getNormalValue(player));if (isSpecial(player)) {//对于特殊牌,本算法不提供特殊大小计算,外部调用者自行判断是否有炸弹玩家产生

player.setSpecial(true);

}

}returnplayer;

}//是否同花

private booleanisFlush(Player player) {return player.cards[0].getFlower() == player.cards[1].getFlower()&& player.cards[1].getFlower() == player.cards[2].getFlower();

}//是否顺子,A32也是同花顺,是最小的同花顺(参考自百度百科)//花色参与比较的时候,黑桃A红桃3黑桃2

private booleanisStraight(Player player) {boolean isNomalStraight = player.cards[0].getNumber() == player.cards[1].getNumber() + 1

&& player.cards[1].getNumber() == player.cards[2].getNumber() + 1;boolean isA32 = player.cards[0].getNumber() == 14 && player.cards[1].getNumber() == 3

&& player.cards[2].getNumber() == 2;if(isA32) {

player.setA32(true);

}return isNomalStraight ||isA32;

}//是否炸弹

private booleanisBmob(Player player) {return player.cards[0].getNumber() == player.cards[1].getNumber()&& player.cards[1].getNumber() == player.cards[2].getNumber();

}//是否对子

private booleanisDouble(Player player) {return player.cards[0].getNumber() == player.cards[1].getNumber()|| player.cards[1].getNumber() == player.cards[2].getNumber();

}//是否特殊牌

private booleanisSpecial(Player player) {return player.cards[0].getNumber() == 5 && player.cards[1].getNumber() == 3 && player.cards[2].getNumber() == 2;

}

}

ValueCalculator

牌值计算器接口,负责提供对一副牌的计算方法,

/*** 牌值计算器

*

*@authorLeon

**/

public interfaceValueCalculator {//获取炸弹牌值绝对大小

intgetBombValue(Player player);//获取同花顺牌值绝对大小

intgetStraightFlushValue(Player player);//获取同花牌值绝对大小

intgetFlushValue(Player player);//获取顺子牌值绝对大小

intgetStraightValue(Player player);//获取对子牌值绝对大小//在判断牌型时,如果是对子,则将对子放在数组前面两位

intgetDoubleValue(Player player);//获取普通牌值绝对大小

intgetNormalValue(Player player);

}

具体实现有:

NonFlowerValueCalculator

花色不参与大小比较的计算器,牌越大,牌值越大

/*** 花色不参与牌大小比较的计算器

* 牌值越大,牌越大

*@authorLeon

**/

public class NonFlowerValueCalculator implementsValueCalculator {//获取炸弹牌值绝对大小

public intgetBombValue(Player player) {return player.cards[0].getNumber() +PlayerType.STRAIGHT_FLUSH_MAX_VALUE;

}//获取同花顺牌值绝对大小,A32也是同花顺,是最小的同花顺(参考自百度百科)

public intgetStraightFlushValue(Player player) {if(player.isA32()) {//此时A就等于是1

return 1 +PlayerType.FLUSH_MAX_VALUE;

}return player.cards[2].getNumber() +PlayerType.FLUSH_MAX_VALUE;

}//获取同花牌值绝对大小

public intgetFlushValue(Player player) {return player.cards[0].getNumber() * 256 + player.cards[1].getNumber() * 16 + player.cards[2].getNumber()+PlayerType.STRAIGHT_MAX_VALUE;

}//获取顺子牌值绝对大小

public intgetStraightValue(Player player) {if(player.isA32()) {//此时A就等于是1

return 1 +PlayerType.DOUBLE_MAX_VALUE;

}return player.cards[2].getNumber() +PlayerType.DOUBLE_MAX_VALUE;

}//获取对子牌值绝对大小//在判断牌型时,如果是对子,则将对子放在数组前面两位

public intgetDoubleValue(Player player) {return player.cards[1].getNumber() * 16 + player.cards[2].getNumber() +PlayerType.NORMAL_MAX_VALUE;

}//获取普通牌值绝对大小

public intgetNormalValue(Player player) {return player.cards[0].getNumber() * 256 + player.cards[1].getNumber() * 16 + player.cards[2].getNumber();

}

}

FlowerValueCalculator

花色参与大小比较的计算器,牌越大,牌值越大

/*** 花色参与牌值大小比较的计算器,牌值越大,牌越大

*

*@authorLeon

**/

public class FlowerValueCalculator implementsValueCalculator {private intgetFlowerValue(Player player) {return player.cards[0].getFlower() * 16 + player.cards[1].getFlower() * 4 + player.cards[2].getFlower();

}private intgetA32FlowerValue(Player player){return player.cards[1].getFlower() * 16 + player.cards[2].getFlower() * 4 + player.cards[0].getFlower();

}//获取炸弹牌值绝对大小

public intgetBombValue(Player player) {//炸弹需要先对牌按花色大小排序,保证比如黑桃A红桃A方片A会>红桃A梅花A方片A

PlayerUtil.sortPlayerByFlower(player);return (player.cards[0].getNumber() + PlayerType.STRAIGHT_FLUSH_MAX_VALUE) * 64 +getFlowerValue(player);

}//获取同花顺牌值绝对大小,A32也是同花顺,是最小的同花顺(参考自百度百科)

public intgetStraightFlushValue(Player player) {if(player.isA32()) {return (1 + PlayerType.FLUSH_MAX_VALUE) * 64 +getA32FlowerValue(player);

}return (player.cards[2].getNumber() + PlayerType.FLUSH_MAX_VALUE) * 64 +getFlowerValue(player);

}//获取同花牌值绝对大小

public intgetFlushValue(Player player) {return (player.cards[0].getNumber() * 256 + player.cards[1].getNumber() * 16 + player.cards[2].getNumber()+ PlayerType.STRAIGHT_MAX_VALUE) * 64 +getFlowerValue(player);

}//获取顺子牌值绝对大小

public intgetStraightValue(Player player) {if(player.isA32()) {return (1 + PlayerType.DOUBLE_MAX_VALUE) * 64 +getA32FlowerValue(player);

}return (player.cards[2].getNumber() + PlayerType.DOUBLE_MAX_VALUE) * 64 +getFlowerValue(player);

}//获取对子牌值绝对大小//在判断牌型时,如果是对子,则将对子放在数组前面两位

public intgetDoubleValue(Player player) {//在花色参与计算大小时,将对子中的花色大的换到前面

PlayerUtil.exchangeSortedDoubleFlower(player);return (player.cards[1].getNumber() * 16 + player.cards[2].getNumber() + PlayerType.NORMAL_MAX_VALUE) * 64

+getFlowerValue(player);

}//获取普通牌值绝对大小

public intgetNormalValue(Player player) {return (player.cards[0].getNumber() * 256 + player.cards[1].getNumber() * 16 + player.cards[2].getNumber()) * 64

+getFlowerValue(player);

}

}

PlayerType类

/*** 对牌型分类,并提供牌大小值的算法,和已经计算好的牌型最大值

*

*@authorLeon

**/

public classPlayerType {//炸弹

public static final int BOMB = 5;//最大值AAA=14,加上同花顺6867=7881

public static final int BOMB_MAX_VALUE = 7881;//同花顺,A32也是顺子,是最小的同花顺(参考自百度百科)

public static final int STRAIGHT_FLUSH = 4;//最大值AKQ=12,加上同花7855=7867

public static final int STRAIGHT_FLUSH_MAX_VALUE = 7867;//同花

public static final int FLUSH = 3;//最大值AKJ,14*16*16+13*16+11=3803,加上顺子4052=7855

public static final int FLUSH_MAX_VALUE = 7855;//顺子,A32也是顺子,是最小的同花顺(参考自百度百科)

public static final int STRAIGHT = 2;//最大值AKQ=12,加上对子的最大值基数4040=4052

public static final int STRAIGHT_MAX_VALUE = 4052;//对子

public static final int DOUBLE = 1;//最大值AAK=14*16+13=237,加上普通牌的基数3803=4040

public static final int DOUBLE_MAX_VALUE = 4040;//普通牌,里面包含一种特殊牌532不同花色//对于特殊牌,本算法不提供特殊大小计算,但会将这副牌标记为特殊牌//外部调用者自行判断是否有炸弹玩家产生

public static final int NORMAL = 0;//最大值AKJ=14*16*16+13*16+11=3803

public static final int NORMAL_MAX_VALUE = 3803;

}

还有两个计算器就不贴代码了:

Low2HeighCalculator

花色不参与大小比较的计算器,牌越大,牌值越小

FlowerLow2HeighCalculator

花色参与大小比较的计算器,牌越大,牌值越小

PlayerComparator 总指挥

负责对牌初始化、牌型识别、牌值计算以及排序。你给我一副或者一组凌乱的牌,我让你整洁有序。

/*** 牌型判断比较器,负责对所有玩家的牌大小进行计算和排序

*

*@authorLeon

**/

public class PlayerComparator implements Comparator{privateTypeValueSetter recognizer;publicPlayerComparator(ValueCalculator calculator) {this.recognizer = newTypeValueSetter(calculator);

}/*** 对玩家牌型进行牌型识别和牌值计算 这副牌三张都已经按照数字从大到小排好序

*

*@paramplayer

* 一副牌*/

public voidsetupRegularPlayer(Player player) {

recognizer.regPlayerType(player);

}/*** 对玩家牌型进行牌型识别和牌值计算 这副牌没有按照数字从大到小排好序

*

*@paramplayer

* 一副牌*/

public voidsetupUnRegularPlayer(Player player) {

PlayerUtil.sortPlayerByNumber(player);

recognizer.regPlayerType(player);

}/*** 对玩家列表进行牌型判断、值获取及排序 每副牌的三张牌都已经按照数字从大到小排序

*

*@paramplayersInput

* 一组牌*/

public void sortRegularPlayers(ListplayersInput) {for(Player player : playersInput) {

recognizer.regPlayerType(player);

}

Collections.sort(playersInput,this);

}/*** 对玩家列表进行牌型判断、值获取及排序 每副牌的三张牌没有按照从大到小排序

*

*@paramplayersInput

* 一组牌*/

public void sortUnRegularPlayers(ListplayersInput) {for(Player player : playersInput) {

PlayerUtil.sortPlayerByNumber(player);

recognizer.regPlayerType(player);

}

Collections.sort(playersInput,this);

}

@Overridepublic intcompare(Player player1, Player player2) {returnInteger.valueOf(player1.getValue()).compareTo(Integer.valueOf(player2.getValue()));

}

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值