PHP一文带你搞懂游戏中的抽奖算法
目录
- 前言
- 一、初始化奖品
- 二、谢谢参与
- 三、过滤抽奖、如充值条件
- 四、重组概率
- 五、进行抽奖
- 六、过滤回调
- 七、最终抽奖结果
- 八、抽奖封装成类
前言 没有特别幸运,那么请先特别努力,别因为懒惰而失败,还矫情地将原因归于自己倒霉。你必须特别努力,才能显得毫不费力。
希望:所以说,树倒了,没有一片雪花是无辜的,抽奖都是假的,只有人家想让你中和不想让你中,如果大家觉得文章有帮助,欢迎点赞。
一、初始化奖品
- id 奖品的id
- pid 奖品的自定义id
- type 奖品类型,1、虚拟奖品 2、实物奖品 3、礼包码 待扩充
- name 奖品名称
- total 奖品总数
- chance 获奖概率/抽奖基数10000
- daynum 每日数量限制
- pay 充值限制
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 ]];
奖品详情应该从数据库中读出来
奖品详情应该加入缓存,避免数据库的压力
二、谢谢参与
0,'pid' => 0,'type' => 1,'name' => '谢谢参与'];
为填充剩余概率的奖品
三、过滤抽奖、如充值条件
$value) {if($value['pay'] > $pay_total) unset($prize[$key]); }
初步过滤一些必要因素,比如充值,角色创建时间等
四、重组概率
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']]; }
初步过滤后,重构新的抽奖信息,加入谢谢参与
第二步重组概率
五、进行抽奖
$_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['total']) {$result = $thanks_prize; } //此处应该查询数据库,查看该奖品今日已经抽中的数量$yet_today_num = 50; if($result['pid'] != 0 && $yet_today_num > $result['daynum']) {$result = $thanks_prize; }
二次过滤,奖品总数的限制以及奖品的每日限制等
七、最终抽奖结果
$award,'rand' => $rand,'result' => $result]);
八、抽奖封装成类
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使用SW-X框架的Redis-UML组件,对用户信息进行缓存读写
- [ C语言 ]一篇带你了解浮点型在内存中的存储
- 如何为项目构建高效的统一文件存储方案
- 面试|PHP 基础知识
- 一文详解C#中方法重载的底层玩法
- 一文看懂博睿数据AIOps场景算法和能力
- docker|一文带你入门docker
- 带你轻松了解Modbus协议
- [ C语言 ]一篇带你初识结构体--用C语言描述一个复杂对象
- PHP(解析url和查询参数query)