闲来无事,再把全套麻将算番代码贴出,供有缘人参考,该算法以标准的国标麻将81种番编写,并严格遵守5大算番规则,不重复原则,不拆移原则,不得相同的原则,就高不就低原则,套算一次原则。
<?php
/**
* Created by PhpStorm.
* User: guochao<gc_mike@163.com>
* Date: 18/10/10
* Time: 下午3:30
*/
namespace components\mahjongAi;
use components\Utility;
/**
*
* 算番规则.
* 1.不重复原则
当某个番种,由于组牌的条件所决定,在其成立的同时,必然并存着其他番种,则其他番种不重复计分。
2.不拆移原则
确定一个番种后,不能将其自身再拆开互相组成新的番种计分。
3.不得相同的原则
凡已组合过某一番种的牌,不能再同其他一副牌组成相同的番种计分
4.就高不就低原则
有两副以上的牌,有可能组成两个以上的番种,而只能选其中一种计分时,可选择分高的番种计分。
5.套算一次原则
如有尚未组合过的一副牌,只可同已组合过的相应一副牌套算一次。
*
*
* Class MJCalcScoring
* @package app\components
*/
class MJCalcScoring extends MJBase{
private static $_handCards;
private static $_knownCards;
private static $_handCardsCountMap;
private static $_splitArr;
/**
* 和牌所用到的参数.
* @var $params = [
* 'is_last_card' => 1,
* 'is_zi_mo' => 1,
* 'is_gang_mo_pai' => 0,
* 'is_qiang_gang_hu' => 0,
* 'ming_gang_count' => 0,
* 'an_gang_count' => 0,
* 'is_hu_jue_zhang' => 0,
* 'men_fen' => 2,
* 'quan_fen' => 1,
* 'hu_card' => 11,
* 'is_ting' => 0,
* 'flower_count' => 1
* ]
*/
private static $_params;
/**
* 构造方法.
*
* @param $handCards
* @param $knownCards
*/
public function __construct($handCards,$knownCards = [],$params = [], $isSplitCard = true){
sort($handCards);
self::$_handCards = $handCards;
self::$_knownCards = $knownCards;
if(!empty($knownCards)){
array_walk_recursive($knownCards, function($value) use (&$handCards) {
array_push($handCards, $value);
});
}
self::$_handCardsCountMap = array_count_values($handCards);
if($isSplitCard){
self::$_splitArr = $this->_splitCard();
echo "===========拆牌结果==================\n";
print_r(self::$_splitArr);
echo "=============================\n";
}
self::$_params = $params;
}
/**
* 算番.
*/
public function calHandCardsPoints(){
$fanCateList = [];
if($this->_isDaSiXi()){
$fanCateList[] = self::F_DaSiXi;
}elseif($this->_isDaSanYuan()){
$fanCateList[] = self::F_DaSanYuan;
}elseif($this->_isShiSanYao()){
$fanCateList[] = self::F_ShiSanYao;
}elseif($this->_isJiuLianBaoDeng()){
$fanCateList[] = self::F_JiuLianBaoDeng;
}elseif($this->_isLianQiDui()){
$fanCateList[] = self::F_LianQiDui;
}elseif($this->_isLvYiSe()){
$fanCateList[] = self::F_LvYiSe;
}elseif($this->_isSiGang()){
$fanCateList[] = self::F_SiGang;
}elseif($this->_isXiaoSanYuan()){
$fanCateList[] = self::F_XiaoSanYuan;
}elseif($this->_isXiaoSiXi()){
$fanCateList[] = self::F_XiaoSiXi;
}elseif($this->_isQingYaoJiu()){
$fanCateList[] = self::F_QingYaoJiu;
}elseif($this->_isYiSeShuangLongHui()){
$fanCateList[] = self::F_YiSeShuangLongHui;
}elseif($this->_isZiYiSe()){
$fanCateList[] = self::F_ZiYiSe;
}elseif($this->_isSiAnKe()){
$fanCateList[] = self::F_SiAnKe;
}elseif($this->_isYiSeSiJieGao()){
$fanCateList[] = self::F_YiSeSiJieGao;
}elseif($this->_isYiSeSiTongShun()){
$fanCateList[] = self::F_YiSeSiTongShun;
}elseif($this->_isYiSeSiBuGao()){
$fanCateList[] = self::F_YiSeSiBuGao;
}elseif(!in_array(self::F_ShiSanYao,$fanCateList) && $this->_isHunYaoJiu()){
$fanCateList[] = self::F_HunYaoJiu;
}elseif(empty(array_intersect([self::F_SiGang],$fanCateList)) && $this->_isSanGang()){
$fanCateList[] = self::F_SanGang;
}elseif(empty(array_intersect([self::F_SiGang,self::F_YiSeShuangLongHui],$fanCateList)) && $this->_isQiDui()){
$fanCateList[] = self::F_QiDui;
}elseif($this->_isQiXingBuKao()){
$fanCateList[] = self::F_QiXingBuKao;
}elseif($this->_isQuanShuangKe()){
$fanCateList[] = self::F_QuanShuangKe;
}elseif($this->_isQuanDa()){
$fanCateList[] = self::F_QuanDa;
}elseif($this->_isQuanZhong()){
$fanCateList[] = self::F_QuanZhong;
}elseif(empty(array_intersect([self::F_YiSeSiTongShun,self::F_YiSeSanTongShun],$fanCateList)) && $this->_isYiSeSanJieGao()){
$fanCateList[] = self::F_YiSeSanJieGao;
}elseif(empty(array_intersect([self::F_YiSeSiJieGao,self::F_YiSeSanJieGao],$fanCateList)) && $this->_isYiSeSanTongShun()){
$fanCateList[] = self::F_YiSeSanTongShun;
}elseif($this->_isQingLong()){
$fanCateList[] = self::F_QingLong;
}elseif($this->_isYiSeSanBuGao()){
$fanCateList[] = self::F_YiSeSanBuGao;
}elseif($this->_isSanSeShuangLongHui()){
$fanCateList[] = self::F_SanSeShuangLongHui;
}elseif($this->_isShiSanBuKao()){
$fanCateList[] = self::F_ShiSanBuKao;
}elseif($this->_isZhuHeLong()){
$fanCateList[] = self::F_ZhuHeLong;
}elseif(empty(array_intersect([self::F_DaSiXi,self::F_XiaoSiXi],$fanCateList)) && $this->_isSanFenKe()){
$fanCateList[] = self::F_SanFenKe;
}elseif($this->_isSanSeSanTongShun()){
$fanCateList[] = self::F_SanSeSanTongShun;
}elseif($this->_isSanSeSanJieGao()){
$fanCateList[] = self::F_SanSeSanJieGao;
}elseif($this->_isSanSeSanBuGao()){
$fanCateList[] = self::F_SanSeSanBuGao;
}
if($this->_isQuanXiao()){
$fanCateList[] = self::F_QuanXiao;
}
if(empty(array_intersect([self::F_JiuLianBaoDeng,self::F_QiDui,self::F_YiSeShuangLongHui],$fanCateList))){
if($this->_isQingYiSe()){
$fanCateList[] = self::F_QingYiSe;
}
}
if($this->_isQuanDaiWu()){
$fanCateList[] = self::F_QuanDaiWu;
}
if($this->_isSanAnKe()){
$fanCateList[] = self::F_SanAnKe;
}
if(empty(array_intersect([self::F_QingYaoJiu],$fanCateList))){
if($this->_isSanTongKe()){
$fanCateList[] = self::F_SanTongKe;
}
}
if($this->_isDaYvWu()){
$fanCateList[] = self::F_DaYvWu;
}
if($this->_isXiaoYvWu()){
$fanCateList[] = self::F_XiaoYvWu;
}
if($this->_isHuaLong()){
$fanCateList[] = self::F_HuaLong;
}
if($this->_isTuiBuDao()){
$fanCateList[] = self::F_TuiBuDao;
}
if($this->_isHaiDiLaoYue()){
$fanCateList[] = self::F_HaiDiLaoYue;
}
if($this->_isMiaoShouHuiChun()){
$fanCateList[] = self::F_MiaoShouHuiChun;
}
if($this->_isGangShangKaiHua()){
$fanCateList[] = self::F_GangShangKaiHua;
}
if($this->_isQiangGangHu()){
$fanCateList[] = self::F_QiangGangHu;
}
if(!in_array(self::F_LvYiSe,$fanCateList)){
if($this->_isHunYiSe()){
$fanCateList[] = self::F_HunYiSe;
}
}
if(empty(array_intersect([self::F_DaSiXi,self::F_SiGang,self::F_QingYaoJiu,self::F_ZiYiSe,self::F_SiAnKe,self::F_YiSeSiJieGao,self::F_HunYaoJiu,self::F_QuanShuangKe],$fanCateList))){
if($this->_isPengPengHu()){
$fanCateList[] = self::F_PengPengHu;
}
}
if(empty(array_intersect([self::F_ShiSanYao,self::F_QiXingBuKao,self::F_ShiSanBuKao],$fanCateList))){
if($this->_isWuMenQi()){
$fanCateList[] = self::F_WuMenQi;
}
}
if($this->_isQuanQiuRen()){
$fanCateList[] = self::F_QuanQiuRen;
}elseif(empty(array_intersect([self::F_QiDui,self::F_QiXingBuKao,self::F_ShiSanBuKao],$fanCateList)) && $this->_isBuQiuRen()){
$fanCateList[] = self::F_BuQiuRen;
}
if(empty(array_intersect([self::F_SanGang],$fanCateList)) && $this->_isShuangAnGang()){
$fanCateList[] = self::F_ShuangAnGang;
}elseif(empty(array_intersect([self::F_SiGang,self::F_SanGang],$fanCateList)) && $this->_isShuangMingGang()){
$fanCateList[] = self::F_ShuangMingGang;
}
if(!in_array(self::F_DaSanYuan,$fanCateList)){
if($this->_isShuangJianKe()){
$fanCateList[] = self::F_ShuangJianKe;
}
}
if(empty(array_intersect([self::F_QingYaoJiu,self::F_HunYaoJiu],$fanCateList))){
if($this->_isQuanDaiYao()){
$fanCateList[] = self::F_QuanDaiYao;
}
}
if(empty(array_intersect([self::F_QiangGangHu],$fanCateList))){
if($this->_isHuJueZhang()){
$fanCateList[] = self::F_HuJueZhang;
}
}
if(empty(array_intersect([self::F_QingYaoJiu,self::F_YiSeShuangLongHui,self::F_YiSeSiBuGao,self::F_SanSeShuangLongHui],$fanCateList))){
if($this->_isPingHu()){
$fanCateList[] = self::F_PingHu;
}
}
if(empty(array_intersect([self::F_QingYaoJiu,self::F_QuanShuangKe,self::F_QuanZhong,self::F_QuanDaiWu],$fanCateList))){
if($this->_isDuanYaoJiu()){
$fanCateList[] = self::F_DuanYaoJiu;
}
}
if(empty(array_intersect([self::F_YiSeSiTongShun],$fanCateList))){
if($this->_isSiGuiYi()){
$fanCateList[] = self::F_SiGuiYi;
}
}
if(empty(array_intersect([self::F_QingYaoJiu],$fanCateList))){
if($this->_isLiangTongKe()){
$fanCateList[] = self::F_LiangTongKe;
}
}
if(empty(array_intersect([self::F_SanAnKe],$fanCateList))){
if($this->_isShuangAnKe()){
$fanCateList[] = self::F_ShuangAnKe;
}
}
if(empty(array_intersect([self::F_ShiSanYao,self::F_SiAnKe,self::F_QiXingBuKao,self::F_ShiSanBuKao],$fanCateList))){
if($this->_isMenQing()){
$fanCateList[] = self::F_MenQing;
}
}
if(!in_array(self::F_DaSiXi,$fanCateList)){
if($this->_isMenFenKe()){
$fanCateList[] = self::F_MenFenKe;
}
}
// if(!in_array(self::F_DaSiXi,$fanCateList)){
// if($this->_isQuanFenke()){
// $fanCateList[] = self::F_QuanFenKe;
// }
// }
if(empty(array_intersect([self::F_DaSanYuan,self::F_ShuangJianKe],$fanCateList))){
if($this->_isJianke()){
$fanCateList[] = self::F_JianKe;
}
}
if(empty(array_intersect([self::F_SanGang,self::F_ShuangAnGang],$fanCateList))){
if($this->_isAnGang()){
$fanCateList[] = self::F_AnGang;
}
}
// 般逢老连
if(empty(array_intersect([self::F_YiSeShuangLongHui,self::F_YiSeSiTongShun,self::F_YiSeSiBuGao,self::F_SanSeShuangLongHui],$fanCateList))){
$sz = 0;
$szList = [];
foreach(self::$_splitArr as $item){
if(count($item) == 3 && $item[0] + 2 == $item[2]){
$szList[] = $item;
$sz ++;
}
}
$s = 0;
$logArr = [];
if(!empty($szList))for($i = 0; $i < $sz; $i ++){
for($j = $i + 1; $j <= $sz - 1; $j ++){
if($s == $sz - 1){
break 2;
}
$groupArr = [$szList[$i],$szList[$j]];
if(empty(array_intersect([self::F_YiSeSanTongShun],$fanCateList))){
if($this->_isYiBanGao($groupArr)){
if(isset($logArr[self::F_YiBanGao]) && $logArr[self::F_YiBanGao] == $groupArr){
continue;
}
$fanCateList[] = self::F_YiBanGao;
$logArr[self::F_YiBanGao] = $groupArr;
$s ++;
}
}
if($this->_isXiXiangFen($groupArr)){
if(isset($logArr[self::F_XiXiangFen]) && $logArr[self::F_XiXiangFen] == $groupArr){
continue;
}
$fanCateList[] = self::F_XiXiangFen;
$logArr[self::F_XiXiangFen] = $groupArr;
$s ++;
}
if(empty(array_intersect([self::F_QiDui],$fanCateList))){
if(isset($logArr[self::F_LianLiu]) && $logArr[self::F_LianLiu] == $groupArr){
continue;
}
if($this->_isLianLiu($groupArr)){
$fanCateList[] = self::F_LianLiu;
$logArr[self::F_LianLiu] = $groupArr;
$s ++;
}
}
if($this->_isLaoShaoPei($groupArr)){
if(isset($logArr[self::F_LaoShaoPei]) && $logArr[self::F_LaoShaoPei] == $groupArr){
continue;
}
$fanCateList[] = self::F_LaoShaoPei;
$logArr[self::F_LaoShaoPei] = $groupArr;
$s ++;
}
}
}
}
if(empty(array_intersect([self::F_TuiBuDao],$fanCateList))){
if($this->_isQueYiMen()){
$fanCateList[] = self::F_QueYiMen;
}
}
// 箭刻不计幺九刻
if(empty(array_intersect([self::F_DaSiXi,self::F_QingYaoJiu,self::F_XiaoSiXi,self::F_HunYaoJiu],$fanCateList))){
if($this->_isYaoJiuKe()){
$fanCateList[] = self::F_YaoJiuKe;
}
}
if(empty(array_intersect([self::F_QingYaoJiu,self::F_YiSeShuangLongHui,self::F_QingYiSe,self::F_QuanDa,self::F_QuanZhong,self::F_QuanXiao,self::F_SanSeShuangLongHui,self::F_DaYvWu,self::F_XiaoYvWu],$fanCateList))){
if($this->_isWuZi()){
$fanCateList[] = self::F_WuZi;
}
}
if(empty(array_intersect([self::F_SiGang,self::F_SanGang,self::F_ShuangMingGang],$fanCateList))){
if($this->_isMingGang()){
$fanCateList[] = self::F_MingGang;
}
}
if($this->_isBianZhang()){
$fanCateList[] = self::F_BianZhang;
}elseif($this->_isKanZhang()){
$fanCateList[] = self::F_KanZhang;
}
if(empty(array_intersect([self::F_ShiSanYao,self::F_SiGang,self::F_QiDui,self::F_QiXingBuKao,self::F_ShiSanBuKao,self::F_QuanQiuRen],$fanCateList))){
if($this->_isDanDiao()){
$fanCateList[] = self::F_DanDiao;
}
}
if(empty(array_intersect([self::F_SiAnKe,self::F_MiaoShouHuiChun,self::F_GangShangKaiHua,self::F_BuQiuRen],$fanCateList))){
if($this->_isZiMo()){
$fanCateList[] = self::F_ZiMo;
}
}
// 一色三同顺、清龙、一色三步高、花龙、三色三同顺、三色三步高
if(array_intersect([self::F_YiSeSanTongShun,self::F_QingLong,self::F_YiSeSanBuGao,self::F_HuaLong,self::F_SanSeSanTongShun,self::F_SanSeSanBuGao],$fanCateList)){
$isHasBFLL = false;
foreach($fanCateList as $fanName){
if(in_array($fanName,[self::F_YiBanGao,self::F_XiXiangFen,self::F_LaoShaoPei,self::F_LianLiu])){
if($isHasBFLL){
array_splice($fanCateList,array_search($fanName,$fanCateList),1);
continue;
}
$isHasBFLL = true;
}
}
}
// 无番和
if(empty($fanCateList) && self::$_params['is_ting'] == 0){
$fanCateList[] = self::F_WuFanHu;
}
if(self::$_params['is_ting'] == 1){
$fanCateList[] = self::F_TingCard;
}
if(self::$_params['flower_count'] > 0){
$fanCateList[] = self::F_FlowerCard;
}
// 格式化番种类
$result = [];
$totalScore = 0;
foreach($fanCateList as $key => $fanName){
$score = Utility::recursive_array_search($fanName,self::$fanScoreMap);
$result[$key]['fan_name'] = self::$fanNameMap[$fanName];
if($fanName == self::F_FlowerCard){
$result[$key]['score'] = self::$_params['flower_count'];
$score = self::