游戲中轉輪抽獎的算法實現[轉]


抽獎

由於最近項目需要做一個抽獎活動,於是實現了一個簡單的抽獎算法,可以控制抽獎概率。提到抽獎,想必大家都見過玩過轉輪抽獎吧,投一個幣,然后轉輪抽獎開始轉動,當幾個輪子的圖片都是一樣的時候就表示中獎了(當然還有大轉盤的玩法,即投幣后指針開始轉動,轉動停止后指針指向的那個位置就是判斷中獎與否)。

1、抽獎原理

假設現在有三個轉輪,每個轉輪上有(1~10)數字圖片。中獎情況如下:

wps_clip_image-2906

每一次投幣之后,系統會返回3個數字,中獎情況可以自由設定:

* 三個數字都相同:中大獎

* 三個數字中有兩個相同:中小獎或不算中獎

* 三個數字都不同:沒中獎

2、概率控制

每一個數字都有相應的概率值:

 
數字    物品    概率       
1    蘋果    5%       
2    橘子    7%       
3    香蕉    9%       
4    葡萄    13%       
5    荔枝    12%       
6    柚子    14%       
7    橙子    10%       
8    柿子    11%       
9    西瓜    8%       
10   芒果   11%    

每個轉輪轉動一次后會隨機(根據概率)選中一個數字。

每個轉輪上的數字的順序是隨機分配的。

第一個轉輪選取過程(第一個默認順序):

 
數字    物品    概率區段       
1    蘋果    0~5%       
2    橘子    5~12%       
3    香蕉    12~21%       
4    葡萄    21~34%       
5    荔枝    34~46%       
6    柚子    46~60%       
7    橙子    60~70%       
8    柿子    70~81%       
9    西瓜    81~89%       
10    芒果    89~100%    

* 在1~100之間產生一個隨機數如:56

* 根據產生的隨機數 56 放到轉輪一中的概率區段去匹配,中獎數字是:6

第二個轉輪選取過程:

 
數字    物品    概率區段       
2    橘子    0~7%       
1    蘋果    7~12%       
3    香蕉    12~21%       
5    荔枝    21~33%       
4    葡萄    33~46%       
6    柚子    46~60%       
7    橙子    60~70%       
8    柿子    70~81%       
10   芒果    81~92%       
9    西瓜    92~100%    

* 在1~100之間產生一個隨機數如:77

* 根據產生的隨機數77放到轉輪一中的概率區段去匹配,中獎數字是:8

第三個轉輪選取過程:

 
數字    物品    概率區段       
4    葡萄    0~13%       
10    芒果    13~24%       
7    橙子    24~34%       
1    蘋果    34~39%       
9    西瓜    39~47%       
6    柚子    47~61%       
3    香蕉    61~70%       
8    柿子    70~81%       
5    荔枝    81~93%       
2    橘子    93~100%    

* 在1~100之間產生一個隨機數如:21

* 根據產生的隨機數21放到轉輪一中的概率區段去匹配,中獎數字是:10

最終的抽獎結果:6,8,10即:柚子,柿子,芒果,未中獎

3、代碼

* 獎品類
package com.lottery.model;

/**
 * @author zyd
 * @date 2012-10-3
 * @desc:
 * 抽獎獎品
 */
public class Reward {
    
    /**
     * 獎品編號
     */
    public int index;
    
    /**
     * 獎品名稱
     */
    public String name;
    
    /**
     * 中獎概率
     */
    public int succPercent;

    
    public Reward(int index, String name, int succPercent) {
        super();
        this.index = index;
        this.name = name;
        this.succPercent = succPercent;
    }


    @Override
    public String toString() {
        return "Reward [index=" + index + ", name=" + name + ", succPercent="
                + succPercent + "]";
    }
    
    
}
* 抽獎算法類
package com.lottery.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import com.lottery.model.Reward;

/**
 * @author zyd
 * @date 2012-10-3
 * @desc:
 * 抽獎主類
 */
public class Lottery {
    
    public static List<Reward> randomList;
    /**
     * 獲取中獎編碼數組
     * @param rlist
     * @param keyLength
     * @return
     */
    public List<Reward> getKeys(List<Reward> rlist,int keyLength){
        List<Reward> list = new ArrayList<Reward>();
        for(int i=0;i<keyLength;i++){
            list.add(getKey(rlist));
        }
        return list;
    }

    /**
     * 獲取中獎編碼
     * @param rlist
     * @return
     */
    private Reward getKey(List<Reward> rlist) {
        //隨機列表
        List<Reward> randomList = getRandomList(rlist);
        //根據隨機列表得到的概率區段
        List<Integer> percentSteps = getPercentSteps(rlist);
        //概率區段的最大值
        int maxPercentStep = percentSteps.get(percentSteps.size()-1);
        //在概率區段范圍內取一個隨機數
        int randomStep = new Random().nextInt(maxPercentStep);
        //中間元素的下標
        int keyIndex = 0;
        int begin = 0;
        int end = 0;
        for(int i=0;i<percentSteps.size();i++){
            if(i == 0){
                begin = 0;
            }else{
                begin = percentSteps.get(i-1);
            }
            end = percentSteps.get(i);
            //判斷隨機數值是否在當前區段范圍內
            if(randomStep>begin && randomStep<=end){
                keyIndex = i;
                break;
            }
        }
        return randomList.get(keyIndex);
    }
    
