java麻将算法_Java实现的麻将胡牌算法

2023-05-16

胡牌:

平胡:1对将及4副(顺子/刻子)

对对胡:4副刻子+1对将组成的胡牌

七小对:全部牌都是1对

门清:全部牌都是自己摸的,没有碰和暗杠

全求人:全部碰或明杠,手上只剩一张牌,并且是点炮胡,不能自摸

清一色:全部都是一色的平胡(包含万、条、筒、字)

七大对:有4张一样的牌且没杠,其余牌都是对子

豪华大七对:有至少两个4张一样的牌,其余牌都是对子

定义麻将牌:

public class MajiangCard extends Card{

protected byte card;

public MajiangCard(){

}

public MajiangCard(byte card){

this.card = card;

}

public MajiangCard(byte cardValue, byte cardType){

this.card = (byte) (cardValue + (cardType<<4));

}

public boolean reqValid(){

return card > 0;

}

public byte getCard() {

return card;

}

public void setCard(byte card) {

this.card = card;

}

@Override

public String toString() {

return MJUtil.mjToStr(this);

}

public byte reqType(){

byte value = (byte)(card>>4);

return value;

}

public byte reqValue(){

byte type = (byte)(0x0F & card);

return type;

}

}

麻将牌占一个字节,高4位为类型(1-4为万条筒字),低4位为数据(1-9)

/**

* 判断 正常的胡牌类型

* @param isSelfCard 是否自摸牌

* @param cpCards 手牌

* @param gangCards 扛牌

* @param touchCards 碰牌

* @return

*/

@SuppressWarnings({ "unchecked", "rawtypes" })

public static int judgeNormalHuType(boolean isSelfCard, ListcpCards,

ListgangCards, ListtouchCards){

ListtmpCards = MJCommonFuncs.cpList(cpCards);

MapnumMap = MJCommonFuncs.transCardsToMap(tmpCards);

MapnumMapCp = (Map) MJCommonFuncs.cpMap((Map,?>)(Map)numMap);

//先判断是否是豪华7大对

int fourPairNum = 0;

int cardSerValue = MJCommonFuncs.filtCardNum(numMapCp, 4);

while(cardSerValue != 0){

fourPairNum++;

numMapCp.remove(cardSerValue);

cardSerValue = MJCommonFuncs.filtCardNum(numMapCp, 4);

}

fourPairNum += gangCards.size();

int ret = MJConst.HUTYPE_DISABLE;

if(fourPairNum >= 2 && touchCards.size() == 0){

//其他是对子

boolean isHu = true;

for(int cnt : numMapCp.values()){

if(cnt != 2){

//不是豪华7大对

isHu = false;

break;

}

}

if(isHu){

//胡了

ret |= MJConst.HUTYPE_HAOHUA;

return ret;

}

}

//判断是否是7大对

if(fourPairNum >= 1 && touchCards.size() == 0){

//其他是对子

boolean isHu = true;

for(int cnt : numMapCp.values()){

if(cnt != 2){

//不是7大对

isHu = false;

break;

}

}

if(isHu){

//胡了

ret |= MJConst.HUTYPE_7BIG_PAIR;

return ret;

}

}

//判断是否是全求人

if(cpCards.size() == 2 && !isSelfCard){

MajiangCard card = (MajiangCard)cpCards.get(0);

MajiangCard mc = (MajiangCard)cpCards.get(1);

if(isSameCard(mc, card)){

//判断杠是否明杠

boolean isAllVisibleGang = true;

for(MJGangStep mjgang : gangCards){

if(mjgang.getGangType() == MJConst.GANGTYPE_DISABLE){

isAllVisibleGang = false;

break;

}

}

if(isAllVisibleGang){

ret |= MJConst.HUTYPE_QQR;

//还有可能是对对胡

}

}

}

//判断是否是7小对

if(touchCards.size() == 0){

boolean isHu = true;

for(int cnt : numMapCp.values()){

if(cnt != 2){

//不是7小对

isHu = false;

break;

}

}

if(isHu){

//胡了

ret |= MJConst.HUTYPE_7SMALL_PAIR;

return ret;

}

}

//判断是否是对对胡

numMapCp.clear();

numMapCp = (Map) MJCommonFuncs.cpMap((Map,?>)(Map)numMap);

cardSerValue = MJCommonFuncs.filtCardNum(numMapCp, 3);

int threePairNum = 0;

while(cardSerValue != 0){

threePairNum++;

numMapCp.remove(cardSerValue);

cardSerValue = MJCommonFuncs.filtCardNum(numMapCp, 3);

}

threePairNum += touchCards.size();

threePairNum += gangCards.size();

if(threePairNum == 4 && numMapCp.size() == 1){

ret |= MJConst.HUTYPE_DDH;

//对对胡,不可能是平胡

return ret;

}

//判断是否是平胡

boolean pinghu = PingHuAnalyser.doAnalysing(tmpCards);

if(pinghu){

ret |= MJConst.HUTYPE_PH;

}

return ret;

}

