PHP一文帶你搞懂游戲中的抽獎算法
前言
沒有特別幸運,那么請先特別努力,別因為懶惰而失敗,還矯情地將原因歸于自己倒霉。你必須特別努力,才能顯得毫不費力。
希望:所以說,樹倒了,沒有一片雪花是無辜的,抽獎都是假的,只有人家想讓你中和不想讓你中,如果大家覺得文章有幫助,歡迎點贊。
一、初始化獎品
- id 獎品的id
- pid 獎品的自定義id
- type 獎品類型,1、虛擬獎品 2、實物獎品 3、禮包碼 待擴(kuò)充
- name 獎品名稱
- total 獎品總數(shù)
- chance 獲獎概率/抽獎基數(shù)10000
- daynum 每日數(shù)量限制
- 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 ] ];
獎品詳情應(yīng)該從數(shù)據(jù)庫中讀出來
獎品詳情應(yīng)該加入緩存,避免數(shù)據(jù)庫的壓力
二、謝謝參與
<?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]); }
初步過濾一些必要因素,比如充值,角色創(chuàng)建時間等
四、重組概率
<?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']]; }
初步過濾后,重構(gòu)新的抽獎信息,加入謝謝參與
第二步重組概率
五、進(jìn)行抽獎
<?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; } } }
開始抽獎,并返回抽中的結(jié)果
六、過濾回調(diào)
<?php //此處應(yīng)該查詢數(shù)據(jù)庫,查看該獎品已經(jīng)抽中的數(shù)量 $yet_num = 50; if($result['pid'] != 0 && $yet_num > $result['total']) { $result = $thanks_prize; } //此處應(yīng)該查詢數(shù)據(jù)庫,查看該獎品今日已經(jīng)抽中的數(shù)量 $yet_today_num = 50; if($result['pid'] != 0 && $yet_today_num > $result['daynum']) { $result = $thanks_prize; }
二次過濾,獎品總數(shù)的限制以及獎品的每日限制等
七、最終抽獎結(jié)果
<?php //刪除敏感字段 unset($result['total'],$result['chance'],$result['daynum'],$result['pay']); //返回最終抽獎結(jié)果 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 { /** * 概率基數(shù) * @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() { //這里應(yīng)該調(diào)用接口,返回用戶正確的充值信息 return 3000; } /** * 重構(gòu)獎池、重組概率 * @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; } /** * 獲取抽獎結(jié)果 * @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; } /** * 抽獎過濾回調(diào)函數(shù) * @param $result * @return array */ public function filter($result) { //獎品總數(shù)限制,此處應(yīng)該查數(shù)據(jù)庫 $yet_num = 50; if($result['pid'] != 0 && $yet_num > $result['total']) { $result = $this->thanks_prize; } //獎品每日數(shù)量限制,此處應(yīng)該查數(shù)據(jù)庫 $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一文帶你搞懂游戲中的抽獎算法的詳細(xì)內(nèi)容,更多關(guān)于PHP抽獎算法的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
PHP接收json 并將接收數(shù)據(jù)插入數(shù)據(jù)庫的實現(xiàn)代碼
這篇文章主要介紹了PHP接收json 并將接收數(shù)據(jù)插入數(shù)據(jù)庫的實現(xiàn)代碼,需要的朋友可以參考下2015-12-12PHP輸出圖像imagegif、imagejpeg與imagepng函數(shù)用法分析
這篇文章主要介紹了PHP輸出圖像imagegif、imagejpeg與imagepng函數(shù)用法,結(jié)合實例形式較為詳細(xì)的分析了imagegif()、imagejpeg()、imagepng()和imagewbmp()函數(shù)的功能、參數(shù)含義及使用技巧,需要的朋友可以參考下2016-11-11php實現(xiàn)的微信分享到朋友圈并記錄分享次數(shù)功能
這篇文章主要介紹了php實現(xiàn)的微信分享到朋友圈并記錄分享次數(shù)功能,結(jié)合實例形式分析了php微信分享功能接口調(diào)用及分享次數(shù)統(tǒng)計具體操作技巧,需要的朋友可以參考下2018-01-01