php 抽獎算法(適合九宮格和大轉(zhuǎn)盤)

/* 
 * 不同概率的抽獎原理就是把0到*(比重總數(shù))的區(qū)間分塊
 * 分塊的依據(jù)是物品占整個的比重逗抑,再根據(jù)隨機(jī)數(shù)種子來產(chǎn)生0-* 中的某個數(shù)
 * 判斷這個數(shù)是落在哪個區(qū)間上麦牺,區(qū)間對應(yīng)的就是抽到的那個物品蝴蜓。
 * 隨機(jī)數(shù)理論上是概率均等的,那么相應(yīng)的區(qū)間所含數(shù)的多少就體現(xiàn)了抽獎物品概率的不同单默。
 */  


    /**
     * 抽獎方法
     * @return [array] [抽獎情況]
     */
    public function doDraw()
    {
        // 獎品數(shù)組
        $proArr = array(
            // id => 獎品等級碘举, name => 獎品名稱, v => 獎品權(quán)重
            array('id'=>1,'name'=>'超級獎品','v'=>0),
            array('id'=>2,'name'=>'特等獎','v'=>1),
            array('id'=>3,'name'=>'一等獎','v'=>5),
            array('id'=>4,'name'=>'二等獎','v'=>10),
            array('id'=>5,'name'=>'三等獎','v'=>12),
            array('id'=>6,'name'=>'四等獎','v'=>22),
            array('id'=>7,'name'=>'五等獎','v'=>50),
            array('id'=>8,'name'=>'六等獎','v'=>100),
            array('id'=>9,'name'=>'七等獎','v'=>200),
            array('id'=>10,'name'=>'沒中獎','v'=>500),
        );

        // 獎品等級獎品權(quán)重數(shù)組
        $arr = [];
        foreach ($proArr as $key => $val) {
            $arr[$val['id']] = $val['v'];
        }
        // 中獎 id
        $rid = $this->get_rand($arr);


        /**模擬抽獎測試**/
/*        $i = 0;
        while ( $i < 10000) {
          $rid = $this->get_rand($arr);
          $res[] = $rid;
          $i++;
        }
        // 統(tǒng)計獎品出現(xiàn)次數(shù)
        $result = array_count_values($res);
        asort($result);
        foreach ($result as $id => $times) {
            foreach ($proArr as $gifts) {
                if($id == $gifts['id']){
                    $response[$gifts['name']] = $times;
                }
            }
        }
        dump($response);
        die;*/


        $result = [];
        // 中獎禮品
        $result['yes'] = $proArr[$rid-1]['name'];
        // 從原獎品數(shù)組中剔除已經(jīng)中獎禮品
        unset($proArr[$rid-1]);

        // 打亂數(shù)組排序
        shuffle($proArr);

        for ($i=0; $i < count($proArr); $i++) {
            $result['no'][] = $proArr[$i]['name'];
        }

        // foreach ($proArr as $k => $v) {
        //     // 沒中獎禮品
        //     $result['no'][] = $v['name'];
        // }

        dump($result);

    }

    /**
     * 抽獎算法
     * @param  array  $proArr 獎品等級獎品權(quán)重數(shù)組
     * @return [int]         中獎獎品等級
     */
    public function get_rand($proArr = array()) {
        if(empty($proArr)) die;
        $rid = '';

        // 概率數(shù)組的總權(quán)重
        $proSum = array_sum($proArr);

        // 概率數(shù)組循環(huán)
        foreach ($proArr as $k => $proCur) {
            // 從 1 到概率總數(shù)中任意取值
            $randNum = mt_rand(1, $proSum);
            // 判斷隨機(jī)數(shù)是否在概率權(quán)重中
            if ($randNum <= $proCur) {
                // 取出獎品 id
                $rid = $k;
                break;
            } else {
                // 如果隨機(jī)數(shù)不在概率權(quán)限中,則不斷縮小總權(quán)重搁廓,直到從獎品數(shù)組中取出一個獎品
                $proSum -= $proCur;
            }
        }

        unset($proArr);
        return $rid;
    }

測試方法:


    public function test(){

        $proArr = array(
            array('id'=>1,'name'=>'特等獎','v'=>1),
            array('id'=>2,'name'=>'一等獎','v'=>5),
            array('id'=>3,'name'=>'二等獎','v'=>10),
            array('id'=>4,'name'=>'三等獎','v'=>12),
            array('id'=>5,'name'=>'四等獎','v'=>22),
            array('id'=>6,'name'=>'沒中獎','v'=>500)
        );

        $result = array();
        foreach ($proArr as $key => $val) {
            $arr[$key] = $val['v'];
        }
        // 概率數(shù)組的總權(quán)重
        $proSum = array_sum($arr);

        // 概率數(shù)組循環(huán)
        foreach ($arr as $k => $v) {

            // 從 1 到概率總數(shù)中任意取值
            $randNum = mt_rand(1, $proSum);
            $aa[$k] = $randNum . '+' . $v . '+' . $proSum;
            if ($randNum <= $v) {
                $result = $proArr[$k];
                // 找到符合條件的值就跳出 foreach 循環(huán)
                // dump($result);
                break;
            } else {
                $proSum = $proSum - $v;
                $bb[$k] = $randNum . '+' . $v . '+' . $proSum;
            }

        }

        dump($aa);
        dump($bb);
        // // dump($result);
        // // dump(__DIR__);
        // $path = __DIR__ . DS . 'log';
        // if(!is_dir($path)){
        //     mkdir($path);
        // }

        // $fileName = $path . DS . 'log.txt';
        // 創(chuàng)建文件和打開文件的函數(shù)都是 fopen
        // $cFile = fopen($fileName,'a+');
        // $a = json_encode($aa) . "\r\n";
        // $b = json_encode($bb) . "\r\n";
        // fwrite($cFile,$a);
        // fwrite($cFile,$b);
        // fclose($cFile);

        // 讀文件
        // $lines = file($fileName);
        // foreach ($lines as $key => $value) {
        //     dump($value.'555555555');
        // }
        // dump($lines);

    }

以下代碼也是意義程度上相同的代碼引颈,但是這種算法用的不多

function get_rand($proArr) 
{   
    $result = array();
    foreach ($proArr as $key => $val) { 
        $arr[$key] = $val['v']; 
    }  
    $proSum = array_sum($arr);      // 計算總權(quán)重
    $randNum = mt_rand(1, $proSum);
    $d1 = 0;
    $d2 = 0;
    for ($i=0; $i < count($arr); $i++)
    {
        $d2 += $arr[$i];
        if($i==0)
        {
            $d1 = 0;
        }
        else
        {
            $d1 += $arr[$i-1];
        }
        if($randNum >= $d1 && $randNum <= $d2)
        {
            $result = $proArr[$i];
        }
    }
    unset ($arr); 
    return $result;
}

// 開啟百分百中獎模式

<?php
    
    /**
    *  $prize_arr 參與抽獎人員數(shù)據(jù)
    *  id: 一般是成員ID
    *  name 姓名
    *  v   得獎概率
    ***/
    $prize_arr = array( 
        '0' => array('id'=>1,'name'=>'小王','v'=>1), 
        '1' => array('id'=>2,'name'=>'小李','v'=>5), 
        '2' => array('id'=>3,'name'=>'小張','v'=>10), 
        '3' => array('id'=>4,'name'=>'小二','v'=>12), 
        '4' => array('id'=>5,'name'=>'小菜','v'=>22), 
        '6' => array('id'=>6,'name'=>'小范','v'=>50), 
        '7' => array('id'=>7,'name'=>'小范01','v'=>50), 
        '8' => array('id'=>8,'name'=>'小范02','v'=>100), 
        '9' => array('id'=>9,'name'=>'小范03','v'=>50), 
        '10' => array('id'=>10,'name'=>'小范04','v'=>50), 
        '11' => array('id'=>11,'name'=>'小范05','v'=>50), 
        '12' => array('id'=>12,'name'=>'小范06','v'=>50), 
        '13' => array('id'=>13,'name'=>'小范07','v'=>50), 
        '14' => array('id'=>14,'name'=>'小范08','v'=>50), 
        '15' => array('id'=>15,'name'=>'小范09','v'=>100), 
        '16' => array('id'=>16,'name'=>'小范10','v'=>100), 
    );  

    foreach ($prize_arr as $key => $val) { 
        $arr[$key] = $val['v']; 
    } 
    
    $total_num = '8'; //設(shè)定得中獎人數(shù)量
    
    $temp_rest=array();
    for($i=0;$i<$total_num;$i++)
    {
        $rid = get_rand($arr,true); //根據(jù)概率獲取人員ID
        $temp_rest[]= $prize_arr[$rid]; //中獎項
        unset($prize_arr[$rid]); 
        unset($arr[$rid]); 
    }

    print_r($temp_rest);//得出結(jié)果

    /****
    *   得出當(dāng)前中獎人
    *   $is_status是否開啟概率為100必中: 默認(rèn)不開啟 
    ***/
    function get_rand($proArr,$is_status = false) { 
        $result = ''; 
        if($is_status){
            $rest = get_100($proArr);  //調(diào)用獲取100命中
        }else{ 
            $rest ='';
        }

        if(empty($rest) || !isset($rest)){
            //概率數(shù)組的總概率精度
            $proSum = array_sum($proArr); 
            //概率數(shù)組循環(huán)
            foreach ($proArr as $key => $proCur) { 
                $randNum = mt_rand(1, $proSum); 
                if ($randNum <= $proCur) { 
                    $result = $key; 
                    break; 
                } else { 
                    $proSum -= $proCur; 
                }   
            } 
        }else{
            $result = $rest;
        }
        unset ($proArr); 
        return $result; 
    }
    function get_100($arr_mast){
        $result = ''; 
        foreach ($arr_mast as $key => $value_mast) { 
           if($value_mast== 100){
                $result = $key; 
                break; 
           }
          
        } 
        unset ($arr_mast); 
        return $result; 
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市境蜕,隨后出現(xiàn)的幾起案子蝙场,更是在濱河造成了極大的恐慌,老刑警劉巖粱年,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件售滤,死亡現(xiàn)場離奇詭異,居然都是意外死亡台诗,警方通過查閱死者的電腦和手機(jī)完箩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拉队,“玉大人弊知,你說我怎么就攤上這事×豢欤” “怎么了秩彤?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵叔扼,是天一觀的道長。 經(jīng)常有香客問我漫雷,道長瓜富,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任珊拼,我火速辦了婚禮食呻,結(jié)果婚禮上流炕,老公的妹妹穿的比我還像新娘澎现。我一直安慰自己,他們只是感情好每辟,可當(dāng)我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布剑辫。 她就那樣靜靜地躺著,像睡著了一般渠欺。 火紅的嫁衣襯著肌膚如雪妹蔽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天挠将,我揣著相機(jī)與錄音胳岂,去河邊找鬼。 笑死舔稀,一個胖子當(dāng)著我的面吹牛乳丰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播内贮,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼产园,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了夜郁?” 一聲冷哼從身側(cè)響起什燕,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎竞端,沒想到半個月后屎即,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡事富,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年技俐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赵颅。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡虽另,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出饺谬,到底是詐尸還是另有隱情捂刺,我是刑警寧澤谣拣,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站族展,受9級特大地震影響森缠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜仪缸,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一贵涵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧恰画,春花似錦宾茂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至片林,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間费封,已是汗流浹背焕妙。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留弓摘,地道東北人焚鹊。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像衣盾,于是被迫代替她去往敵國和親寺旺。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內(nèi)容