php大转盘抽奖算法
16lz
2021-01-22
问题描述:
现在的营销工具大部分都包含抽奖部分,例如大转盘,刮刮卡等。虽然在前端显示的效果完全不同,但是从发出抽奖请求,到返回抽奖结果直接php部分可以通用。整个流程包括 1拼装奖项数组2进行概率计算3返回中奖情况(包括是否中奖,奖品编号,奖品名称,奖品图片,奖品类型等)。
问题分析:
(1)拼装奖项数组
//奖品数组 $prize_arr = array( '0' => array('id'=>1,'prize'=>'平板电脑','v'=>1), '1' => array('id'=>2,'prize'=>'数码相机','v'=>5), '2' => array('id'=>3,'prize'=>'音箱设备','v'=>10), '3' => array('id'=>4,'prize'=>'4G优盘','v'=>12), '4' => array('id'=>5,'prize'=>'10Q币','v'=>22), '5' => array('id'=>6,'prize'=>'空奖','v'=>50), );
从配置信息中获取奖品名称,数量,概率等信息,并进行拼装。
(2)核心部分 计算概率
function get_rand($proArr) { $result = ''; //概率数组的总概率精度 $proSum = array_sum($proArr); //概率数组循环 foreach ($proArr as $key => $proCur) { $randNum = mt_rand(1, $proSum); if ($randNum <= $proCur) { $result = $key; break; } else { $proSum -= $proCur; } } unset ($proArr); return $result; }$proArr是一个预先设置的数组,假设数组为:array(100,200,300,400),开始是从1,1000这个概率范围内筛选第一个数是否在他的出现概率范围之内, 如果不在,则将概率空间,也就是k的值减去刚刚的那个数字的概率空间,在本例当中就是减去100,也就是说第二个数是在1,900这个范围内筛选的。这样筛选到最终,总会有一个数满足要求。就相当于去一个箱子里摸东西,第一个不是,第二个不是,第三个还不是,那最后一个一定是。
(3)返回中奖信息
奖品名称保存在$res['yes']中,对应的id是$rid。未中奖奖品是$res['no']。这里只需要返回奖品名称$result['name']=$res['yes']
扩展部分:
1)限制中奖次数 :在中奖函数开始时,判断统计该用户中奖次数。超出次数,跳出;没有超过,继续抽奖
2)一个人不能重复中奖:在中奖函数结束时,判断统计该用户中奖名称是否已存在。存在则重新抽奖或者跳出;不存在,则继续抽奖。
3)返回未中奖信息$res['no']。目前大转盘,刮刮卡没有用到未中奖的信息,如果是翻牌类抽奖,则需要展示未中奖的奖品。
4)某项奖品必中一次。抽奖开始时,判断是否已有该奖品,有则正常抽奖;没有,则直接中该奖品,跳出函数。
完整代码
//计算中奖函数 function get_gift(){ //奖品数组 $prize_arr = array( '0' => array('id'=>1,'prize'=>'平板电脑','v'=>1), '1' => array('id'=>2,'prize'=>'数码相机','v'=>5), '2' => array('id'=>3,'prize'=>'音箱设备','v'=>10), '3' => array('id'=>4,'prize'=>'4G优盘','v'=>12), '4' => array('id'=>5,'prize'=>'10Q币','v'=>22), '5' => array('id'=>6,'prize'=>'空奖','v'=>50), ); foreach ($prize_arr as $key => $val) { $arr[$val['id']] = $val['v'];//概率数组 } $rid = get_rand($arr); //根据概率获取奖项id $res['yes'] = $prize_arr[$rid-1]['prize']; //中奖项 unset($prize_arr[$rid-1]); //将中奖项从数组中剔除,剩下未中奖项 shuffle($prize_arr); //打乱数组顺序 for($i=0;$i<count($prize_arr);$i++){ $pr[] = $prize_arr[$i]['prize']; } $res['no'] = $pr; if($res['yes']!='空奖'){ $result['status']=1; $result['name']=$res['yes']; }else{ $result['status']=-1; $result['msg']=$res['yes']; } return $result; }
function get_rand($proArr) { $result = ''; //概率数组的总概率精度 $proSum = array_sum($proArr); //概率数组循环 foreach ($proArr as $key => $proCur) { $randNum = mt_rand(1, $proSum); if ($randNum <= $proCur) { $result = $key; break; } else { $proSum -= $proCur; } } unset ($proArr); return $result; } $res=get_gift(); echo json_encode($res); die();