目录

一、初始化奖品

二、谢谢参与

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

四、重组概率

五、进行抽奖

六、过滤回调

七、最终抽奖结果

八、抽奖封装成类


一、初始化奖品

  • 奖品详情应该从数据库中读出来
  • 奖品详情应该加入缓存,避免数据库的压力
<?php
// id 奖品的id
// pid 奖品的自定义id
// type 奖品类型,1、虚拟奖品 2、实物奖品 3、礼包码 待扩充
// name 奖品名称
// total 奖品总数
// chance 获奖概率/抽奖基数10000
// daynum 每日数量限制
// pay 充值限制
$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());

一文搞懂│王者游戏中荣耀水晶难抽?探索游戏中的抽奖算法相关推荐

  1. php算法抽荣耀水晶,还在抱怨王者荣耀水晶难抽?PHP一文带你搞懂游戏中的抽奖算法...

    前言: 没有特别幸运,那么请先特别努力,别因为懒惰而失败,还矫情地将原因归于自己倒霉.你必须特别努力,才能显得毫不费力. 希望:所以说,树倒了,没有一片雪花是无辜的,抽奖都是假的,只有人家想让你中和不 ...

  2. 一文搞懂Qt中的颜色渐变(QGradient Class)

    一文搞懂Qt中的颜色渐变(QGradient Class) 1, 快速开始! Qt中与颜色渐变有关的类是QGradient 其中它又有三个子类:QLinearGradient.QRadialGradi ...

  3. python中gbk字符原因报错_不想再被鄙视?那就看进来! 一文搞懂 Python 2 字符编码...

    原标题:不想再被鄙视?那就看进来! 一文搞懂 Python 2 字符编码 程序员都自视清高,觉得自己是创造者,经常鄙视不太懂技术的产品或者QA.可悲的是,程序员之间也相互鄙视,程序员的鄙视链流传甚广, ...

  4. 【UE·蓝图底层篇】一文搞懂NativeClass、GeneratedClass、BlueprintClass、ParentClass

    本文将对蓝图类UBlueprint的几个UClass成员变量NativeClass.GeneratedClass.BlueprintClass.ParentClass进行比较深入的讲解,看完之后对蓝图 ...

  5. 一文搞懂 Cocos Creator 3.0 坐标转换原理

    一文搞懂 Cocos Creator 3.0 坐标转换原理 屏幕坐标 UI 触点坐标 UI 多分辨率适配方案 UI 触点获取 不同坐标之间的转换 屏幕坐标与 3D 节点世界坐标互转 3D 节点之间的坐 ...

  6. 【显卡】一文搞懂显卡

    [显卡]一文搞懂显卡 文章目录 [显卡]一文搞懂显卡 1. 前言介绍 1.1 CPU和显卡的区别 1.1.1 作用不同 1.1.2 结构不同 1.1.3 应用场景不同 1.2 三个著名的显卡公司 2. ...

  7. 一文搞懂什么VR,什么是6Dof,欧拉角,四元数转视图矩阵

    目录 一.什么是VR 二.什么是3Dof,6Dof, 9Dof 三.欧拉角(姿态角) 四.Android手机的欧拉角与坐标系 五.安卓坐标系转换欧拉角 六.根据姿态四元数求视图矩阵 一文搞懂什么VR, ...

  8. 一文搞懂RNN(循环神经网络)

    基础篇|一文搞懂RNN(循环神经网络) https://mp.weixin.qq.com/s/va1gmavl2ZESgnM7biORQg 神经网络基础 神经网络可以当做是能够拟合任意函数的黑盒子,只 ...

  9. 一文搞懂 Python 的 import 机制

    一.前言 希望能够让读者一文搞懂 Python 的 import 机制 1.什么是 import 机制? 通常来讲,在一段 Python 代码中去执行引用另一个模块中的代码,就需要使用 Python ...

最新文章

  1. 构建一个增量推荐系统
  2. 关于自动驾驶, Mobileye 的 14 个最新观点
  3. layer用ajax往jsp页面传值,layer.open中父页面向子页面传值(示例代码)
  4. RxJava 和 RxAndroid 二(操作符的使用)
  5. java泛型学习一:解惑继承
  6. easyui 如何为标签动态追加属性实现渲染效果
  7. 不懂这25个名词,好意思说你懂大数据?
  8. JavaEE实战班第18天
  9. 亿元大奖后抑郁被网友质疑卖惨 信小呆:不想再被打扰
  10. 1700x关闭超线程超频_转发分享一个超频技术新手知识BIOS设置指南
  11. 随想录(elf文件)
  12. 从1亿个ip中找出访问次数最多的IP
  13. 虚拟机中PXE-MOF:Exiting intel PXE ROM.Operating system not found解决方法
  14. 【Java万字笔记】重要基础知识点整理与汇总
  15. python在excel中的应用:freeze_panes冻结不是第一行的问题,其实可能是一个小细节。
  16. 支付宝签名php,支付宝快捷支付 PHP服务端签名
  17. Graph Convolutional Tracking
  18. java去掉转义字符,双引号,全角空格
  19. laravel配置语言包,实现网站中英文切换
  20. 处理器博通还是高通比较好_苹果手机基带高通还是Intel好?iPhone查看基带生产商厂家方法...

热门文章

  1. 【OpenCall】ICASSP2023通用会议理解及生成挑战赛邀请函
  2. 如何采集QQ群中所有成员QQ号码
  3. 【综合类型第 10 篇】什么是时间戳
  4. 靶机12 PENTESTER LAB: XSS AND MYSQL FILE
  5. 百度android 定位返回161,重拾百度定位之踩坑篇(下)
  6. SQL*Plus中 Set timing on的时间显示单位
  7. iOS 编译过程的原理和应用
  8. 编译Android源码(9.0)
  9. Qt 绘制拖动刻度尺
  10. Android实现word模板套打功能