    /**
     * 獲取概率區段[如:10,15,25,30,40,60,75,80,90,95,100]
     * @param rlist
     * @return
     */
    private List<Integer> getPercentSteps(List<Reward> rlist) {
        List<Integer> percentSteps = new ArrayList<Integer>();
        int percent = 0;
        for(Reward r: rlist){
            percent += r.succPercent;
            percentSteps.add(percent);
        }
        return percentSteps;
    }

    /**
     * 獲取隨機列表
     * @param rlist
     * @return
     */
    private List<Reward> getRandomList(List<Reward> rlist){
        List<Reward> oldList = new ArrayList<Reward>(rlist);
        List<Reward> newList = new ArrayList<Reward>();
        //隨機排序的老序列中元素的下標
        int randomIndex = 0; 
        //隨機排序下標的取值范圍
        int randomLength = 0;
        for(int i=0;i<rlist.size();i++){
            //指向下標范圍
            randomLength = oldList.size()-1;
            //取值范圍元素的個數為多個時,從中隨機選取一個元素的下標
            if(randomLength != 0){
                randomIndex = new Random().nextInt(randomLength);
            //取值范圍元素的個數為一個時,直接返回該元素的下標
            }else{
                randomIndex = 0;
            }
            //在新的序列當中添加元素,同時刪除元素取值范圍中的randomIndex下標所對應的元素
            newList.add(oldList.remove(randomIndex));
        }
        return newList;
    }
    
    
}
* 測試類
package com.lottery.test;

import java.util.ArrayList;
import java.util.List;

import com.lottery.model.Reward;
import com.lottery.util.Lottery;

/**
 * @author zyd
 * @date 2012-10-3
 * @desc:
 * 測試
 */
public class Test {
    
    public static void main(String[] args){
        List<Reward> rlist = initRewards();
        Lottery lottery = new Lottery();
        List<Reward> rewards = null;
        for(int i=0;i<1000;i++){
            rewards = lottery.getKeys(rlist, 3);
            if(isWinner(rewards)){
                System.out.println("============================抽獎開始  第"+i+"次 ===============================");
                for(Reward r:rewards){
                    System.out.println(r);
                }
                System.out.println("============================抽獎結束===============================");
            }
        }
    }
    
    public static boolean isWinner(List<Reward> list){
        boolean isWinner = false;
        for(int i=0;i<list.size();i++){
            for(int j=i+1;j<list.size();j++){
                if(list.get(i).index != list.get(j).index){
                    return false;
                }else{
                    isWinner =true;
                }
            }
        }
        return isWinner;
    }
    
    public static List<Reward> initRewards(){
        List<Reward> rlist = new ArrayList<Reward>();
        rlist.add(new Reward(1, "香蕉", 5));
        rlist.add(new Reward(2, "蘋果", 15));
        rlist.add(new Reward(3, "橘子", 5));
        rlist.add(new Reward(4, "葡萄", 15));
        rlist.add(new Reward(5, "荔枝", 5));
        rlist.add(new Reward(6, "西瓜", 5));
        rlist.add(new Reward(7, "柚子", 20));
        rlist.add(new Reward(8, "橙子", 10));
        rlist.add(new Reward(9, "柿子", 5));
        rlist.add(new Reward(10, "芒果", 15));
        return rlist;
    }
}

*    測試輸出
============================抽獎開始  第82次 ===============================
Reward [index=1, name=香蕉, succPercent=5]
Reward [index=1, name=香蕉, succPercent=5]
Reward [index=1, name=香蕉, succPercent=5]
============================抽獎結束===============================
============================抽獎開始  第115次 ===============================
Reward [index=9, name=柿子, succPercent=5]
Reward [index=9, name=柿子, succPercent=5]
Reward [index=9, name=柿子, succPercent=5]
============================抽獎結束===============================
============================抽獎開始  第510次 ===============================
Reward [index=9, name=柿子, succPercent=5]
Reward [index=9, name=柿子, succPercent=5]
Reward [index=9, name=柿子, succPercent=5]
============================抽獎結束===============================
============================抽獎開始  第542次 ===============================
Reward [index=9, name=柿子, succPercent=5]
Reward [index=9, name=柿子, succPercent=5]
Reward [index=9, name=柿子, succPercent=5]
============================抽獎結束===============================
============================抽獎開始  第584次 ===============================
Reward [index=9, name=柿子, succPercent=5]
Reward [index=9, name=柿子, succPercent=5]
Reward [index=9, name=柿子, succPercent=5]
============================抽獎結束===============================
============================抽獎開始  第706次 ===============================
Reward [index=5, name=荔枝, succPercent=5]
Reward [index=5, name=荔枝, succPercent=5]
Reward [index=5, name=荔枝, succPercent=5]
============================抽獎結束===============================

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM