php 抽奖算法,适合九宫格和大转盘

php实现的抽奖算法,可以设置概率

/* 
 * 不同概率的抽奖原理就是把0到*(比重总数)的区间分块
 * 分块的依据是物品占整个的比重,再根据随机数种子来产生0-* 中的某个数
 * 判断这个数是落在哪个区间上,区间对应的就是抽到的那个物品。
 * 随机数理论上是概率均等的,那么相应的区间所含数的多少就体现了抽奖物品概率的不同。
 */  


    /**
     * 抽奖方法
     * @return [array] [抽奖情况]
     */
    public function doDraw()
    {
        // 奖品数组
        $proArr = array(
            // id => 奖品等级, name => 奖品名称, v => 奖品权重
            array('id'=>1,'name'=>'超级奖品','v'=>0),
            array('id'=>2,'name'=>'特等奖','v'=>1),
            array('id'=>3,'name'=>'一等奖','v'=>5),
            array('id'=>4,'name'=>'二等奖','v'=>10),
            array('id'=>5,'name'=>'三等奖','v'=>12),
            array('id'=>6,'name'=>'四等奖','v'=>22),
            array('id'=>7,'name'=>'五等奖','v'=>50),
            array('id'=>8,'name'=>'六等奖','v'=>100),
            array('id'=>9,'name'=>'七等奖','v'=>200),
            array('id'=>10,'name'=>'八等奖','v'=>200),
            array('id'=>11,'name'=>'没中奖','v'=>500),
        );

        // 奖品等级奖品权重数组
        $arr = [];
        foreach ($proArr as $key => $val) {
            $arr[$val['id']] = $val['v'];
        }
        // 中奖 id
        $rid = $this->get_rand($arr);


        /**模拟抽奖测试**/
/*        $i = 0;
        while ( $i < 10000) {
          $rid = $this->get_rand($arr);
          $res[] = $rid;
          $i++;
        }
        // 统计奖品出现次数
        $result = array_count_values($res);
        asort($result);
        foreach ($result as $id => $times) {
            foreach ($proArr as $gifts) {
                if($id == $gifts['id']){
                    $response[$gifts['name']] = $times;
                }
            }
        }
        dump($response);
        die;*/


        $result = [];
        // 中奖礼品
        $result['yes'] = $proArr[$rid-1]['name'];
        // 从原奖品数组中剔除已经中奖礼品
        unset($proArr[$rid-1]);

        // 打乱数组排序
        shuffle($proArr);

        for ($i=0; $i < count($proArr); $i++) {
            $result['no'][] = $proArr[$i]['name'];
        }

        // foreach ($proArr as $k => $v) {
        //     // 没中奖礼品
        //     $result['no'][] = $v['name'];
        // }

        dump($result);

    }

    /**
     * 抽奖算法
     * @param  array  $proArr 奖品等级奖品权重数组
     * @return [int]         中奖奖品等级
     */
    public function get_rand($proArr = array()) {
        if(empty($proArr)) die;
        $rid = '';

        // 概率数组的总权重
        $proSum = array_sum($proArr);

        // 概率数组循环
        foreach ($proArr as $k => $proCur) {
            // 从 1 到概率总数中任意取值
            $randNum = mt_rand(1, $proSum);
            // 判断随机数是否在概率权重中
            if ($randNum <= $proCur) {
                // 取出奖品 id
                $rid = $k;
                break;
            } else {
                // 如果随机数不在概率权限中,则不断缩小总权重,直到从奖品数组中取出一个奖品
                $proSum -= $proCur;
            }
        }

        unset($proArr);
        return $rid;
    }

测试方法:


public function test(){

    $proArr = array(
        array('id'=>1,'name'=>'特等奖','v'=>1),
        array('id'=>2,'name'=>'一等奖','v'=>5),
        array('id'=>3,'name'=>'二等奖','v'=>10),
        array('id'=>4,'name'=>'三等奖','v'=>12),
        array('id'=>5,'name'=>'四等奖','v'=>22),
        array('id'=>6,'name'=>'没中奖','v'=>500)
    );

    $result = array();
    foreach ($proArr as $key => $val) {
        $arr[$key] = $val['v'];
    }
    // 概率数组的总权重
    $proSum = array_sum($arr);

    // 概率数组循环
    foreach ($arr as $k => $v) {

        // 从 1 到概率总数中任意取值
        $randNum = mt_rand(1, $proSum);
        $aa[$k] = $randNum . '+' . $v . '+' . $proSum;
        if ($randNum <= $v) {
            $result = $proArr[$k];
            // 找到符合条件的值就跳出 foreach 循环
            // dump($result);
            break;
        } else {
            $proSum = $proSum - $v;
            $bb[$k] = $randNum . '+' . $v . '+' . $proSum;
        }

    }

    dump($aa);
    dump($bb);
    // // dump($result);
    // // dump(__DIR__);
    // $path = __DIR__ . DS . 'log';
    // if(!is_dir($path)){
    //     mkdir($path);
    // }

    // $fileName = $path . DS . 'log.txt';
    // 创建文件和打开文件的函数都是 fopen
    // $cFile = fopen($fileName,'a+');
    // $a = json_encode($aa) . "\r\n";
    // $b = json_encode($bb) . "\r\n";
    // fwrite($cFile,$a);
    // fwrite($cFile,$b);
    // fclose($cFile);

    // 读文件
    // $lines = file($fileName);
    // foreach ($lines as $key => $value) {
    //     dump($value.'555555555');
    // }
    // dump($lines);

}
说说我的看法