zoukankan      html  css  js  c++  java
  • Java实现抽奖功能

    主要根据概率返回每次抽到的奖品,
    以下是抽奖工具类

    package com.ruoyi.project.dy.utils;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    
    /**
     * @description:
     *  抽奖工具类,概率和可以不等于1
     *  概率为百分数去掉百分号的部分,如10%,则为10
     *  抽奖操作如下:
     *  1.输入抽奖概率集合,【抽奖概率集合为{10.0, 20.0, 30.0}】
     *  2.生成连续集合,       【生成的连续集合为{(0.0, 10.0],(10.0, 30.0],(30.0, 60.0]}】
     *  3.生成随机数,          【生成方法为 random.nextDouble() * maxElement】
     *  4.判断随机数在哪个区间内,返回该区间的index【生成了随机数12.001,则它属于(10.0, 30.0],返回 index = 1】
     *
     *  */
    public class LotteryUtil {
        /**
         * 定义一个连续集合
         * 集合中元素x满足:(minElement,maxElement]
         * 数学表达式为:minElement < x <= maxElement
         *
         */
        public class ContinuousList {
    
            private double minElement;
            private double maxElement;
    
            public ContinuousList(double minElement, double maxElement){
                if(minElement > maxElement){
                    throw new IllegalArgumentException("区间不合理,minElement不能大于maxElement!");
                }
                this.minElement = minElement;
                this.maxElement = maxElement;
            }
    
            /**
             * 判断当前集合是否包含特定元素
             * @param element
             * @return
             */
            public boolean isContainKey(double element){
                boolean flag = false;
                if(element > minElement && element <= maxElement){
                    flag = true;
                }
                return flag;
            }
    
        }
    
        private List<ContinuousList> lotteryList;
        //概率连续集合
        private double maxElement;
        //这里只需要最大值,最小值默认为0.0
    
        /**
         * 构造抽奖集合
         * @param list 为奖品的概率
         */
        public LotteryUtil(List<Double> list){
            lotteryList = new ArrayList<ContinuousList>();
            if(list.size() == 0){
                throw new IllegalArgumentException("抽奖集合不能为空!");
            }
            double minElement = 0d;
            ContinuousList continuousList = null;
            for(Double d : list){
                minElement = maxElement;
                maxElement = maxElement + d;
                continuousList = new ContinuousList(minElement, maxElement);
                lotteryList.add(continuousList);
            }
        }
    
        /**
         * 进行抽奖操作
         * 返回:奖品的概率list集合中的下标
         */
        public int randomColunmIndex(){
            int index = -1;
            Random r = new Random();
            double d = r.nextDouble() * maxElement;
            //生成0-1间的随机数
            if(d == 0d){
                d = r.nextDouble() * maxElement;
                //防止生成0.0
            }
            int size = lotteryList.size();
            for(int i = 0; i < size; i++){
                ContinuousList cl = lotteryList.get(i);
                if(cl.isContainKey(d)){
                    index = i;
                    break;
                }
            }
            if(index == -1){
                throw new IllegalArgumentException("概率集合设置不合理!");
            }
            return index;
    
        }
    
        public double getMaxElement() {
            return maxElement;
        }
    
        public List<ContinuousList> getLotteryList() {
            return lotteryList;
        }
        public void setLotteryList(List<ContinuousList> lotteryList) {
            this.lotteryList = lotteryList;
        }
    
    }
    
    

    该工具类的基本思想是,将抽奖概率分布到数轴上,如现有三个抽奖概率10、20、30,将三者依次添加到概率集合中,则构造的数轴为:010范围内表示概率10,1030范围内表示概率为20,3060范围内表示概率为30,数轴上的长度对应着相应的概率。由这种处理方式可知,概率总和并不需要等于1。该工具类的成功与否在于Random.nextDouble()能否等概率地生成01之间的任意一个数。
    对该抽奖工具进行测试,测试类如下:

    package com.ruoyi.project.dy.utils;
    
    
    /**
     * @description:
     */
    public class Result {
        private int index;
        private int sumTime;
        private int time;
        private double probability;
        private double realProbability;
    
        public int getIndex() {
            return index;
        }
    
        public void setIndex(int index) {
            this.index = index;
        }
    
        public int getTime() {
            return time;
        }
    
        public void setTime(int time) {
            this.time = time;
        }
    
        public int getSumTime() {
            return sumTime;
        }
    
        public void setSumTime(int sumTime) {
            this.sumTime = sumTime;
        }
    
        public double getProbability() {
            return probability;
        }
    
        public double getRealProbability() {
            return realProbability;
        }
    
        public void setRealProbability(double realProbability) {
            this.realProbability = realProbability;
        }
    
        public Result(){
    
        }
    
        public Result(int index, int sumTime, int time, double realProbability) {
            this.setIndex(index);
            this.setTime(time);
            this.setSumTime(sumTime);
            this.setRealProbability(realProbability);
    
        }
    
        @Override
        public String toString(){
            return "索引值:" + index + ",抽奖总数:" + sumTime + ",抽中次数:" + time + ",概率:"
                    + realProbability + ",实际概率:" + (double)time/sumTime;
        }
    }
    //----------------------------------
    
    package com.ruoyi.project.dy.utils;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * @description: 测试抽奖工具
     */
    public class TestLottery {
        static final int TIME = 1000000;
    
        public static void iteratorMap(Map<Integer, Integer> map, List<Double> list){
            for(Map.Entry<Integer, Integer> entry : map.entrySet()){
                int index = entry.getKey();
                int time  = entry.getValue();
                Result result = new Result(index, TIME, time, list.get(index));
                System.out.println(result);
            }
        }
    
        public static void main(String[] args) {
            //构造概率集合
            List<Double> list = new ArrayList<Double>();
            list.add(90d);
            list.add(4d);
            list.add(3d);
            list.add(2d);
            list.add(1d);
            LotteryUtil ll = new LotteryUtil(list);
            double sumProbability = ll.getMaxElement();
    
            Map<Integer, Integer> map = new HashMap<Integer, Integer>();
            for(int i = 0; i < TIME; i++){
                int index = ll.randomColunmIndex();
                if(map.containsKey(index)){
                    map.put(index, map.get(index) + 1);
                }else{
                    map.put(index, 1);
                }
            }
            for(int i = 0; i < list.size(); i++){
                double probability = list.get(i) / sumProbability;
                list.set(i, probability);
            }
            iteratorMap(map, list);
    
        }
    }
    
    

    调用方式

    public LotteryUtil(List<Double> list)

    传入参数作为概率集合

    public int randomColunmIndex()

    进行抽奖操作,返回List集合中索引下标

    测试结果:

    作者:山丘!

    -------------------------------------------

    你闻讯而来,我大喜过望,我在这等你,你又在哪呢?喜欢的话加一个“关注”呗!

    如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!

  • 相关阅读:
    BZOJ BLO 1123 (割点)【双连通】
    P4291 [HAOI2008]排名系统
    P3165 [CQOI2014]排序机械臂
    P3224 [HNOI2012]永无乡
    P1169 [ZJOI2007]棋盘制作
    P2303 [SDOi2012]Longge的问题
    P2216 [HAOI2007]理想的正方形
    P2473 [SCOI2008]奖励关
    P2617 Dynamic Rankings
    P2518 [HAOI2010]计数
  • 原文地址:https://www.cnblogs.com/mengd/p/15141023.html
Copyright © 2011-2022 走看看