java抽奖详细介绍
来源:互联网 发布:腾讯代理吃鸡后优化 编辑:程序博客网 时间:2024/06/06 00:21
前言:应项目中有需求做一个抽奖活动,所以我去看了很多篇文章,取了其中一篇文章,做了修改.达到了我的需求,
思路:
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,学过概率的你肯定知道抽奖次数越多,
测试结果越准确~~,
阅读全文