简单实用的 PHP 中奖概率抽奖现实



我们在PHP开发过程中,常常会用到概率抽奖的问题。比如大转盘抽奖、抽微信红包、九宫格抽奖、刮刮卡。其实只要是关于概率的问题,全都可以用下面这个 抽奖核心方法 类即可现实。虽然注释我写的已经足够详细,但是为了小白也能看懂,后面我将会做更详细的解释。
/*
* 抽奖核心方法
*/
function raffleCore($configArray) // (1)
{
// 实例化一个空数组,用来存放抽奖核心信息。
$coreArray = [];
// 把配置文件中的"id(奖品编号)"和"chance(奖品中奖概率)"两项目单独合并为一个数组。
foreach ($configArray as $key => $value) {
$coreArray[$value['id']] = $value['chance'];
}
// 实例化一个空字符串,用来存放中奖的奖品编号。
$result = '';
// 概率数组的总概率
$coreSum = array_sum($coreArray);
// 如果总概率为0,则直接返回。(2)
if ($coreSum === 0) {
return null;
}
// 概率数组循环
foreach ($coreArray as $id => $chance) {
// (3)
$coreNumber = mt_rand(1, $coreSum); // 生成一个1到总概率之间的随机数
if ($coreNumber <= $chance) {
$result = $id; // 如果随机数小于当前的概率数,则直接返回当前id。
break;
} else { // 否则从总概率中剔除掉当前的概率,继续循环。
$coreSum = $coreSum - $chance;
}
}
unset($coreArray); //$coreArr数组使用完,销毁。
return $result; // 返回中奖的奖品编号。
}
注释(1)
$configArray
变量为传入的奖品配置,举个例子。
$configArray = [
["id" => 0, "title" => "1元红包", "chance" => 5, "number" => 3000],
["id" => 1, "title" => "2元红包", "chance" => 3, "number" => 1500],
["id" => 2, "title" => "5元红包", "chance" => 2, "number" => 500],
];
其中 id
和 chance
是必要的。
id
是返回时的商品编号。建议 id
的编号从0开始,这样商品编号就能与数组下标一至,方便获取商品信息。
chance
是商品的中奖概率。通过上面的 抽奖核心方法 就能知道,这个是必须的。
其他的参数可以根据具体的项目添加,我在这个地方用到的还有 title
、number
两个参数,分别为 标题 和 奖品总数 。
注释(2)
上面的配置参数在传到 抽奖核心方法 前往往会先进行判断,当前的奖品是否已经达到了 奖品总数 的上限,如果已经达到上限,则把概率设置为 0
,这样当前奖品就不参与抽奖。
当所有奖品的中奖概率都为 0
时,则直接返回 null
不进行抽奖操作。
注释(3)
抽奖核心方法 的原理,举个例子。
根据上面的配置,概率为 5:3:2
,总概率 为 10
,从 1
到 10
中随机产生一个数 $coreNumber
,如果 $coreNumber
小于 当前奖品概率 5
,则直接返回当前 id
。否则从总概率中剔除掉 当前奖品概率,继续循环。
第一次循环时 当前奖品概率数 是 id
为 0
的商品的概率 5
,从 1
到 10
三个奖品的概率总和 中随机产生一个数 $coreNumber
, 那么 $coreNumber
小于等于 当前奖品概率数 5
的概率为 50%
,这与我们期待的概率是吻合的,所以直接返回当前 id
。如果$coreNumber
大于 当前奖品概率数 5
,则认为中的是 id
为 1
或者 id
为 2
的奖品,进入下一次循环。
第二次循环时 当前奖品概率数 是 id
为 1
的商品的概率 3
,从 1
到 5
总概率减去上一个奖品的概率 中随机产生一个数 $coreNumber
,那么 $coreNumber
小于等于 当前奖品概率数 3
的概率为 60%
,这与我们期待的概率是吻合的,所以直接返回当前 id
。如果$coreNumber
大于 当前奖品概率数 5
,则认为中的是 id
为 2
的奖品,进入下一次循环。
第三次循环时 当前奖品概率数 是 id
为 2
的商品的概率 2
,从 1
到 2
总概率减去上一个奖品的概率 中随机产生一个数 $coreNumber
,那么 $coreNumber
小于等于 当前奖品概率数 2
的概率为 100%
,所以直接返回当前 id
。