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

吾爱主题 阅读:130 2022-11-11 16:09:00 评论:0

前言

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

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

一、初始化奖品

  • id 奖品的id
  • pid 奖品的自定义id
  • type 奖品类型,1、虚拟奖品 2、实物奖品 3、礼包码 待扩充
  • name 奖品名称
  • total 奖品总数
  • chance 获奖概率/抽奖基数10000
  • daynum 每日数量限制
  • pay 充值限制
?
1 2 3 4 5 6 7 <?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 ] ];

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

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

二、谢谢参与

?
1 2 3 4 5 6 7 <?php $thanks_prize = [      'id' => 0,      'pid' => 0,      'type' => 1,      'name' => '谢谢参与' ];

为填充剩余概率的奖品

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

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

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

四、重组概率

?
1 2 3 4 5 6 7 8 9 10 11 <?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' ]]; }

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

第二步重组概率

五、进行抽奖

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?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 ;          }      } }

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

六、过滤回调

?
1 2 3 4 5 6 7 8 9 10 11 12 <?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 ; }

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

七、最终抽奖结果

?
1 2 3 4 5 6 7 8 9 10 <?php //删除敏感字段 unset( $result [ 'total' ], $result [ 'chance' ], $result [ 'daynum' ], $result [ 'pay' ]);   //返回最终抽奖结果 echo json_encode([      'prize' => $award ,      'rand' => $rand ,      'result' => $result ]);

八、抽奖封装成类

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 <?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抽奖算法的资料请关注服务器之家其它相关文章!

原文链接:https://mp.weixin.qq.com/s/19u6Ag06IntC_2ohijhRhg

可以去百度分享获取分享代码输入这里。
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

【腾讯云】云服务器产品特惠热卖中
搜索
标签列表
    关注我们

    了解等多精彩内容