咱们平时抽奖总感受想抽到最高的奖那么难,哈哈固然不会那么容易啦,正巧写了个抽奖的功能,趁着有时间把抽奖的功能实现整理一下,咱们要抽奖首先要定义一个奖品的实体类,这个实体类中包含奖品的基本信息,好比奖品名称,奖品数量,抽奖权值,是不是奖品(由于要考虑到谢谢惠顾之类的未中奖状况)等等,根据需求的扩增也能够对每一个人抽中奖的次数进行限制(增长抽奖次数属性),在此不作过于复杂的设计,主要说实现的逻辑。定义实体类后咱们就去装填奖品信息了(去数据库增长中奖信息...),咱们也能够不使用数据库只作一些模拟数据,以上都准备好后就能够开始咱们的抽奖逻辑设计了。数据库
咱们经过定义奖品信息的权值来做为后续控制中奖概率的关键,权值为整数类型,数值越小被抽中的概率越小,咱们把真正的奖品设置的权值小一些,将不中奖的权值设置的大一些,而后咱们将权值做为map数组的value放入map数组中,key为奖品的具体对象信息(一个奖品的对象信息对应着它的权值)。咱们根据它们的权值来新建一个专门用来抽奖的数组,这个数组必须知足1.是有序的2.与奖品数组的下标一一对应。最简单粗暴的方式就是让全部的权值递加变成一个递增的新数组。生成这个数组后咱们就能够利用binarySearch函数实现根据随机数来拿取具体的奖品对象了,实现了由奖品权值来定义抽奖的中奖率。数组
下面用一段逻辑代码来描述中奖奖品产生的关键过程。在这里补充一下binarySearch函数的运用,binarySearch(Object[], Object key)函数中第一个参数是要搜索的数组,参数key为要搜索的值dom
状况 | 结果 |
---|---|
值不是数组元素,且在数组范围内 | 获得-(插入点索引值《后面讲到》+1) |
值是数组元素 | 获得搜索的索引值 |
值不是数组元素,且大于数组内元素 | -(length+1) |
值不是数组元素,且小于数组内元素 | -1 |
插入的索引值其实就是将当前的搜索值放入搜索数值后,获得的这个值的下一位值的索引值,打个比方,搜索数组为:【12,13,20,90】搜索值为【60】那么将搜索值放入搜索数组后获得【12,13,20,60,90】那么这时的90的索引值4即为插入点索引值,试想当搜索值不在该数组范围内且小于数组范围时,此时的插入点应该是数组的第一个值,该插入点的索引值也就是1,反之大于数组范围时插入点的索引值为(length+1)。函数
public class GetIndex { private int weightAdder ; //权值加法器基数 private int index ; //权值加法器填充时下标 private int dex; //中奖值下标 private int max; //最大权值 private int random; private Random ran; private ArrayList<String> record = new ArrayList<String>(); private int[] weights; //权值加法器数组 public static DecimalFormat df = new DecimalFormat("0.00"); //格式化数值 public static int[] map = new int[] {10,8450,1000,500,40}; //中奖权值 选中率分别为1/1000,845/1000,1/10,5/100,4/1000 public static int looptime = 100;//抽奖次数 public static void main(String[] args) { GetIndex getindex = new GetIndex(); for (int j = 0;j<looptime;j++) { getindex.index = 0; getindex.weightAdder = 0; getindex.ran = new Random(); getindex.weights = new int[map.length]; //生成权限加法器数组,保证新生成数据值有序递增 for(int w : map ) { getindex.weights[getindex.index++] = (getindex.weightAdder = getindex.weightAdder + w); } /* * for(int w : weights) { System.out.println("数组:"+w); } */ getindex.max = getindex.weights[getindex.weights.length-1]; //获取权限加法器数组最大值 getindex.random = getindex.ran.nextInt(getindex.max)+1; //生成随机数 getindex.dex = Arrays.binarySearch(getindex.weights, getindex.random);//重要:获取该数组的一个下标即为中奖值 System.out.println("随机数:"+getindex.random); System.out.println("Dex: "+getindex.dex); //计算dex时数组被加1,因此在此减一 if(getindex.dex < 0) { getindex.dex = -1 - getindex.dex; } System.out.println("Result: "+getindex.dex+" 加法器数组数据:"+getindex.weights[getindex.dex]+" 选中号:"+map[getindex.dex]); if(getindex.dex == 4 || getindex.dex == 0 || getindex.dex == 3) { //假设第一位与第五位中奖 getindex.record.add("中奖号:"+map[getindex.dex]); } } for(String rec: getindex.record) { System.out.println(rec ); } String odds = df.format((float)getindex.record.size()/map.length); System.out.println("中奖率: "+ odds ); } } 以上是抽奖过程当中的主要逻辑,其核心就是利用binarySearch函数在随机搜索值中找到一个搜索数组的一个下标,根据该下标定位到具体的奖品信息。
贴上逻辑运算结果 :
oop