除了平胡类型外,其他的胡牌类型都很简单,无非是判断每种牌的数据。平胡类型就复杂些了

/**

* 平胡分析器

* @author skymr

*

*/

public class PingHuAnalyser {

public static boolean doAnalysing(Listcards){

MapnumMap = MJCommonFuncs.transCardsToMap(cards);

ListtmpList = new ArrayList();

try{

//找出所有对子的可能

int cardSerValue = MJCommonFuncs.filtCardMinNum(numMap, 2);

while(cardSerValue != 0){

tmpList.add(cardSerValue);

numMap.remove(cardSerValue);

cardSerValue = MJCommonFuncs.filtCardMinNum(numMap, 2);

}

if(tmpList.size() == 0){

return false;

}

for(int twoNumCard : tmpList){

ListtmpCards = MJCommonFuncs.cpList(cards);

MJCommonFuncs.removeByNum(tmpCards, twoNumCard, 2);

//System.out.println("踢除对子后:"+tmpCards);

//踢除对子后找刻子

if(couldHu(tmpCards)){

tmpCards.clear();

return true;

}

tmpCards.clear();

}

return false;

}finally{

numMap.clear();

tmpList.clear();

}

}

/**

* 去掉一个对子后,是否是能胡牌的类型

* @param cards

* @return

*/

private static boolean couldHu(Listcards){

//分案

List> allKindsList = partKinds(cards);

for(ListcardList : allKindsList){

if(cardList.size() % MJConst.KEZHI_CARD_NUM != 0){

return false;

}

}

List> allDataList = new ArrayList>();

for(ListcardList : allKindsList){

//System.out.println("cardList:" +cardList);

ListdataList = kindTypeConform(cardList);

//System.out.println("这一案组成顺子或该子:"+dataList);

if(dataList == null){

return false;

}

if(dataList.size() == 0){

return false;

}

allDataList.add(dataList);

}

return couldPolicyHu(allDataList);

}

/**

* 分案,把每案的牌区分出来

* @param cardList

* @return

*/

private static List> partKinds(ListcardList){

List> ret = new ArrayList>();

MajiangCard lastCard = null;

Listlist = null;

for(MajiangCard card : cardList){

if(lastCard == null){

lastCard = card;

list = new ArrayList();

ret.add(list);

}

if(card.reqType() == lastCard.reqType()){

lastCard = card;

list.add(card);

}

else{

lastCard = card;

list = new ArrayList();

ret.add(list);

list.add(card);

}

}

return ret;

}

/**

* 是否可以胡牌

* @param allDataList 所有案牌的顺刻子数据

* @return

*/

private static boolean couldPolicyHu(List> allDataList){

if(allDataList.size() == 1){

for(KindTypeData ktd : allDataList.get(0)){

if(ktd.getOrderCnt() > 0 ){

//至少有一个顺子

return true;

}

}

}

//2是胡牌案的数量

else if(allDataList.size() >= 2){

for(Listlist : allDataList){

for(KindTypeData ktd : list){

if(ktd.getOrderCnt() > 0){

return true;

}

}

}

}

return false;

}

/**

* 将同一案的牌组合成刻子或顺子

* @param cards

* @return

*/

private static ListkindTypeConform(Listcards){

Listret = new ArrayList();

MapnumMap = MJCommonFuncs.transCardsToMap(cards);

//先找刻子

int cardSerValue = MJCommonFuncs.filtCardMinNum(numMap, MJConst.KEZHI_CARD_NUM);

//刻子牌

ListkezhiValueList = new ArrayList();

while(cardSerValue != 0){

kezhiValueList.add(cardSerValue);

numMap.remove(cardSerValue);

cardSerValue = MJCommonFuncs.filtCardMinNum(numMap, MJConst.KEZHI_CARD_NUM);

}

if(kezhiValueList.size() > 0){

//有刻子牌

List> sublist = MJCommonFuncs.getSubset(kezhiValueList);

for(Listlist : sublist){

ListcpCards = MJCommonFuncs.cpList(cards);

MJCommonFuncs.removeByCardValue(cpCards, list, MJConst.KEZHI_CARD_NUM);

//取得顺子数量

int cardsCnt = cpCards.size();

int orderCnt = getOrderCnt(cpCards);

if(orderCnt != cardsCnt / MJConst.ORDER_CARD_NUM){

cpCards.clear();

continue;

}

KindTypeData ktd = new KindTypeData();

ktd.setOrderCnt(orderCnt);

ktd.setKezhiCnt(list.size());

ret.add(ktd);

}

sublist.clear();

}

else{

//没有刻子牌

ListcpCards = MJCommonFuncs.cpList(cards);

int cardsCnt = cpCards.size();

int orderCnt = getOrderCnt(cpCards);

if(orderCnt != cardsCnt / MJConst.ORDER_CARD_NUM){

cpCards.clear();

return ret;

}

KindTypeData ktd = new KindTypeData();

ktd.setOrderCnt(orderCnt);

ret.add(ktd);

}

kezhiValueList.clear();

numMap.clear();

return ret;

}

/**

* 取得顺子数量

* @param cardList

* @return

*/

private static int getOrderCnt(ListcardList){

if(cardList.size() < MJConst.ORDER_CARD_NUM){

return 0;

}

if(cardList.get(0).reqType() == MJUtil.CARD_TYPE_WORD){

//字,没有顺

return 0;

}

int ret = 0;

while(removeOrderCards(cardList)){

ret ++;

}

return ret;

}

/**

* 去掉一个顺子牌

* @param cardList

* @return 是否去除成功

*/

private static boolean removeOrderCards(ListcardList){

int len = cardList.size();

if(len < MJConst.ORDER_CARD_NUM){

return false;

}

MajiangCard last = cardList.remove(len - 1);

int cnt = 2;

for(int i = len - 2; i >= 0; i--){

if(cardList.get(i).reqValue() + 1 == last.reqValue()){

last = cardList.remove(i);

cnt --;

if(cnt == 0){

return true;

}

continue;

}

if(cardList.get(i).reqValue() == last.reqValue()){

continue;

}

else{

return false;

}

}

return false;

}

/**

* 同一案牌中的类型数据

* @author skymr

*

*/

private final static class KindTypeData{

//刻子数量

private int kezhiCnt;

//顺子数量

private int orderCnt;

//剩下的散牌数量

private int leftCardNum;

public int getKezhiCnt() {

return kezhiCnt;

}

public void setKezhiCnt(int kezhiCnt) {

this.kezhiCnt = kezhiCnt;

}

public int getOrderCnt() {

return orderCnt;

}

public void setOrderCnt(int orderCnt) {

this.orderCnt = orderCnt;

}

public int getLeftCardNum() {

return leftCardNum;

}

public void setLeftCardNum(int leftCardNum) {

this.leftCardNum = leftCardNum;

}

@Override

public String toString() {

return "KindTypeData [kezhiCnt=" + kezhiCnt + ", orderCnt=" + orderCnt + "]";

}

}

}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java麻将算法_Java实现的麻将胡牌算法 的相关文章

随机推荐