抽獎系統的核心在於根據權重計算中獎機率。常見做法是將所有獎項權重累加,產生一個隨機數,落在哪個區間即中該獎項。本文提供一個通用、高效的 PHP 實作。
<?php
/**
* 加權隨機抽取
* @param array $proArr 鍵為獎項ID,值為權重
* @return mixed 中獎鍵值
*/
function get_rand(array $proArr) {
$proSum = array_sum($proArr); // 總權重
foreach ($proArr as $key => $proCur) {
$randNum = mt_rand(1, $proSum); // 1 到總權重
if ($randNum <= $proCur) {
return $key; // 命中
}
$proSum -= $proCur; // 縮減範圍
}
return ''; // 理論不會執行到這裡
}
?>
<?php
// 獎池定義:id, 獎品代碼, 權重
$prize_arr = [
['id' => 1, 'prize' => '1000000514', 'v' => 2],
['id' => 2, 'prize' => '1000000513', 'v' => 5],
['id' => 3, 'prize' => '1000000512', 'v' => 13],
['id' => 4, 'prize' => '1000000511', 'v' => 15],
['id' => 5, 'prize' => '1000000510', 'v' => 25],
['id' => 6, 'prize' => '1000000509', 'v' => 30],
['id' => 7, 'prize' => '1000000508', 'v' => 10],
];
// 整理為 get_rand 需要的格式:id => 權重
$arr = [];
foreach ($prize_arr as $val) {
$arr[$val['id']] = $val['v'];
}
// 執行抽獎
$rid = get_rand($arr);
$winPrize = $prize_arr[$rid - 1]['prize'];
// 移除已中獎項,剩餘獎品打亂順序作為「未中獎」展示
unset($prize_arr[$rid - 1]);
shuffle($prize_arr);
$noPrizes = array_column($prize_arr, 'prize');
// 結果輸出
$result = [
'yes' => $winPrize, // 中獎獎品
'no' => $noPrizes // 未中獎獎品列表
];
print_r($result);
?>
rand() 更快、隨機品質更好,適合高併發場景。❌ 錯誤:
$rand = mt_rand(1, 100); if ($rand <= 10) ...— 只能處理百分比,難以動態調整多獎項權重。
✅ 正確:使用陣列權重配置,新增/調整獎項只需改陣列,業務邏輯零修改。
此演算法簡潔高效,適用於電商大轉盤、遊戲抽卡、活動抽獎等多種場景。