首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 實作抽獎機率演算法

     編輯:PHP 綜合知識

加權隨機抽獎核心邏輯

抽獎系統的核心在於根據權重計算中獎機率。常見做法是將所有獎項權重累加,產生一個隨機數,落在哪個區間即中該獎項。本文提供一個通用、高效的 PHP 實作。

核心函式:get_rand()

<?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);
?>

演算法原理解析

  1. 權重正規化:不需手動計算百分比,直接用相對權重值。
  2. 區間映射:累加權重形成連續區間,隨機數落入哪個區間即命中對應獎項。
  3. 動態縮減:每次迴圈減去當前權重,等同於將區間左邊界右移。
  4. mt_rand():比 rand() 更快、隨機品質更好,適合高併發場景。

擴展建議

  • 防重複中獎:中獎後從獎池移除(如範例),或用 Redis Set 記錄已中獎用戶。
  • 大獎控制:可加入「每日大獎上限」邏輯,達上限後動態將大獎權重設為 0。
  • 分散式一致性:高併發下建議用 Lua 腳本在 Redis 原子執行「檢查庫存→扣減→抽獎」。
  • 驗證公平性:引入可驗證隨機函數(VRF)或區塊鏈區塊雜湊作為隨機種子。

常見誤區

❌ 錯誤:$rand = mt_rand(1, 100); if ($rand <= 10) ... — 只能處理百分比,難以動態調整多獎項權重。
✅ 正確:使用陣列權重配置,新增/調整獎項只需改陣列,業務邏輯零修改。

此演算法簡潔高效,適用於電商大轉盤、遊戲抽卡、活動抽獎等多種場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved