【算法】PHP简单实现斗地主洗牌和发牌

本文分享了如何设计斗地主数据结构,包括炸弹、顺子等规则,以及一个简单的洗牌和发牌函数实例。通过数字编码牌型,演示了如何创建和打乱牌组,适用于后续游戏逻辑开发。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近有时间了,重新学习一下基础知识。工作中一直都只关注业务实现,丢了很多基础的东西。今天遇到一道题目问斗地主的数据结构要怎么设计,当时初步构思了一下,今晚把构思写出来,并加上洗牌的简单实现。

思路:理清斗地主的出牌逻辑,如

炸弹:王炸、4炸;

3带1对,3带1个,3个不带;

飞机:3+3,3+3+1+1,3+3+2+2;

顺子:牌3到牌A连续,5张起

一对

单个

 

按照这个思路逻辑,我计划用数字大小来做牌的主key,方便后续实现运算,王+13个牌,分别设计为王-14,二-13,A-12...三-1 ,一个牌有4个花色,分别用4到1来区分。大小王分别用142、141,二用134,133,132,131,依此类推来设计牌的数据结构。

 


    /**
     * @name 简单版 斗地主洗牌、发牌
     * @return array
     */
    public function randPuker()
    {
        $puker = [
            142    => '大王',
            141    => '小王',
            134    => '黑桃2',
            133    => '红心2',
            132    => '梅花2',
            131    => '方块2',
            124    => '黑桃A',
            123    => '红心A',
            122    => '梅花A',
            121    => '方块A',
            114    => '黑桃K',
            113    => '红心K',
            112    => '梅花K',
            111    => '方块K',
            104    => '黑桃Q',
            103    => '红心Q',
            102    => '梅花Q',
            101    => '方块Q',
            94    => '黑桃J',
            93    => '红心J',
            92    => '梅花J',
            91    => '方块J',
            84    => '黑桃10',
            83    => '红心10',
            82    => '梅花10',
            81    => '方块10',
            74    => '黑桃9',
            73    => '红心9',
            72    => '梅花9',
            71    => '方块9',
            64    => '黑桃8',
            63    => '红心8',
            62    => '梅花8',
            61    => '方块8',
            54    => '黑桃7',
            53    => '红心7',
            52    => '梅花7',
            51    => '方块7',
            44    => '黑桃6',
            43    => '红心6',
            42    => '梅花6',
            41    => '方块6',
            34    => '黑桃5',
            33    => '红心5',
            32    => '梅花5',
            31    => '方块5',
            24    => '黑桃4',
            23    => '红心4',
            22    => '梅花4',
            21    => '方块4',
            14    => '黑桃3',
            13    => '红心3',
            12    => '梅花3',
            11    => '方块3',
        ];

        //随机打乱数组,由于shuffle函数会重置key值,所以使用key值来打乱,再通过key值把牌生成好
        $randKeys = array_keys($puker);
        shuffle($randKeys);
        //重新按打乱顺序排好牌
        foreach ($randKeys as $k){
            $pukerTemp[$k] = $puker[$k];
        }
        //重组完毕
        $puker = $pukerTemp;

        //先抽3张作为底牌
        $keys = array_rand($puker,3);
        $arrCover = [];
        foreach ($keys as $key){
            $arrCover[$key] = $puker[$key];
            unset($puker[$key]);
        }

        $i = 0;
        //将剩下的数组分3份,发牌
        foreach($puker as $key => $val){
            $arrPlayer[$i % 3][$key] = $val;
            $i++;
        }

        return array('cover'=> $arrCover, 'player'=> $arrPlayer);
    }

拿到牌以后,可以按顺序排列。

public function test()
{
        echo '<pre>';
        $data = $this->randPuker();
        //如果玩家1叫地主,则把底牌给他
        $i = 0;//0,1,2
        $data['player'][$i] = $data['player'][$i] + $data['cover'];

        krsort($data['player'][0]);
        krsort($data['player'][1]);
        krsort($data['player'][2]);
        print_r($data);
        die();
}

运行结果:

Array
(
    [cover] => Array
        (
            [114] => 黑桃K
            [12] => 梅花3
            [51] => 方块7
        )

    [player] => Array
        (
            [0] => Array
                (
                    [141] => 小王
                    [133] => 红心2
                    [122] => 梅花A
                    [114] => 黑桃K
                    [113] => 红心K
                    [112] => 梅花K
                    [111] => 方块K
                    [104] => 黑桃Q
                    [84] => 黑桃10
                    [82] => 梅花10
                    [73] => 红心9
                    [64] => 黑桃8
                    [63] => 红心8
                    [61] => 方块8
                    [51] => 方块7
                    [34] => 黑桃5
                    [24] => 黑桃4
                    [21] => 方块4
                    [13] => 红心3
                    [12] => 梅花3
                )

            [1] => Array
                (
                    [142] => 大王
                    [134] => 黑桃2
                    [132] => 梅花2
                    [131] => 方块2
                    [121] => 方块A
                    [103] => 红心Q
                    [101] => 方块Q
                    [93] => 红心J
                    [83] => 红心10
                    [74] => 黑桃9
                    [52] => 梅花7
                    [44] => 黑桃6
                    [41] => 方块6
                    [31] => 方块5
                    [23] => 红心4
                    [14] => 黑桃3
                    [11] => 方块3
                )

            [2] => Array
                (
                    [124] => 黑桃A
                    [123] => 红心A
                    [102] => 梅花Q
                    [94] => 黑桃J
                    [92] => 梅花J
                    [91] => 方块J
                    [81] => 方块10
                    [72] => 梅花9
                    [71] => 方块9
                    [62] => 梅花8
                    [54] => 黑桃7
                    [53] => 红心7
                    [43] => 红心6
                    [42] => 梅花6
                    [33] => 红心5
                    [32] => 梅花5
                    [22] => 梅花4
                )

        )

)

另再写了个出牌key值获取的方法,方便后续出牌判断。

public function getPukerKey($k)
{
    //提取牌的大小及花色,斗地主除了大小王,其他牌与花色无关,通过判断数字大小及打牌规则来看是否可以出牌
    if($k < 100){
        $pk = substr($k,0,1);
        //$hs = substr($k,-1);
    }else{
        $pk = substr($k,0,2);
        //$hs = substr($k,-1);
    }
    //echo $pk.'<br/>';
    return $pk;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值