PHP一文带你搞懂游戏中的抽奖算法

 更新时间:2022-07-25 10:31:59   作者:佚名   我要评论(0)

目录前言一、初始化奖品二、谢谢参与三、过滤抽奖、如充值条件四、重组概率五、进行抽奖六、过滤回调七、最终抽奖结果八、抽奖封装成类前言

前言

没有特别幸运,那么请先特别努力,别因为懒惰而失败,还矫情地将原因归于自己倒霉。你必须特别努力,才能显得毫不费力。

希望:所以说,树倒了,没有一片雪花是无辜的,抽奖都是假的,只有人家想让你中和不想让你中,如果大家觉得文章有帮助,欢迎点赞。

一、初始化奖品

  • id 奖品的id
  • pid 奖品的自定义id
  • type 奖品类型,1、虚拟奖品 2、实物奖品 3、礼包码 待扩充
  • name 奖品名称
  • total 奖品总数
  • chance 获奖概率/抽奖基数10000
  • daynum 每日数量限制
  • pay 充值限制
<?php
$prize = [
    ['id' => 1, 'pid' => 11, 'type' => 1, 'name' => '典藏英雄', 'total' => 20, 'chance' => 1000, 'daynum' => 10, 'pay' => 2000 ],
    ['id' => 2, 'pid' => 12, 'type' => 1, 'name' => '史诗皮肤', 'total' => 40, 'chance' => 1000, 'daynum' => 10, 'pay' => 4000 ],
    ['id' => 3, 'pid' => 13, 'type' => 1, 'name' => '钻石奖励', 'total' => 80, 'chance' => 1000, 'daynum' => 10, 'pay' => 4000 ],
    ['id' => 4, 'pid' => 14, 'type' => 1, 'name' => '荣耀水晶', 'total' => 20, 'chance' => 1000, 'daynum' => 10, 'pay' => 8000 ]
];

 奖品详情应该从数据库中读出来

奖品详情应该加入缓存,避免数据库的压力

二、谢谢参与

<?php
$thanks_prize = [
    'id' => 0,
    'pid' => 0,
    'type' => 1,
    'name' => '谢谢参与'
];

为填充剩余概率的奖品

三、过滤抽奖、如充值条件

<?php
$pay_total = 7000;
foreach ($prize as $key => $value) {
    if($value['pay'] > $pay_total) unset($prize[$key]);
}

初步过滤一些必要因素,比如充值,角色创建时间等

四、重组概率

<?php
$now_chance = array_sum(array_column($prize, 'chance'));
$remain_chance = 10000 - $now_chance;
$prize[] = ['id' => 0, 'pid' => 0, 'type' => 1, 'name' => '谢谢参与', 'total' => 0, 'chance' => $remain_chance, 'daynum' => 0, 'pay' => 0];
 
$award = [];
$num = 0;
foreach ($prize as $_v) {
    $num += $_v['chance'];
    $award[] = ['id' => $_v['id'], 'pid' => $_v['pid'], 'type' => $_v['type'], 'name' => $_v['name'], 'total' => $_v['total'], 'chance' => $num, 'daynum' => $_v['daynum'], 'pay' => $_v['pay']];
}

初步过滤后,重构新的抽奖信息,加入谢谢参与

第二步重组概率

五、进行抽奖

<?php
$rand = mt_rand(1, 10000);
$result = [];
foreach ($award as $_k => $_v) {
    if ($_k == 0) {
        if ($rand > 0 && $rand <= $_v['chance']) {
            $result = $_v;
            break;
        }
    } else {
        if ($rand > $award[$_k - 1]['chance'] && $rand <= $_v['chance']) {
            $result = $_v;
            break;
        }
    }
}

开始抽奖,并返回抽中的结果

六、过滤回调

<?php
//此处应该查询数据库,查看该奖品已经抽中的数量
$yet_num = 50;
if($result['pid'] != 0 && $yet_num > $result['total']) {
    $result = $thanks_prize;
}
 
//此处应该查询数据库,查看该奖品今日已经抽中的数量
$yet_today_num = 50;
if($result['pid'] != 0 && $yet_today_num > $result['daynum']) {
    $result = $thanks_prize;
}

