Приветствую тебя, разработчик или случайно зашедший на огонек в этот уютный технический бложек. Сегодня речь пойдет о несколько математической задаче, хоть и немного там математики, да и она понятна школьнику 5го класса. Сегодня мы научимся распознавать комбинации в Техасском холдеме, именно в такую разновидность покера я играю (играл). Т.к. это очень простой класс на PHP, он не будет иметь определять старшинство одинаковых по названию комбинаций, но разнящихся по номиналу, к примеру стрит до 10 и стрит до 8 будут трактоваться этим классом, как просто стрит. В Техасском холдеме всего 10 комбинаций и мы с вами пройдемся от самой старшей из них – флеш рояль до самой младшей – старшая карта.
Флеш рояль
Высшая кобинация в покере – это стрит (стрейт) флеш до туза.
Это когда три карты одного достоинства и две другого. Не самая удачная реализация :)
1234567891011
protectedfunction_isFullHouse(){$ranks=$this->_ranks;sort($ranks);if((($ranks[0]==$ranks[1]&&$ranks[1]==$ranks[2])&&($ranks[3]==$ranks[4]))// 1=2=3 and 4=5||($ranks[0]==$ranks[1])&&($ranks[2]==$ranks[3]and$ranks[3]==$ranks[4]))// 1=2 and 3=4=5returntrue;returnfalse;}
Флеш
Все карты в комбинации должны быть одной масти. Проверяет все очень просто: сортируется массив с мастями и проверяется на равенство первая и последняя карты.
Вне зависимости от масти, достоинство карт должно быть по старшенству (5 подряд). Из-за того, что туз может в зависимости от ситуации быть и самой старшей, и самой младшей картой, пришлось сделать две проверки.
12345678910111213141516171819202122232425
protectedfunction_isStraight(){$ranks=$this->_ranks;sort($ranks);// if Ace is low card in straightif($key=array_search(14,$ranks)){$tempRanks=$ranks;unset($tempRanks[$key]);if(array(2,3,4,5)==$tempRanks){returntrue;}unset($tempRanks);}// if Ace is high card - default algorithm$min=$ranks[0];foreach($ranksas$key=>$value){$ranks[$key]-=$min;if($key!=$ranks[$key])returnfalse;}returntrue;}
Сет, трипс или тройка
Нужно наличие трех одинаковых карт. Алгоритм опять же далек от совершенства, но он выполняет свою работу.
Из название алгоритма должно быть понятно что к чему.
12345678910111213141516171819
protectedfunction_isTwoPairs(){$ranks=$this->_ranks;foreach($ranksas$key=>$rank){$testRanks=$ranks;unset($testRanks[$key]);sort($testRanks);if(($testRanks[0]==$testRanks[1])and($testRanks[2]==$testRanks[3])and($testRanks[0]!=$testRanks[2])// exclude full houseand($testRanks[0]!=$ranks[$key])and($testRanks[2]!=$ranks[$key]))returntrue;}returnfalse;}
Пара
Количество уникальных карт из пяти должно равняться четырем, если опять же я ничего не перепутал :).
<?php/** * @author vredniy.ru ***/classPoker{protected$_cards=array();//protected$_ranks=array();protected$_suits=array();publicfunction__construct(array$cards){$this->_cards=$cards;$rank=null;foreach($cardsas$card){switch(strtolower($card['rank'])){case't':$rank=10;break;case'j':$rank='11';break;case'q':$rank='12';break;case'k':$rank='13';break;case'a':$rank='14';break;;default:$rank=$card['rank'];break;}$this->_ranks[]=$rank;$this->_suits[]=$card['suit'];}}publicfunctioncheckCombination(){// is Royal Flushecho$this->_isRoyalFlush()?'royal flush':'not royal flush';echo'<br>';// is Quad (four of kind)echo$this->_isQuad()?'quad':'not quad';echo'<br>';// is StraightFlushecho$this->_isStraightFlush()?'straight flush':'not straight flush';echo'<br>';// is Full Houseecho$this->_isFullHouse()?'full house':'not full house';echo'<br>';// is Flushecho$this->_isFlush()?'flush':'not flush';echo'<br>';// is Straightecho$this->_isStraight()?'straight':'not straigt';echo'<br>';// is Three of Kindecho$this->_isThreeOfKind()?'three of kind':'not three of kind';echo'<br>';// is Two Pairsecho$this->_isTwoPairs()?'two pairs':'not two pairs';echo'<br>';// is one Pairecho$this->_isPair()?'pair':'not pair';echo'<br>';// is High Cardecho$this->_isHighCard()?'high card':'not high card';echo'<br>';}/** * chech that combination is flush and straight and contains ace and king (exclude straight flush "ace-5") * * @return bool */protectedfunction_isRoyalFlush(){return($this->_isFlush()&&$this->_isStraight()&&array_search(14,$this->_ranks)&&array_search('13',$this->_ranks));}/** * check combination is quad (four of kind) * * @return bool */protectedfunction_isQuad(){$test=$this->_ranks;$uniqueElementsCount=array();foreach($this->_ranksas$key=>$card){$test=$this->_ranks;unset($test[$key]);$uniqueElementsCount[]=count(array_unique($test));}return1===min($uniqueElementsCount);}/** * is a straight and a flush? * * @return bool */protectedfunction_isStraightFlush(){return($this->_isFlush()&&$this->_isStraight());}/** * is full house? * (1=2=3 and 4=5) or (1=2 and 3=4=5) * * @return bool */protectedfunction_isFullHouse(){$ranks=$this->_ranks;sort($ranks);if((($ranks[0]==$ranks[1]&&$ranks[1]==$ranks[2])&&($ranks[3]==$ranks[4]))// 1=2=3 and 4=5||($ranks[0]==$ranks[1])&&($ranks[2]==$ranks[3]and$ranks[3]==$ranks[4]))// 1=2 and 3=4=5returntrue;returnfalse;}/** * is flush? * * @return bool */protectedfunction_isFlush(){$suits=$this->_suits;sort($suits);if($suits[0]===$suits[4])returntrue;returnfalse;}/** * check straight. 2 attempt, 'cause ace may be high card, or low. * * @return bool */protectedfunction_isStraight(){$ranks=$this->_ranks;sort($ranks);// if Ace is low card in straightif($key=array_search(14,$ranks)){$tempRanks=$ranks;unset($tempRanks[$key]);if(array(2,3,4,5)==$tempRanks){returntrue;}unset($tempRanks);}// if Ace is high card - default algorithm$min=$ranks[0];foreach($ranksas$key=>$value){$ranks[$key]-=$min;if($key!=$ranks[$key])returnfalse;}returntrue;}/** * is Three of kind * * @return bool */protectedfunction_isThreeOfKind(){$ranks=$this->_ranks;sort($ranks);if(($ranks[0]==$ranks[1]and$ranks[1]==$ranks[2])||($ranks[1]==$ranks[2]and$ranks[2]==$ranks[3])||($ranks[2]==$ranks[3]and$ranks[3]==$ranks[4]))returntrue;returnfalse;}/** * is two pairs * * @return bool */protectedfunction_isTwoPairs(){$ranks=$this->_ranks;foreach($ranksas$key=>$rank){$testRanks=$ranks;unset($testRanks[$key]);sort($testRanks);if(($testRanks[0]==$testRanks[1])and($testRanks[2]==$testRanks[3])and($testRanks[0]!=$testRanks[2])// exclude full houseand($testRanks[0]!=$ranks[$key])and($testRanks[2]!=$ranks[$key]))returntrue;}returnfalse;}/** * is single Pair * * @return bool */protectedfunction_isPair(){return4===count(array_unique($this->_ranks));}/** * is High Card * * @return bool true */protectedfunction_isHighCard(){returntrue;}}
Комбинация из 5 карт для данного класса задается массивом из 5 элементов, которые в свою очередь явлеются ассоциативными массивами (suit – это масть, rank – достоинство карты).
Эпилог
Данный класс можно немного доработать, чтобы вместо название комбинаций, он выводил какой-нибудь балл комбинации, чтобы имелась возможность сравнивать две одинаковых комбинации, но это по желанию и выходит за пределы данной заметки. Также вы можете допилить проверку на корректность заданной комбинации. На этом на сегодня все. Удачи вам в любых начинаниях и продолжениях.