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> 解决问题的方式,就是解决它一次