java抽奖详细介绍

前言:应项目中有需求做一个抽奖活动,所以我去看了很多篇文章,取了其中一篇文章,做了修改.达到了我的需求,

思路:

1.先计算权重,然后得到区域,

2.随机一个随机数,判断在哪个区域,就得到相应的奖品

这里写图片描述

  分析:如上图,为了便于计算和理解,可以设置每种奖品的权重分别为1,2,3,4,所以被抽到的概率分别为0.1,0.2,0.3,0.4(本次活动中奖概率为100%)。

  先生成一个随机数randomNumber,然后根据随机数所处区域判断奖品:

0 <=randomNumber <0.1 表示抽中一等奖
0.1<=randomNumber<0.3 表示抽中二等奖
0.3<=randomNumber<0.6 表示抽中三等奖
0.6<=randomNumber<1.0 表示抽中四等奖

抽奖实现


  奖品实体 Prize.java

    public class Prize {    
    private int id;//奖品id
    private String prize_name;//奖品名称
    private int prize_amount;//奖品(剩余)数量
    private int prize_weight;//奖品权重
    //getter、setter
}


  这里只考虑最简单的抽奖实现,所以暂时只为奖品设计如上4个字段。

  见注释,prize_name表示奖品名称;prize_amount表示奖品数量,即本次抽奖活动计划发放此奖品的数量;prize_weight表示奖品权重,表示奖品被抽到的几率的比重,权重越大,被抽到的几率越大,比如本次砸金蛋活动有4种奖品,权重分别是1、2、3、4、90,总权重是100,那么每种奖品被抽到的几率就是1/100,2/100,3/100,4/100 , 90/100。

  核心算法:

/**
     * 根据Math.random()产生一个double型的随机数,判断每个奖品出现的概率
     * @param prizes  奖品实体集合
     * @return random:奖品列表prizes中的序列(prizes中的第random个就是抽中的奖品)
     */
    public int getPrizeIndex(List<Prize> prizes) {
        int random = -1;
        try{
            //计算总权重
            double sumWeight = 0;
            for(Prize p : prizes){
                sumWeight += p.getPrize_weight();
            }

            //产生随机数
            double randomNumber;
            randomNumber = Math.random();

            //根据随机数在所有奖品分布的区域并确定所抽奖品
            double d1 = 0;
            double d2 = 0;          
            for(int i=0;i<prizes.size();i++){
                d2 += Double.parseDouble(String.valueOf(prizes.get(i).getPrize_weight()))/sumWeight;
                if(i==0){
                    d1 = 0;
                }else{
                    d1 +=Double.parseDouble(String.valueOf(prizes.get(i-1).getPrize_weight()))/sumWeight;
                }
                if(randomNumber >= d1 && randomNumber <= d2){
                    random = i;
                    break;
                }
            }
        }catch(Exception e){
            System.out.println("生成抽奖随机数出错,出错原因:" +e.getMessage());
        }
        return random;
    }

抽奖测试:

	public static void main(String[] agrs) {
        int i = 0;
        int[] result=new int[5];
        List<Prize> prizes = new ArrayList<Prize>();

        Prize p1 = new Prize();
        p1.setPrize_name("范冰冰海报");
        p1.setPrize_weight(1);//奖品的权重设置成1
        p1.setPrize_amount(1);
        prizes.add(p1);

        Prize p2 = new Prize();
        p2.setPrize_name("上海紫园1号别墅");
        p2.setPrize_weight(2);//奖品的权重设置成2
        p2.setPrize_amount(1);
        prizes.add(p2);

        Prize p3 = new Prize();
        p3.setPrize_name("奥迪a9");
        p3.setPrize_weight(3);//奖品的权重设置成3
        p3.setPrize_amount(1);
        prizes.add(p3);

        Prize p4 = new Prize();
        p4.setPrize_name("双色球彩票");
        p4.setPrize_weight(4);//奖品的权重设置成4
        p4.setPrize_amount(1);
        prizes.add(p4);
        
        Prize p5 = new Prize();
        p5.setPrize_name("谢谢参与");
        p5.setPrize_weight(90);//奖品的权重设置成90
        p5.setPrize_amount(10000);
        prizes.add(p5);

        System.out.println("抽奖开始");
        for (i = 0; i < 10000; i++)// 打印10000个测试概率的准确性
        {
            //标记,用来结束死循环
            boolean flag=true;
            //奖品索引
            int selected = 0;
        	while(flag){
        		//抽奖
        		selected=getPrizeIndex(prizes);
                if (prizes.get(selected).getPrize_amount()>0) {
                	flag=false;
                }else{
                	System.out.println(prizes.get(selected).getPrize_name()+"的数量为"+prizes.get(selected).getPrize_amount()+",所以重新抽奖!!");
                }
                	
        	}

            //抽到奖品后,奖品-1
            prizes.get(selected).setPrize_amount( prizes.get(selected).getPrize_amount()-1);
            
            System.out.println("奖品索引: "+selected);
            System.out.println("第"+i+"次抽中的奖品为:"+prizes.get(selected).getPrize_name());
            System.out.println(prizes.get(selected).getPrize_name()+"奖品剩余数量:"+prizes.get(selected).getPrize_amount());
            result[selected]++;
            System.out.println("--------------------------------");

        }
        System.out.println("抽奖结束");
        System.out.println("每种奖品抽到的数量为:");
        System.out.println("一等奖:"+result[0]);
        System.out.println("二等奖:"+result[1]);
        System.out.println("三等奖:"+result[2]);
        System.out.println("四等奖:"+result[3]);       
        System.out.println("五等奖:"+result[4]);       
    }

 尝试抽奖10000次的结果如下: 

一等奖:1
二等奖:1
三等奖:1
四等奖:1
五等奖:9996

因为我这里设置前面几个奖项只有1个,所以导致这里最多只能抽中一次,

其实每类奖品获奖次数比例刚好大约为1:2:3:4 : 90,学过概率的你肯定知道抽奖次数越多,

测试结果越准确~~,


【 转载请注明出处——胡玉洋 《【项目实战】——Java中根据奖品权重实现抽奖(砸金蛋、大转盘等)》






猜你喜欢

转载自blog.csdn.net/baidu_38990811/article/details/78902445