• PHP实现自定义中奖和概率算法


    最近玩《QQ飞车手游》,出了一款点券A车,需要消耗抽奖券抽奖,甚是激动,于是抽了几次,没想到中的都是垃圾道具,可恨可叹~~

    这几天项目中也涉及到了类似的概率操作,于是思考了一下,简单分装了一个精确到万分之一的概率算法实现类,废话不多说上代码。

    <?php
    
    /**
     * Created by PhpStorm.
     * User: hgq
     * Date: 2018/05/07
     * Time: 上午 10:00
     * 一个抽奖类,精确到万分之一
     * 三个步骤:1.接受一个中奖概率数组;2.接受一个抽奖种子;3.返回中奖等级
     */
    class LuckyDraw {
        /**
         * 中奖概率数组,自动判断奖项数目
         * 数组键值和为10000,自动计算出不中奖的概率,若初始是超过10000抛出一个错误
         * @var array
         */
        protected $_rate = array();
    
        /**
         * 设置中奖概率,
         * @param array $rate 中奖概率,以数组形式传入
         * @throws Exception
         * @author hgq <393210556@qq.com>.
         * @date: 2018/05/07 上午 10:05
         */
        public function setRate($rate = array(1)) {
            $this->_rate = $rate;
            if(array_sum($this->_rate) > 10000)//检测概率设置是否有问题
                throw new Exception('Winning rate upto 100%');
            if(array_sum($this->_rate) < 10000)
                //定义未中奖情况的概率,用户给的概率只和为100时,则忽略0
                $this->_rate[] = 10000 - array_sum($this->_rate);
        }
    
        /**
         * 随机生成一个1-10000的整数种子,提交给中奖判断函数
         * @return int 按传入的概率排序,返回中奖的项数
         * @author hgq <393210556@qq.com>.
         * @date: 2018/05/07 上午 10:07
         */
        public function runOnce() {
            return $this->judge(mt_rand(0, 10000));
        }
    
        /**
         * 按所设置的概率,判断一个传入的随机值是否中奖
         * @param $seed 10000以内的随机数
         * @return int $i 按传入的概率排序,返回中奖的项数 从1开始 如果只有一个奖项则等于1即中奖
         * @author hgq <393210556@qq.com>.
         * @date: 2018/05/07 上午 10:17
         */
        protected function judge($seed) {
            foreach($this->_rate as $key => $value) {
                $tmpArr[$key + 1] = $value;
            }
            //将概率累计,以便随机选择,组合成
            $tmpArr[0] = 0;
            foreach($tmpArr as $key => $value) {
                if($key > 0) {
                    $tmpArr[$key] += $tmpArr[$key - 1];
                }
            }
            for($i = 1; $i < count($tmpArr); $i++) {
                if($tmpArr[$i - 1] < $seed && $seed <= $tmpArr[$i]) {
                    return $i; //返回中奖的项数(按概率的设置顺序)
                }
            }
        }
    }

    最后看一下运行效果,循环运行10000次

    上述设置了6款产品,概率分别为100,200,500,600,420,512,多次运行中奖概率基本符合概率设置,如果将对应的奖项的设置成0,即意味着该奖项抽中的几率是0

    最后说一下为什么抽不到大奖?

    在很多类似的抽奖活动中,参与者往往抽不到大奖,笔者从程序的角度举个例给你看,假如我是抽奖活动的主办方,我设置了6个奖项,每个奖项不同的中奖概率,假如一等奖是一台iphoneX,可是我设置了其中奖概率为0,这意味着什么?

    这意味着参与抽奖者无论怎么抽,永远也无法中奖。

    所以抽奖有风险,操作需谨慎啊~~

    作者:旧旧的 <393210556@qq.com> 解决问题的方式,就是解决它一次

  • 相关阅读:
    Js获取时间,当前,一周前,一月前的时间,时间戳转换,时间格式化,日期格式化
    echarts图随窗口大小的变化而变化
    Vue中使用Google地图插件
    element el-progress渐变色进度条
    Vue中使用mixins
    CSS3 使用 calc() 计算高度 vh px
    element-ui饿了么框架中导航菜单中箭头方向问题
    Vue中使用QRcode.js生成二维码---qrcodejs2
    鼠标经过时显示样式的两种方法
    element 按钮样式:确认按钮发布后样式发生改变
  • 原文地址:https://www.cnblogs.com/widgetbox/p/9001409.html
Copyright © 2020-2023  润新知