场景
项目变数
- 参与人数未知
- 活动持续时间未知(活动方可能根据活动热度增减时间,以月为单位)
- 可预见的『老板需求』:活动人数太多了,临时增加1个大奖 & 无数个小奖。或者大奖太少,临时增加出大奖概率刺激活动效果。
举例:奖池设定
- 一等奖: 2个
- 二等奖:30个
- 三等奖:500个
- 四等奖:20000个
实现方案讨论
- rand 程序随机? 可能会超发,据说有策划团队已经赔过钱了
- 提前把奖品数量转化为数据库的记录。用户抽奖时,利用数据库的随机查询
select * from 奖池表 where status = '未被抽中' order by rand() limit 0,1
。问题:记录数太多,调整(增减)奖品数量不灵活,方案不优雅
最终方案
- 每次开奖结果:
rand(1, 当时的奖品总数)
,具体看代码
- 优势:随时增减奖池数量,没有关联其它表(灵活、解耦),不会超发
代码
<?php
// 设置的奖品信息
$priceInfo = [
'102' => 3, // 奖品id,奖品数量
'203' => 10,
'3092' => 100,
];
// 抽奖函数
function getPrice(&$priceInfo)
{
if (!array_sum($priceInfo)) {
return 0; //奖池已空
}
$randId = rand(1, array_sum($priceInfo)); // 170
$i = 0;
foreach ($priceInfo as $id => $num) {
$i += $num;
if ($i >= $randId) {
$priceInfo[$id]--;
return $id;
}
}
}
// 模拟100次抽奖
for ($i = 0; $i < 130; $i++) {
echo "
中奖ID: " . getPrice($priceInfo);
}
//剩余的奖品
echo "
奖池状态:
";
print_r($priceInfo);