TP5 实现转盘抽奖

1、实现

转盘分多种情况,常见的有 不同中奖几率的奖品限定数量的奖品限定数量和中奖几率的奖品

1.1、不同中奖几率的奖品 的实现

1)计算出总概率的精度M
2)然后将所有的概率数组依次遍历
3)遍历中随机取出一个1~M的数字
4)如果随机数比当前这个数概率小,则表示命中。
5)反之则将总精度减去当前未命中的概率,表示剩余的总概率

总精度是为了生成随机数,而减去未命中的概率是为了排除出去,最后必定会命中

1.1.1、代码实现
  • 传入的数组对应原有下标的一维数组,值为概率,整数/小数都可以
  • 计算完后返回对应的下标,再可根据下标找到对应下标的中奖内容即可

测试的中奖几率的方法

/**
 * 测试中奖概率
 */
public function test()
{
    //获取奖品列表
    $appAnglePrize =db('奖品配置表')->where('status', 1)->field('name as "奖项",rate')->order('weigh', 'DESC')->select();
    //获取对应的几率数组
    $rateArr = array_column($appAnglePrize, 'rate');
    foreach ($appAnglePrize as $k => $v) {
        $appAnglePrize[$k]['中奖次数'] = 0;
        $appAnglePrize[$k]['概率'] = strval($v['rate']) . '%';
        unset($appAnglePrize[$k]['rate']);
    }
    for ($i = 0; $i < 10000; $i++) {
        $result = $this->getRandPrize($rateArr);
        $appAnglePrize[$result]['中奖次数']++;
    }
    $this->success($appAnglePrize);
}

抽奖方法

/**
 * 返回转盘抽奖结果
 * @param array $proArr 概率数组(值为概率)
 * @return int|string 返回对应数组的下标
 */
private function getRandPrize($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;
}
1.1.2、测试
TP5 实现转盘抽奖_第1张图片

1)我们可以看出已经很接近对应的概率了。
2)我这里是跑一万次,我分别跑了好几次观察结果是可行的。

你可能感兴趣的:(TP5 实现转盘抽奖)