• 游戏中转轮抽奖的算法实现[转]


    抽奖

    由于最近项目需要做一个抽奖活动,于是实现了一个简单的抽奖算法,可以控制抽奖概率。提到抽奖,想必大家都见过玩过转轮抽奖吧,投一个币,然后转轮抽奖开始转动,当几个轮子的图片都是一样的时候就表示中奖了(当然还有大转盘的玩法,即投币后指针开始转动,转动停止后指针指向的那个位置就是判断中奖与否)。

    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]
    ============================抽奖结束===============================
  • 相关阅读:
    第二周总结
    币值转换
    抓老鼠
    秋季学习总结
    第七周作业
    第六周作业
    2019年春季第五周
    2019年春季学期第四周作业
    2019年春季学期第三周作业
    2019年春季学期第二周作业
  • 原文地址:https://www.cnblogs.com/sybboy/p/5754096.html
Copyright © 2020-2023  润新知