本文共 20933 字,大约阅读时间需要 69 分钟。
在前段时间开发了一款×××士游戏,前面已经说到过是采用PHP开发的,这此我将详细描述此算法的实现过程。
由于此游戏逻辑较简单,仅判断牛型大小、并对牛型进行比较,所以我决定采用type、num、count的结构来表示一张牌对象。如下:
10都作为10 */ function __construct($type, $num, $count) { $this->type = $type; $this->num = $num; $this->count = $count; } }?>
所以我们×××中获得的对象便是五个这样的对象构成的数组,以下是算法代码:
num > $cards[$j + 1]->num || ($cards[$j]->num == $cards[$j+1]->num && $cards[$j]->type < $cards[$j+1]->type)){ $t = $cards[$j]; $cards[$j] = $cards[$j+1]; $cards[$j+1] = $t; } } } } /** * @param $playerCards 玩家的手牌,这里假设的是以{玩家ID,Cards(array)}的方式传过来的数据 * @param $typeSelected 允许的可选牌型的数组,用于是否开启该牌型,包含数据为 * canShunDou: 能否顺斗; canKanDou: 能否坎斗 * canTongHuaShun: 能否同花顺 * canZhaDanNiu: 能否×××牛 * canWuXiaoNiu: 能否五小牛 * canWuHuaNiu: 能否五花牛 * canSiHuaNiu: 能否四花牛 * canHuLuNiu: 能否葫芦牛 * canTongHuaNiu: 能否同花牛 * canShunZiNiu: 能否顺子牛 * @return $resultArray 某一个玩家的结果数组,存放结果 * 'playerID' : 对应的玩家 * 'level': 牌的级别,按照同花顺 > 五小牛 > 五花牛 > 四花牛 > ×××牛 > 葫芦牛 > 同花 * > 顺子 > ××× > 牛9-牛5 > 牛4-牛1 > 无牛进行排列 * 注意:坎斗、顺斗以及普通牛是同一级别,都看点数 * 'levelResult': 牌的级别对应的最大牌,用于同级别的判断 * */ public function getNiuniuResult($playerCards, $typeSelected){ $resultArray = array();//array('playerID'=>'', 'level'=>0, 'levelResult'=>''); for($i = 0; $i < count($playerCards); $i++){ //初始化一个基本结果,然后和所有数据判断 $resultArray[$i]['playerID'] = $playerCards[$i]['playerID']; $resultArray[$i]['level'] = -1; $resultArray[$i]['levelResult'] = ''; $resultArray[$i]["douPai"]=array(); //保存一个临时牌组,并按从小到大排序 $cards = $playerCards[$i]['cards']; $this->sortPlayerCards($cards); //获取普通牛数据 $r = $this->getNiuniuCount($cards); $this->proce***esult($resultArray[$i], $r); if($typeSelected['canShunDou']){ //获取顺斗的数据 $r = $this->getShunDouPoint($cards); $this->proce***esult($resultArray[$i], $r); } if($typeSelected['canCanDou']){ //获取豹子牛数据 $r = $this->getBaoZhiNiuPoint($cards); if($r["level"]==BAOZHINIU){ $this->proce***esult($resultArray[$i], $r); } } //可能出错 if($typeSelected['canWuHuaNiu']){ //获取五花牛 $r = $this->isWuHuaNiu($cards); if($r["level"]==WUHUANIU){ $this->proce***esult($resultArray[$i], $r); } } if($typeSelected['canShunZiNiu']){ //获取顺子牛数据 $r = $this->isShunZiNiu($cards); if($r["level"]==SHUNZINIU){ $this->proce***esult($resultArray[$i], $r); } } if($typeSelected['canTongHuaNiu']){ //获取同花牛 $r = $this->isTonghuaNiu($cards); if($r["level"]==TONGHUANIU){ $this->proce***esult($resultArray[$i], $r); } } if($typeSelected['canHuLuNiu']){ //获取葫芦牛 $r = $this->huluNiu($cards); if($r["level"]==HULUNIU){ $this->proce***esult($resultArray[$i], $r); } } if($typeSelected['canZhaDanNiu']){ //获取×××牛 $r = $this->isBoomNiu($cards); if($r["level"]==ZHADANNIU){ $this->proce***esult($resultArray[$i], $r); } } if($typeSelected['canWuXiaoNiu']){ //获取五小牛 $r = $this->isWuXiaoNiu($cards); if($r["level"]==WUXIAONIU){ $this->proce***esult($resultArray[$i], $r); } } if($typeSelected['canTongHuaShun']){ //获取同花顺 $r = $this->isTongHuaShun($cards); if($r["level"]==TONGHUASHUN){ $this->proce***esult($resultArray[$i], $r); } } } return $resultArray; } private function proce***esult(&$playerResult, $newResult){ if($playerResult['level'] < $newResult['level']){ $playerResult['level'] = $newResult['level']; $playerResult['levelResult'] = $newResult['maxCard']; $playerResult['douPai'] = $newResult['douPai']; } } /** * 判断×××点数 * @param $playerCards 玩家的手牌,这里假设的是以玩家ID=》Cards(array)的方式传过来的数据 * @return $array:[level:牌力,maxCard: 最大牌] */ public function getNiuniuCount($playerCard){ $result = array(); $result['douPai']=array(); //总点数 $cardsTotalPoint = 0; //计算总点数 for($i = 0; $i < count($playerCard); $i++){ $cardsTotalPoint += $playerCard[$i]->count; } //计算余数 $lave = $cardsTotalPoint % 10; for($i = 0; $i < count($playerCard) - 1; $i++){ for($j = $i + 1; $j < count($playerCard); $j++){ if(($playerCard[$i]->count + $playerCard[$j]->count) % 10 == $lave){ //此处是有牛,则取出斗的牌 if($i!=0&&$j!=0){ array_push($result["douPai"],$playerCard[0]); } if($i!=1&&$j!=1){ array_push($result["douPai"],$playerCard[1]); } if($i!=2&&$j!=2){ array_push($result["douPai"],$playerCard[2]); } if($i!=3&&$j!=3){ array_push($result["douPai"],$playerCard[3]); } if($i!=4&&$j!=4){ array_push($result["douPai"],$playerCard[4]); } $result['level'] = $this->_getCount($lave); $result['maxCard'] = $playerCard[4]; return $result; } } } $result['level'] = WUNIU; $result['maxCard'] = $playerCard[4]; return $result; } /* * 辅助函数,用于处理牛1-牛9的细分结果处理 * @param $lave: getNiuniuCount的余数结果 */ private function _getCount($lave) { switch ($lave) { case 0: return NIUNIU; case 1: return NIUNIU1; case 2: return NIUNIU2; case 3: return NIUNIU3; case 4: return NIUNIU4; case 5: return NIUNIU5; case 6: return NIUNIU6; case 7: return NIUNIU7; case 8: return NIUNIU8; case 9: return NIUNIU9; default: return -1; } } /** * 判断是否为五花牛的函数 * @param $playerCard 某一个玩家的手牌 * @return $array:[level: 牌力,maxCard: 最大牌] */ private function isWuHuaNiu($playerCard){ $result = array('level'=>-1, 'maxCard'=>'','douPai'=>array()); for($i = 0; $i < count($playerCard); $i++){ if($playerCard[$i]->num <= 10){ return $result; } } $result['level'] = WUHUANIU; $result['maxCard'] = $playerCard[4]; $result['douPai'] = $playerCard; return $result; } /** * 判断是否为同花牛的函数 * @param $playerCard 某一个玩家的手牌 * @return $array:[level:牌力,maxCard: 最大牌] */ private function isTonghuaNiu($playerCard){ $result = array('level'=>-1, 'maxCard'=>'','douPai'=>array()); $type = $playerCard[0]->type; $isTonghua = true; for($i = 1; $i < count($playerCard); $i++){ if($type != $playerCard[$i]->type){ $isTonghua = false; break; } } if($isTonghua){ $result['level'] = TONGHUANIU; $result['maxCard'] = $playerCard[4]; $result['douPai'] = $playerCard; } return $result; } /** * 判断是否为同花顺牛的函数 * @param $playerCard * @return array:[level:牌力, maxCard: 同花顺的最大牌] */ private function isTongHuaShun($playerCard){ $result = array('level'=>-1, 'maxCard'=>'','douPai'=>array()); $r1 = $this->isTonghuaNiu($playerCard); $r2 = $this->isShunZiNiu($playerCard); if($r1['level'] == TONGHUANIU && $r2['level'] == SHUNZINIU){ $result['level'] = TONGHUASHUN; $result['maxCard'] = $playerCard[4]; $result['douPai'] = $playerCard; } return $result; } /** * 判断是否为×××牛的函数 * @param $playerCard 某一个玩家的手牌 * @return $array:[level:牌力,maxCard: ×××牌] */ private function isBoomNiu($playerCard){ $result = array('level'=>-1, 'maxCard'=>'','douPai'=>array()); //假设牌已经按照从小到大排序 //aaaa* if($playerCard[0]->num == $playerCard[3]->num){ $result['level'] = ZHADANNIU; $result['maxCard'] = $playerCard[0]; array_push($result["douPai"],$playerCard[0]); array_push($result["douPai"],$playerCard[1]); array_push($result["douPai"],$playerCard[2]); array_push($result["douPai"],$playerCard[3]); } //*aaaa else if($playerCard[1]->num == $playerCard[4]->num){ $result['level'] = ZHADANNIU; $result['maxCard'] = $playerCard[1]; array_push($result["douPai"],$playerCard[1]); array_push($result["douPai"],$playerCard[2]); array_push($result["douPai"],$playerCard[3]); array_push($result["douPai"],$playerCard[4]); } else{ $result['level'] = -1; $result['maxCard'] = ''; $result["douPai"]=array(); } return $result; } /** * 判断是否为五小牛的函数 * @param $playerCard 某一个玩家的手牌 * @return $array:[level:是否为五小牛, maxCard:最大的卡牌] */ private function isWuXiaoNiu($playerCard){ $result = array('level'=>-1, 'maxCard'=>'','douPai'=>array()); $totalCount = 0; for($i = 0; $i < count($playerCard); $i++){ if($playerCard[$i]->num > 5){ return $result; } else{ $totalCount += $playerCard[$i]->num; } } if($totalCount <= 10 && $totalCount > 0){ $result['level'] = WUXIAONIU; $result['maxCard'] = $playerCard[4]; $result["douPai"]=$playerCard; } return $result; } /** * 判断是否为葫芦牌型的函数 * @param $playerCard 某一个玩家的手牌 * @return $array: [level:是否为葫芦牛, maxCard:葫芦的点数最大牌] */ private function huluNiu($playerCard){ $result = array('level'=>-1, 'maxCard'=>0,'douPai'=>array()); //aaabb if($playerCard[0]->num == $playerCard[2]->num){ if($playerCard[3]->num == $playerCard[4]->num){ $result['level'] = HULUNIU; $result['maxCard'] = $playerCard[0]; array_push($result["douPai"],$playerCard[0]); array_push($result["douPai"],$playerCard[1]); array_push($result["douPai"],$playerCard[2]); } } //aabbb if($playerCard[2]->num == $playerCard[4]->num){ if($playerCard[0]->num == $playerCard[1]->num){ $result['level'] = HULUNIU; $result['maxCard'] = $playerCard[2]; array_push($result["douPai"],$playerCard[2]); array_push($result["douPai"],$playerCard[3]); array_push($result["douPai"],$playerCard[4]); } } return $result; } /** * 判断是否为四花型的函数 * @param $playerCard 某一个玩家的手牌 * @return $array:[level:是否为四花牛, maxCard:四花的最大牌] */ private function isSiHuaNiu($playerCard){ $result = array('level'=>-1, 'maxCard'=>''); $temp = true; for($i = 0; $i < count($playerCard); $i++){ if($playerCard[$i]->num < 10){ $temp = false; break; } } if($playerCard[0]->num == 10 && $temp){ $result['level'] = SIHUANIU; $result['maxCard'] = $playerCard[4]; } return $result; } /** * 判断是否为顺子牛的函数 * @param $playerCard 某一个玩家的手牌 * @return $array:[level:是否为顺子牛, maxCard:顺子牛的最大牌] */ private function isShunZiNiu($playerCard){ $result = array('level'=>-1, 'maxCard'=>'','douPai'=>array()); //abcde $temp=$playerCard[0]->num; $num=0; if($temp==1){ //第一张为A //a 2 3 4 5 if($playerCard[1]->num==2){ $num++; for($i=2;$i<5;$i++){ if($playerCard[$i]->num-$i==$temp){ $num++; }else{ return $result; } } }else if($playerCard[1]->num==10){ $num++; for($i=2;$i<5;$i++){ if($playerCard[$i]->num-$i+1==10){ $num++; }else{ return $result; } } } //10 J Q K A }else{ for($i=1;$i<5;$i++){ if($playerCard[$i]->num-$i==$temp){ $num++; }else{ return $result; } } } if($num==4){ $result['level'] = SHUNZINIU; $result['maxCard'] = $playerCard[4]; array_push($result["douPai"],$playerCard); }// if($playerCard[0]->num + 4 == $playerCard[4]->num){// $result['level'] = SHUNZINIU;// $result['maxCard'] = $playerCard[4];// } return $result; } /** * 获取是否为豹子牛的函数 */ private function getBaoZhiNiuPoint($playerCard){ $result = array('level'=>-1, 'maxCard'=>'','douPai'=>array()); //aaa** if($playerCard[0]->num == $playerCard[2]->num){ //$count = $playerCard[3]->point + $playerCard[4]->point; $result['level'] = BAOZHINIU; $result['maxCard'] = $playerCard[4]; array_push($result["douPai"],$playerCard[0]); array_push($result["douPai"],$playerCard[1]); array_push($result["douPai"],$playerCard[2]); } //*aaa* else if($playerCard[1]->num == $playerCard[3]->num){ //$count = $playerCard[0]->point + $playerCard[4]->point; $result['level'] = BAOZHINIU; $result['maxCard'] = $playerCard[4]; array_push($result["douPai"],$playerCard[1]); array_push($result["douPai"],$playerCard[2]); array_push($result["douPai"],$playerCard[3]); } //**aaa else if($playerCard[2]->num == $playerCard[4]->num){ //$count = $playerCard[0]->point + $playerCard[1]->point; $result['level'] = BAOZHINIU; $result['maxCard'] = $playerCard[1]; array_push($result["douPai"],$playerCard[2]); array_push($result["douPai"],$playerCard[3]); array_push($result["douPai"],$playerCard[4]); } //else{ //$count = -1; //} //$count = $count % 10; //$result['level'] = BAOZHINIU; return $result; } /** * 获取是否为坎斗的函数 * @param $playerCard 某一个玩家的手牌 * @return $result:[level:坎斗形成的点数, maxCard: 坎斗中的最大牌] */ private function getKanDouPoint($playerCard){ $result = array('level'=>-1, 'maxCard'=>''); //aaa** if($playerCard[0]->num == $playerCard[2]->num){ $count = $playerCard[3]->point + $playerCard[4]->point; $result['maxCard'] = $playerCard[4]; } //*aaa* else if($playerCard[1]->num == $playerCard[3]->num){ $count = $playerCard[0]->point + $playerCard[4]->point; $result['maxCard'] = $playerCard[4]; } //**aaa else if($playerCard[2]->num == $playerCard[4]->num){ $count = $playerCard[0]->point + $playerCard[1]->point; $result['maxCard'] = $playerCard[1]; } else{ $count = -1; } $count = $count % 10; $result['level'] = $this->_getCount($count); return $result; } /** * 获取是否为顺斗的函数 * @param $playerCard 某一个玩家的手牌 * @return $result:[level:顺斗形成的点数, maxCard: 顺斗中的最大牌] */ private function getShunDouPoint($playerCard){ $result = array('level'=>-1, 'maxCard'=>'','douPai'=>array()); //枚举所有情况产生点数的数组 $tempResult = array(); //第一种情况abc** if( ($playerCard[0]->num+1 == $playerCard[1]->num) && ($playerCard[1]->num == $playerCard[2]->num - 1)){ $r=array(); array_push($r,$playerCard[0]); array_push($r,$playerCard[1]); array_push($r,$playerCard[2]); array_push($tempResult, array('level'=>($playerCard[3]->count + $playerCard[4]->count)%10, 'maxCard'=>$playerCard[4],'douPai'=>$r)); } //第二种情况*abc* if (($playerCard[1]->num+1 == $playerCard[2]->num) && ($playerCard[2]->num == $playerCard[3]->num - 1)){ $r=array(); array_push($r,$playerCard[1]); array_push($r,$playerCard[2]); array_push($r,$playerCard[3]); array_push($tempResult, array('level'=>($playerCard[0]->count + $playerCard[4]->count)%10, 'maxCard'=>$playerCard[4],'douPai'=>$r)); } //第三种情况**abc if (($playerCard[2]->num+1 == $playerCard[3]->num) && ($playerCard[3]->num == $playerCard[4]->num - 1)){ $r=array(); array_push($r,$playerCard[2]); array_push($r,$playerCard[3]); array_push($r,$playerCard[4]); array_push($tempResult, array('level'=>($playerCard[0]->count + $playerCard[1]->count)%10, 'maxCard'=>$playerCard[4],'douPai'=>$r)); } //第四种情况abbc* if ($playerCard[0]->num+2 == $playerCard[3]->num && $playerCard[0]->num + 1 == $playerCard[1]->num){ $r=array(); array_push($r,$playerCard[0]); array_push($r,$playerCard[1]); array_push($r,$playerCard[3]); array_push($tempResult, array('level'=>($playerCard[4]->count + $playerCard[1]->count)%10, 'maxCard'=>$playerCard[4],'douPai'=>$r)); } //第五种情况*bccd; if($playerCard[1]->num+2 == $playerCard[4]->num && $playerCard[3]->num + 1 == $playerCard[4]->num) { $r=array(); array_push($r,$playerCard[1]); array_push($r,$playerCard[2]); array_push($r,$playerCard[4]); array_push($tempResult, array('level'=>($playerCard[0]->count + $playerCard[2]->count)%10, 'maxCard'=>$playerCard[3],'douPai'=>$r)); } //第六种情况aabbc; if(($playerCard[0]->num+1 == $playerCard[2]->num) && ($playerCard[2]->num+1 == $playerCard[4]->num)){ $r=array(); array_push($r,$playerCard[0]); array_push($r,$playerCard[2]); array_push($r,$playerCard[4]); array_push($tempResult, array('level'=>($playerCard[0]->count + $playerCard[2]->count)%10, 'maxCard'=>$playerCard[3],'douPai'=>$r)); } //第七种情况abbcc if(($playerCard[0]->num+1 == $playerCard[2]->num) && ($playerCard[2]->num+1 == $playerCard[4]->num)){ $r=array(); array_push($r,$playerCard[0]); array_push($r,$playerCard[1]); array_push($r,$playerCard[3]); array_push($tempResult, array('level'=>($playerCard[1]->count + $playerCard[3]->count)%10, 'maxCard'=>$playerCard[4],'douPai'=>$r)); } //第8种情况abbbc if($playerCard[0]->num+2 == $playerCard[4]->num && $playerCard[0]->num + 1 == $playerCard[1]->num) { $r=array(); array_push($r,$playerCard[0]); array_push($r,$playerCard[1]); array_push($r,$playerCard[4]); array_push($tempResult, array('level'=>($playerCard[1]->count * 2)%10, 'maxCard'=>$playerCard[3],'douPai'=>$r)); } //有可能没有结果,直接返回 if(count($tempResult) == 0){ return $result; } //获取最大的可能性结果返回 $level = $tempResult[0]['level']; $index = 0; for($i = 1; $i < count($tempResult); $i++){ if($tempResult[$i]['level'] > $level){ $index = $i; } } //echo $tempResult[$index]['level']; $result['level'] = $this->_getCount($tempResult[$index]['level'] % 10 ); $result['maxCard'] = $tempResult[$index]['maxCard']; $result['douPai'] = $tempResult[$index]['douPai']; return $result; }}?>
基本思路便是把传进来的五张牌对象进行升序排列后,判断可能出现的情况,得到最后的牛型以及确定此牛型相关的牌(斗)。
转载于:https://blog.51cto.com/13563193/2064888