1. 程式人生 > >用PHP實現一個關於德州撲克演算法的程式(四):程式碼

用PHP實現一個關於德州撲克演算法的程式(四):程式碼

程式主入口

<?php
include "Table.class.php";
//顯示函式
function pre($str){
    echo '<pre>';
    print_r($str);
    echo '</pre>';
}

//建立撲克牌
$c=new Cards();
//初始化玩家數量
$table=new Table(2,$c->Cards);

撲克牌類 Cards.class.php

class Cards{
    public $Cards=array();

    function __construct()
    {
        $this
->Cards=$this->createCards(); shuffle($this->Cards); } private function createCards() { $cards=array(); $suit=array("H","S","D","C"); $p=array("T","J","Q","K","A"); for($i=0;$i<count($suit);$i++){ for($j=2;$j<=9;$j++){ $cards
[]=$suit[$i].$j; } for($k=0;$k<count($p);$k++){ $cards[]=$suit[$i].$p[$k]; } } return $cards; } }

玩家類 Player.class.php

class Player{

    public $score=0;
    public $CardInHand=array();

    function __construct($cards)
    {
$this->getCardInHand($cards); } private function getCardInHand($cards){ $randkey=array_rand($cards,2); $this->CardInHand[]=$cards[$randkey[0]]; $this->CardInHand[]=$cards[$randkey[1]]; return $this->CardInHand; } }

牌桌類(核心演算法類)Table.class.php

include "Cards.class.php";
include "Player.class.php";

class  Table{

    public $players=array();
    public $tablecards=array();

    function __construct($num,$cards)
    {
        for($i=0;$i<$num;$i++){
            $this->players[$i]=new Player($cards);
            $cards=array_diff($cards,$this->players[$i]->CardInHand);
            //echo count($cards).'<br>';
            $k=$i+1;
            echo "玩家".$k."的手牌為<br>";
            $this->showCard($this->players[$i]->CardInHand);
            echo "<br>==========<br>";
        }
        array_shift($cards);
        for($i=0;$i<3;$i++) {
            $this->tablecards[] = $cards[$i];
        }
        $cards=array_diff($cards,$this->tablecards);
        for($i=0;$i<2;$i++){
            array_shift($cards);
            $this->tablecards[] = $cards[0];
        }
        echo "<br>====公牌為====<br>";
        $this->showCard($this->tablecards);

        for($i=0;$i<count($this->players);$i++){
            $k=$i+1;
            echo "<br>----玩家{$k}的結果為----<br>";
            $this->result($this->players[$i]);
            echo "<br>-----------------------<br>";
        }
    }

    private function showCard($cards){
        foreach ($cards as $ca) {
            $path.= "<img src='./pukeImage/". $ca . ".jpg'>";
        }
        echo $path;
    }

    private function pre($str,$comment){
        echo "<pre>=={$comment}===<br>";
        print_r($str);
        echo '</pre>====<br>';
    }

    private function result(Player $p){
        $result=array_merge($p->CardInHand,$this->tablecards);
        //pre($result);
        foreach($result as $c){
            $suit.=$c[0];
            $point.=$c[1];
        }
        //字串轉換為陣列
        $su=str_split($suit);
        $po=str_split($point);
        //統計花色和點數
        $su_count=array_count_values($su);
        $po_count=array_count_values($po);
        switch(max($su_count)){
            case "5":
                echo "這是".array_keys($su_count,"5")[0]."同花"."<br>";
                break;
            default:
                switch(max($po_count)){
                    case "4":
                        echo "這是".array_keys($po_count,"4")[0]."四條"."<br>";
                        $this->showCard($this->pukesort($result));
                        break;
                    case "3":
                        //echo "這是".array_keys($po_count,"3")[0]."三條"."<br>";
                        $this->isStraight($result);
                        break;
                    case "2":
                        //echo "這是".array_keys($po_count,"2")[0]."對子"."<br>";
                        $this->isStraight($result);
                        break;
                    default:
                        $this->isStraight($result);

                }
                break;
        }
    }

