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

PHP 抽獎概率算法實現:適用於刮刮卡、大轉盤等場景

     編輯:PHP 綜合知識

算法核心思想

本文介紹一種經典的 PHP 抽獎概率算法,核心邏輯基於「概率空間遞減」原理:將所有獎項概率權重累加為總基數,在 1 到總基數範圍內生成隨機數,依次遍歷獎項,若隨機數落在當前獎項的概率區間內則中獎,否則從總基數中扣除該獎項權重,繼續下一輪篩選。這種「箱子摸球」式算法保證必有結果產出,時間複雜度 O(n),極適合高併發大數據量場景。

核心函數 get_rand() 解析

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;
}

關鍵點:使用 mt_rand() 而非 rand(),前者基於梅森旋轉算法,速度更快、隨機性更好;循環中動態縮減 $proSum 實現「不歸位抽樣」邏輯。

獎項配置與業務邏輯

獎項陣列採用二維結構,包含 id、獎品名稱、權重值 v:

$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),
);

權重總和為 100,平板電腦中獎概率 1%。若需萬分之一精度,將總基數擴大至 10000 並按比例調整各權重即可。設置 v=0 可禁用某獎項。

完整業務流程

  1. 構建 $arr[$val['id']] = $val['v'] 映射 id 到權重
  2. 調用 get_rand($arr) 獲取中獎 id
  3. 從獎項池移除中獎項,剩餘項打亂順序組成未中獎列表
  4. 返回 JSON 格式結果:{'yes': 中獎獎品, 'no': [未中獎列表]}

應用場景與擴展建議

  • 大轉盤/刮刮卡:前端動畫展示,後端此算法決定結果
  • 防刷機制:結合 Redis 限制用戶每日抽獎次數、IP 限流
  • 獎品庫存控制:中獎後原子性扣減庫存,庫存為 0 時動態將權重設為 0
  • 日誌記錄:記錄用戶 ID、請求時間、中獎結果、隨機數值,便於審計

總結

該算法代碼簡潔(核心不足 20 行)、邏輯清晰、性能優異,是 PHP 抽獎系統的首選方案。實際部署時建議將權重配置外置到資料庫或配置文件,支援運營動態調整概率無需改代碼。

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