目录
百度百科:
玩法介绍:
贰柒拾的玩法有很多种,主要有“乐山贰柒拾”,“犍为贰柒拾”,“眉山贰柒拾”,“四十张三人”,“两人贰柒拾”等,不同玩法之间其核心的打牌逻辑都是相同的,区别在于一些算分和番型不同而已。具体的打牌规则和各玩法介绍,由于篇幅较大,对核心的处理逻辑没有影响,这里就不做过多的介绍。
核心算法:
温馨提示:本文主要对胡牌逻辑进行分析,想要理解算法,请务必先学会打牌规则及玩法。
1. 编号&获取
编号:首先需要分别将红黑牌进行编号,因为没有压牌规则,所以不同花色可以单独编组。如红牌1-10 、黑牌11-20,这里建议通过一个花色码进行移位编号。
获取:寻找牌值时,需根据花色与牌值进行寻找。
2. 吃 & 摆
单独的吃操作其实很简单,但贰柒拾的吃操作之前,必须先对摆操作进行校验,摆操作和吃操作的都是一样的牌型,只不过多了一层约束。首先,根据目标牌寻找手牌中可以吃的组合,检查目标牌是否存在?
--存在:进入检查摆牌逻辑,如果摆牌成功,即可吃,如果摆牌失败,即不能吃
--不存在:可直接吃
3. 对(碰)
检查手牌有且只有两张时可进行对操作
4、开(杠,下雨)
检查手牌有且只有3张可进行开操作
5、胡 & 听牌提示
先对红黑牌进行分类并排序,然后进行组合判断,由于红牌的牌型胡数大于黑牌,所以先对红牌进行组合判断。这里以红牌为例,黑牌逻辑相同,不再赘述。
获取第一张牌,判断该牌是否为目标牌(进行标记),获取该牌的张数,根据不同的张数组成不同的“组合”,张数可能如下:
1、4张,可组成一磙
2、3张,可组成一坎(包含目标牌则可组成对)
3、1&2张,可组成吃,吃的话需要去寻找相邻的牌(包括2710)(这里涉及到红吃黑,所以也需要去黑牌里找)
如能组合成功,将组合成功的牌全部移除,然后再取一张,重复如此,直至牌全部移除(红黑),则可胡。
如其递归过程出现组合失败,则目标牌不可胡。退出判断
4、胡牌之后判断番型胡数,可在组合判断的过程对一些牌型进行收集,如圈牌,胡数,2710,坤,漂,天,地等。
代码:(java)
/**
* 胡牌检查
*
* @param result
* @param
* @return
*/
public static ErQiShiTingResult realCheckHu(ErQiShiTingResult result) {
if (result.getZhuCard().size() == 0 && result.getFuCard().size() == 0) {
if (result.getYouNum() >= result.getNeedYouNum()) {
result.setHu(true);
}
return result;
}
List<Byte> zhuCard = result.getZhuCard();
Byte card = result.getCard();
ErQiShiTingResult r;
if (zhuCard.size() > 0) {
Byte one = zhuCard.get(0);
int oneNum = getCardNumInList(one, zhuCard);
if (oneNum == 4) {
if (one == card) {
// 三张摸一张的情况
// r = removeLianZi(copyResult, one);
// if (r.isHu()) {
// return r;
// }
return removeGunKai(result, one);
} else {
// 判断磙
return removeGun(result, one);
}
} else if (oneNum == 3) {
if (one == card) {
// 根据标识和圈牌 判断优先算圈胡还是算二七十
if (result.isFlag() && card == result.getQuanCard()) {
r = removeDuiZi(result, one);
if (r.isHu()) {
return r;
}
r = removeErQiShi(result, one);
if (r.isHu()) {
return r;
}
} else {
r = removeErQiShi(result, one);
if (r.isHu()) {
return r;
}
r = removeDuiZi(result, one);
if (r.isHu()) {
return r;
}
}
r = selectMaxHu(result, one);
if (r.isHu()) {
return r;
}
// r = removeZhuangZi(result, one);
// if (r.isHu()) {
// return r;
// }
//
// r = removeDazi1(result, one);
// if (r.isHu()) {
// return r;
// }
//
// r = removeLianZi(result, one);
// if (r.isHu()) {
// return r;
// }
} else {
// 判断坎
return removeKan(result, one);
}
} else if (oneNum == 2) {
r = removeErQiShi(result, one);
if (r.isHu()) {
return r;
}
r = selectMaxHu(result, one);
if (r.isHu()) {
return r;
}
// r = removeZhuangZi(result, one);
// if (r.isHu()) {
// return r;
// }
//
// r = removeDazi1(result, one);
// if (r.isHu()) {
// return r;
// }
//
// r = removeLianZi(result, one);
// if (r.isHu()) {
// return r;
// }
} else if (oneNum == 1) {
r = removeErQiShi(result, one);
if (r.isHu()) {
return r;
}
r = removeLianZi(result, one);
if (r.isHu()) {
return r;
}
}
} else {
r = realCheckHu(result.swap());
if (r.isHu()) {
return r;
}
}
return result;
}