    private function pukesort($cards){
        foreach($cards as $ca){
            $arr[]=$ca[1];
        }
        $arr=array_count_values($arr);


        foreach(array_keys($arr) as $v) {
            switch ($v) {
                case "A":
                    $poi[] = 14;
                    break;
                case "K":
                    $poi[] = 13;
                    break;
                case "Q":
                    $poi[] = 12;
                    break;
                case "J":
                    $poi[] = 11;
                    break;
                case "T":
                    $poi[] = 10;
                    break;
                default:
                    $poi[] = $v;
                    break;
            }
        }

        $puke=array(
            "num"=>array_values($arr),
            "poi"=>$poi
        );

        array_multisort($puke["num"], SORT_NUMERIC, SORT_DESC,
            $puke["poi"],SORT_NUMERIC, SORT_DESC
        );
        $arr= array_combine($puke["poi"],$puke["num"]);

        foreach($arr as $key=>$value){
            switch($key){
                case "14":
                    $arr1["A"]=$arr["14"];
                    break;
                case "13":
                    $arr1["K"]=$arr["13"];
                    break;
                case "12":
                    $arr1["Q"]=$arr["12"];
                    break;
                case "11":
                    $arr1["J"]=$arr["11"];
                    break;
                case "10":
                    $arr1["T"]=$arr["10"];
                    break;
                default:
                    $arr1[$key]=$value;
                    break;
            }
        }
        $keys=array_keys($arr1);
        foreach($keys as $v){
            $pstr= '/.'.$v.'/';
            foreach($cards as $c) {
                if(preg_match($pstr,$c)){
                    $maxcard[]=$c;
                }
            }
        }
        $maxcard=array_slice($maxcard,0,5);
        return $maxcard;
    }

    private function pointToNum($arr){
        $num=0;
        //統計在這副牌型中點數為數字的情況,從而判斷A是做14合適還是作1合適
        foreach($arr as $p){
            if(!is_numeric($p))
                $num++;
        }
        foreach($arr as $p){
            switch($p){
                case "A":
                    if($num>=5){
                        $poi[]=14;
                    }else{
                        $poi[]=1;//A還可以作為1使用
                    }
                    break;
                case "K":
                    $poi[]=13;
                    break;
                case "Q":
                    $poi[]=12;
                    break;
                case "J":
                    $poi[]=11;
                    break;
                case "T":
                    $poi[]=10;
                    break;
                default:
                    $poi[]=$p;
                    break;
            }
        }
        return $poi;
    }

    private function numToPoint($arr){
        foreach($arr as $p){
            switch($p){
                case "14":
                case "1":
                    $poi[]="A";
                    break;
                case "13":
                    $poi[]="K";
                    break;
                case "12":
                    $poi[]="Q";
                    break;
                case "11":
                    $poi[]="J";
                    break;
                case "10":
                    $poi[]="T";
                    break;
                default :
                    $poi[]=$p;
            }
        }
        return $poi;
    }

    private function isStraight($cards){
        foreach($cards as $c){
            $point.=$c[1];
        }
        $po=array_unique(str_split($point));
        //如果元素不為5個,則不滿足順子成牌的基本條件
        if(count($po)<5){
            $this->showCard($this->pukesort($cards));
        }else{
            $po=$this->pointToNum($po);
            arsort($po);
            $a1=array_values($po);
            $j=0;
            for($i=1;$i<count($a1);$i++){
                if($a1[$i]==$a1[$i-1]-1){
                    $j++;
                    $a2[]=array_search($a1[$i-1],$po);
                    $a2[]=array_search($a1[$i],$po);
                }else{
                    $j=0;
                }
            }
            if($j>=4){
                $a2=array_unique($a2);//去掉重複值
                $a2=array_values($a2);//重建索引
                $a2=array_slice($a2,0,5);//取出5個元素
                for($i=0;$i<count($a2);$i++){
                    $result[]=$po[$a2[$i]];
                }
                $arr=$this->numToPoint($result);
                foreach($arr as $v){
                    $pstr= '/.'.$v.'/';
                    foreach($cards as $c) {
                        if(preg_match($pstr,$c)){
                            $maxcard[]=$c;
                            break;
                        }
                    }
                }
                $this->showCard($this->pukesort($maxcard));
            }else{
                $this->showCard($this->pukesort($cards));
            }
        }
    }
}

執行顯示效果:
這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

ps:以上算是德州撲克的演算法程式的90%內容,還有10%的內容是同花順的判斷,以及玩家分數的計算和勝負的判斷,但是這些內容已經很簡單,已經沒有演算法上的挑戰性,因此《用PHP實現一個關於德州撲克演算法的程式》就告一段落了。