二次过滤,奖品总数的限制以及奖品的每日限制等 

七、最终抽奖结果

<?php
//删除敏感字段
unset($result['total'],$result['chance'],$result['daynum'],$result['pay']);
 
//返回最终抽奖结果
echo json_encode([
    'prize' => $award,
    'rand' => $rand,
    'result' => $result
]);

八、抽奖封装成类

<?php
/**
 * Created by PhpStorm.
 * User: autofelix
 * Date: 2020/10/30
 * Time: 13:14
 * Desc: 抽奖算法
 */
 
class Lottery
{
    /**
     * 概率基数
     * @var int
     */
    private $total_chance = 10000;
 
    /**
     * 谢谢参与奖励
     * @var array
     */
    private $thanks_prize = [
        'id' => 0,
        'pid' => 0,
        'type' => 1,
        'name' => '谢谢参与'
    ];
 
    /**
     * 奖池
     * @var array
     */
    private $prize = [
        ['id' => 1, 'pid' => 11, 'type' => 1, 'name' => '典藏英雄', 'total' => 20, 'chance' => 1000, 'daynum' => 10, 'pay' => 2000 ],
        ['id' => 2, 'pid' => 12, 'type' => 1, 'name' => '史诗皮肤', 'total' => 40, 'chance' => 1000, 'daynum' => 10, 'pay' => 4000 ],
        ['id' => 3, 'pid' => 13, 'type' => 1, 'name' => '钻石奖励', 'total' => 80, 'chance' => 1000, 'daynum' => 10, 'pay' => 4000 ],
        ['id' => 4, 'pid' => 14, 'type' => 1, 'name' => '荣耀水晶', 'total' => 20, 'chance' => 1000, 'daynum' => 10, 'pay' => 8000 ]
    ];
 
    /**
     * Lottery constructor.
     */
    public function __construct()
{
    }
 
    /**
     * @return int
     */
    private function get_user_pay()
{
        //这里应该调用接口,返回用户正确的充值信息
        return 3000;
    }
 
    /**
     * 重构奖池、重组概率
     * @return array
     */
    private function init_lottery_pond()
{
        $award = [];
 
        //充值限制
        $user_pay = $this->get_user_pay();
        foreach ($this->prize as $key => $value) {
            if($value['pay'] <= $user_pay) unset($this->prize[$key]);
        }
 
        //加入谢谢惠顾
        $now_chance = array_sum(array_column($this->prize, 'chance'));
        $remain_chance = $this->total_chance - $now_chance;
        $this->prize[] = ['id' => 0, 'pid' => 0, 'type' => 1, 'name' => '谢谢参与', 'total' => 0, 'chance' => $remain_chance, 'daynum' => 0, 'pay' => 0];
 
        //重组概率
        $num = 0;
        foreach ($this->prize as $_v) {
            $num += $_v['chance'];
            $award[] = ['id' => $_v['id'], 'pid' => $_v['pid'], 'type' => $_v['type'], 'name' => $_v['name'], 'total' => $_v['total'], 'chance' => $num, 'daynum' => $_v['daynum'], 'pay' => $_v['pay']];
        }
 
        return $award;
    }
 
    /**
     * 获取抽奖结果
     * @return array
     */
    public function get_prize()
{
        $award = $this->init_lottery_pond();
        $rand = mt_rand(1, $this->total_chance);
        $result = [];
        foreach ($award as $_k => $_v) {
            if ($_k == 0) {
                if ($rand > 0 && $rand <= $_v['chance']) {
                    $result = $_v;
                    break;
                }
            } else {
                if ($rand > $award[$_k - 1]['chance'] && $rand <= $_v['chance']) {
                    $result = $_v;
                    break;
                }
            }
        }
 
        $result = $this->filter($result);
        return $result;
    }
 
