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

PHP 抽獎機率演算法實作:加權隨機抽獎邏輯

     編輯:PHP 相關知識

PHP 抽獎機率演算法實作:加權隨機抽獎邏輯

實現一個高效、精確的加權隨機抽獎函式,支援動態獎品池與機率配置,回傳中獎結果與未中獎獎品列表供前端展示。

核心機率函式

<?php
function get_rand(array $proArr) {
    $proSum = array_sum($proArr); // 總權重
    foreach ($proArr as $key => $proCur) {
        $randNum = mt_rand(1, $proSum);
        if ($randNum <= $proCur) {
            return $key; // 中獎索引
        }
        $proSum -= $proCur; // 權重遞減
    }
    return ''; // 理論不會執行到這裡
}
?>

原理:將機率空間視為連續區間,隨機落點落在哪個獎品區間即中獎。每次未中獎縮減總權重,保證最終必中獎。

完整抽獎流程

<?php
// 獎品池配置:id、名稱、權重(v)
$prize_arr = [
    1 => ['id'=>1, 'prize'=>'平板電腦', 'v'=>1],
    2 => ['id'=>2, 'prize'=>'數碼相機', 'v'=>5],
    3 => ['id'=>3, 'prize'=>'音箱設備', 'v'=>10],
    4 => ['id'=>4, 'prize'=>'4G優盤', 'v'=>12],
    5 => ['id'=>5, 'prize'=>'10Q幣', 'v'=>22],
    6 => ['id'=>6, 'prize'=>'下次沒準就能中哦', 'v'=>50],
];

// 建立權重陣列
$weights = [];
foreach ($prize_arr as $item) {
    $weights[$item['id']] = $item['v'];
}

// 抽獎
$winId = get_rand($weights);
$winPrize = $prize_arr[$winId]['prize'];

// 移除已中獎項目,打亂剩餘順序供前端展示
unset($prize_arr[$winId]);
shuffle($prize_arr);
$otherPrizes = array_column($prize_arr, 'prize');

// 回傳 JSON
echo json_encode([
    'status' => 1,
    'win' => $winPrize,
    'others' => $otherPrizes
]);
?>

前端 AJAX 對接

<button id="drawBtn">開始抽獎</button>
<div id="result"></div>

<script>
$('#drawBtn').click(function() {
    $.post('lottery.php', function(res) {
        if (res.status) {
            $('#result').html('恭喜中獎:' + res.win + '
其他獎品:' + res.others.join(', ')); } }, 'json'); }); </script>

機率精度與測試

  • 權重總和即為分母:總和 100 → 1% 精度;總和 10000 → 0.01% 精度
  • 大量測試驗證:跑 100 萬次統計各獎品出現次數,應接近理論機率
  • 權重為 0 的獎品永不中獎,可用於下架獎品保留顯示

擴充:防刷與日誌

<?php
// 簡易防刷:同 IP 每日限 5 次
$key = 'lottery:' . $_SERVER['REMOTE_ADDR'] . ':' . date('Ymd');
$count = $redis->incr($key);
if ($count === 1) $redis->expire($key, 86400);
if ($count > 5) exit(json_encode(['status'=>0, 'msg'=>'今日次數已用完']));

// 記錄中獎日誌
$log = [
    'uid' => $userId,
    'prize' => $winPrize,
    'ip' => $_SERVER['REMOTE_ADDR'],
    'time' => time()
];
$redis->lpush('lottery:log', json_encode($log));
?>
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved