基于PHP实现抽奖功能的算法怎么理解
Admin 2022-08-02 群英技术资讯 454 次浏览
没有特别幸运,那么请先特别努力,别因为懒惰而失败,还矫情地将原因归于自己倒霉。你必须特别努力,才能显得毫不费力。
希望:所以说,树倒了,没有一片雪花是无辜的,抽奖都是假的,只有人家想让你中和不想让你中,如果大家觉得文章有帮助,欢迎点赞。
<?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());
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
我们做网站开发的时候,有些需求会需要用到php正则表达式,对此,这篇文章就给大家分享一下php正则表达式使用方法,小编认为是比较实用的,大家可以参考一下。
序列化是将对象状态转换为可保持或可传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。将对象的状态信息转换为可以存储或传输的窗体的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。通常,对象实例的所有字段都会被序列化,这意味着数据会被表示为实例的序列化数据。这
在thinkphp中,L方法用于启用多语言的情况下,设置和获取当前的语言定义,设置语言定义的语法为“L('LANG_VAR','语言定义');”,获取语言定义的语法为“$langVar = L('LANG_VAR');”。
关于php中的信号处理器和信号处理操作,很多新手不是很清楚,这篇文章小编就给大家介绍一些关于php的信号说明以及信号处理操作,感兴趣的朋友可以看一看。
这篇文章主要介绍laravel数据库测试需要注意的事项,小编觉得比较实用,因此分享给大家作为参考,感兴趣的朋友可以参考一下,希望对大家学习有帮助,下面我们一起来了解一下。
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008