    /**
     * 抽奖过滤回调函数
     * @param $result
     * @return array
     */
    public function filter($result)
{
        //奖品总数限制,此处应该查数据库
        $yet_num = 50;
        if($result['pid'] != 0 && $yet_num > $result['total']) {
            $result = $this->thanks_prize;
        }
 
        //奖品每日数量限制,此处应该查数据库
        $yet_today_num = 50;
        if($result['pid'] != 0 && $yet_today_num > $result['daynum']) {
            $result = $this->thanks_prize;
        }
 
        //不暴露敏感信息
        unset($result['total'], $result['chance'], $result['daynum'], $result['pay'] );
        return $result;
    }
 
    private function __clone()
{
    }
}
 
echo json_encode((new Lottery())->get_prize());

以上就是PHP一文带你搞懂游戏中的抽奖算法的详细内容,更多关于PHP抽奖算法的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
  • PHP实现转盘抽奖算法分享
  • PHP编程实现计算抽奖概率算法完整实例
  • PHP抽奖算法程序代码分享
  • php编写的抽奖程序中奖概率算法
  • 适用于抽奖程序、随机广告的PHP概率算法实例

相关文章

  • PHP一文带你搞懂游戏中的抽奖算法

    PHP一文带你搞懂游戏中的抽奖算法

    目录前言一、初始化奖品二、谢谢参与三、过滤抽奖、如充值条件四、重组概率五、进行抽奖六、过滤回调七、最终抽奖结果八、抽奖封装成类前言
    2022-07-25
  • PHP实现常见排序算法的示例代码

    PHP实现常见排序算法的示例代码

    目录1、冒泡排序2、选择排序3、快速排序4、插入排序补充1、冒泡排序 两两相比,每循环一轮就不用再比较最后一个元素了,因为最后一个元素已经
    2022-07-25
  • 利用PHP?POST临时文件机制实现任意文件上传的方法详解

    利用PHP?POST临时文件机制实现任意文件上传的方法详解

    目录原理如何获取临时文件名$_FILESphpinfoglob如何利用该文件组合请求延长临时文件存在时间参考原理 向 PHP 发送 Post 数据包,如果数据包中
    2022-07-25
  • PHP中数组处理函数的使用方法详解

    PHP中数组处理函数的使用方法详解

    目录一、键、值操作函数二、数组元素个数有关的函数三、使用回调函数处理数组的函数四、数组的排序函数五、拆分,合并,分解,结合数组六、获
    2022-07-25
  • 基于PHP实现邮件实时通知功能

    基于PHP实现邮件实时通知功能

    目录一、安装环境二、下载 三、 邮箱设置四、php发送邮件五、php框架中使用一、安装环境 PHPMailer 需要 PHP 的 sockets 扩展支持 另外登录
    2022-07-25
  • 基于PHP实现原生增删改查的示例代码

    基于PHP实现原生增删改查的示例代码

    目录一、代码1、sql2、列表页(index.php)3、delete.php4、update.php5、create.php二、效果图一、代码 1、sql -- phpMyAdmin SQL Dump -- ve
    2022-07-25
  • PHP利用雪花(SnowFlake)算法生成唯一ID

    PHP利用雪花(SnowFlake)算法生成唯一ID

    目录一、雪花算法原理解析1. 分布式ID常见生成策略2. 雪花算法的结构二、PHP源码实现案例1.demo12.demo2这个算法的好处很简单可以在每秒产生
    2022-07-25
  • PHP平滑关闭/重启的实现方法

    PHP平滑关闭/重启的实现方法

    目录前言原理阻塞信号处理信号拼起来思考前言 写过 CLI 常驻进程的老司机肯定遇到过这么一个问题:在需要更新程序的时候,我要怎样才能安全关
    2022-07-25
  • PHP中时间处理类Carbon的用法详解

    PHP中时间处理类Carbon的用法详解

    目录1.Introduction2.Instantiation3.Localization4.Testing Aids()5.Getters6.Setters7.Fluent Setters8.IsSet1.Introduction Carbon 是php
    2022-07-25
  • PHP实战之投票系统的实现

    PHP实战之投票系统的实现

    目录一、实现代码1.sql2.html3.admin.php(增删改查投票的页面)密码:admi4.index.php投票的页面二、效果图一、实现代码 1.sql -- phpMyAd
    2022-07-25

最新评论