搶紅包算法

<?php
/* * 生成紅包的函數 */

function getRandMoney($totalMoney, $totalPeople = 2, $miniMoney = 1)
{
    $randRemainMoney = $totalMoney - $totalPeople * $miniMoney; //剩餘需要隨機的錢數
    return _getRandMoney($randRemainMoney, $totalPeople, $miniMoney);
}

/* * 紅包生成的邏輯代碼 */

function _getRandMoney($totalMoney, $totalPeople, $miniMoney)
{
    $returnMessage = array('status' => 1, 'data' => NULL);
    if ($totalMoney > 0) {
        $returnMessage['data'] = _randMoney($totalMoney, $totalPeople, $miniMoney);
    } elseif ($totalMoney == 0) {
        $returnMessage['data'] = array_fill(0, $totalPeople, 1);
    } else {
        $returnMessage['status'] = -1;
        $returnMessage['data'] = '參數傳遞有誤,生成紅包失敗';
    }
    return $returnMessage;
}

/* 參數無誤,開始生成對應的紅包金額 */

function _randMoney($totalMoney, $totalPeople, $miniMoney)
{
    $data = array_fill(0, $totalPeople, $miniMoney);
    if ($totalPeople > 1) {
        foreach ($data as $k => $v) {
            if ($k == $totalPeople - 1) {
                $data[$k] = $totalMoney + $v;
                break;
            } else {
                if ($totalMoney == 0)
                    break;
                $randMoney = rand(0, $totalMoney);
                $totalMoney -= $randMoney;
                $data[$k] = $randMoney + $v;
            }
        }
    }
    return $data;
}

class redpack
{

//總金額
    private $total = 0;
//紅包數量
    private $num = 0;
//最小紅包金額
    private $min = 0.01;

    public function __construct($total, $num, $min)
    {
        $this->total = $total;
        $this->num = $num;
        $this->min = $min;
    }

//紅包結果
    public function getPack()
    {
        $total = $this->total;
        $num = $this->num;
        $min = $this->min;
        for ($i = 1; $i < $num; $i++) {
            $safe_total = ($total - ($num - $i) * $min) / ($num - $i); //隨機安全上限
            $money = mt_rand($min * 100, $safe_total * 100) / 100;
            $total = $total - $money;
//紅包數據
            $readPack[] = [
                'money' => $money,
                'balance' => $total,
            ];
        }
//最後一個紅包,不用隨機
        $readPack[] = [
            'money' => $money,
            'balance' => 0,
        ];
//返回結果
        return $readPack;
    }

}

$money = getRandMoney(20, 10, 0.01);
var_dump($money);
$total = 20; //紅包總金額
$num = 10; // 分成10個紅包,支持10人隨機領取
$min = 0.01; //每個人最少能收到0.01元
$redpack = new redpack($total, $num, $min);
$jieguo = $redpack->getPack();
foreach ($jieguo as $key => $val) {
    $n = $key + 1;
    echo '第' . $n . '個紅包:' . $val['money'] . ' 元,餘額:' . $val['balance'] . ' 元<br>';
}

輸出結果:

array (size=2)
  'status' => int 1
  'data' => 
    array (size=10)
      0 => float 5.01
      1 => float 6.01
      2 => float 1.01
      3 => float 5.01
      4 => float 1.01
      5 => float 1.01
      6 => float 0.01
      7 => float 0.01
      8 => float 0.01
      9 => float 0.911個紅包:0.6 元,餘額:19.4 元
第2個紅包:1.23 元,餘額:18.17 元
第3個紅包:0.47 元,餘額:17.7 元
第4個紅包:1.12 元,餘額:16.58 元
第5個紅包:0.37 元,餘額:16.21 元
第6個紅包:3.4 元,餘額:12.81 元
第7個紅包:4.02 元,餘額:8.79 元
第8個紅包:3.85 元,餘額:4.94 元
第9個紅包:0.96 元,餘額:3.98 元
第10個紅包:0.96 元,餘額:0

不足點:實際情況中還需要考慮併發的情況,使用隊列或者加鎖。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章