前言

我们平时抽奖总感觉想抽到最高的奖那么难,哈哈当然不会那么容易啦,正巧写了个抽奖的功能,趁着有时间把抽奖的功能实现整理一下,我们要抽奖首先要定义一个奖品的实体类,这个实体类中包含奖品的基本信息,比如奖品名称,奖品数量,抽奖权值,是否是奖品(因为要考虑到谢谢惠顾之类的未中奖情况)等等,根据需求的扩增也可以对每个人抽中奖的次数进行限制(增加抽奖次数属性),在此不做过于复杂的设计,主要说实现的逻辑。定义实体类后我们就去装填奖品信息了(去数据库增加中奖信息...),我们也可以不使用数据库只做一些模拟数据,以上都准备好后就可以开始我们的抽奖逻辑设计了。

抽奖逻辑

我们通过定义奖品信息的权值来作为后续控制中奖几率的关键,权值为整数类型,数值越小被抽中的几率越小,我们把真正的奖品设置的权值小一些,将不中奖的权值设置的大一些,然后我们将权值作为map数组的value放入map数组中,key为奖品的具体对象信息(一个奖品的对象信息对应着它的权值)。我们根据它们的权值来新建一个专门用来抽奖的数组,这个数组必须满足1.是有序的2.与奖品数组的下标一一对应。最简单粗暴的方式就是让所有的权值递加变成一个递增的新数组。生成这个数组后我们就可以利用binarySearch函数实现根据随机数来拿取具体的奖品对象了,实现了由奖品权值来定义抽奖的中奖率。

逻辑功能实现

下面用一段逻辑代码来描述中奖奖品产生的关键过程。在这里补充一下binarySearch函数的运用,binarySearch(Object[], Object key)函数中第一个参数是要搜索的数组,参数key为要搜索的值

情况 结果
值不是数组元素,且在数组范围内 得到-(插入点索引值《后面讲到》+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函数在随机搜索值中找到一个搜索数组的一个下标,根据该小标定位到具体的奖品信息。

利用binarySearch实现抽奖计算逻辑的更多相关文章

  1. 利用canvas实现抽奖转盘---转载别人的

    功能需求 转盘要美观,转动效果流畅. 转盘上需要显示奖品图片,并且奖品是后台读取的照片和名字. 转动动画完成后要有相应提示. 获取的奖品具体算法在数据库里操作,前端只提供最后的效果展示.   知识要点 ...

  2. 利用java实现抽奖转盘(着重安全控制)

    本文是针对jquery 实现抽奖转盘作者的一个补充(主要用java去实现转盘结果生成及存储,解决jquery 做法 非法用户采用模拟器实现改变转盘值的风险性),针对jQuery的具体实现,请看案例:h ...

  3. IOS- 快速排序,冒泡排序,直接插入排序和折半插入排序,希尔排序,堆排序,直接选择排序

    /*******************************快速排序 start**********************************///随即取 当前取第一个,首先找到第一个的位置 ...

  4. OC 实现的几个排序算法

    和在VC++6.0里相比 在OC里面实现 不算困难 可是我用惯了C/C++呢 快速排序,冒泡排序,直接插入排序和折半插入排序,希尔排序,堆排序,直接选择排序 /******************** ...

  5. Android SurfaceView实战 带你玩转flabby bird (上)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/42965779 ,本文出自:[张鸿洋的博客] 1.概述 哈,记得以前写过Andro ...

  6. WEB前端学习资源清单

    常用学习资源 JS参考与基础学习系列 [MDN]JS标准参考 es6教程 JS标准参考教程 编程类中文书籍索引 深入理解JS系列 前端开发仓库 <JavaScript 闯关记> JavaS ...

  7. [转] WEB前端学习资源清单

    常用学习资源 JS参考与基础学习系列 [MDN]JS标准参考 es6教程 JS标准参考教程 编程类中文书籍索引 深入理解JS系列 前端开发仓库 <JavaScript 闯关记> JavaS ...

  8. Python利用带权重随机数解决抽奖和游戏爆装备问题

    关于带权随机数 为了帮助理解,先来看三类随机问题的对比: 1.已有n条记录,从中选取m条记录,选取出来的记录前后顺序不管. 实现思路:按行遍历所有记录,约隔n/m条取一个数据即可 2.在1类情况下,还 ...

  9. C#部分---利用arraylist集合做滚动抽奖;

    输入多个手机号码,放到集合中,进行三秒钟的滚动抽奖:随机显示号码,清空,再显示: 1.收集号码: 2.每隔三秒进行抽奖,及作弊代码,哈哈哈: 3.System.Threading.Thread.Sle ...

随机推荐

  1. 第四届蓝桥杯JavaC组省赛真题

    解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1.猜年龄 题目描述 美国数学家维纳(N.Wiener)智力早熟,11岁就上了大学.他曾在1935~1936年应邀来中国清华大学讲学. 一 ...

  2. 自己动手写SQL执行引擎

    自己动手写SQL执行引擎 前言 在阅读了大量关于数据库的资料后,笔者情不自禁产生了一个造数据库轮子的想法.来验证一下自己对于数据库底层原理的掌握是否牢靠.在笔者的github中给这个database起 ...

  3. 用户管理命令-passwd

    passwd可以给用户设置密码或者修改密码,超级用户可以修改任何用户的密码,而且可以不遵守密码的复杂性原则,普通用户只能修改自己的密码,必须遵守密码的复杂性原则 passwd [选项] 用户名 常用选 ...

  4. 一个Jmeter模拟上传文件接口的实例

    资料参考:https://blog.csdn.net/u010390063/article/details/78329373 项目中,避免不了要用到很多上传文件.图片的接口,那么碰到这类接口该如何进行 ...

  5. 天哪!手动编写mybatis雏形竟然这么简单

    前言 mybaits 在ORM 框架中,可算是半壁江山了,由于它是轻量级,半自动加载,灵活性和易拓展性.深受广大公司的喜爱,所以我们程序开发也离不开mybatis .但是我们有对mabtis 源码进行 ...

  6. Java创建ES索引实现

    1.pom.xml文件 <dependency> <groupId>org.springframework.boot</groupId> <artifactI ...

  7. @loj - 3120@ 「CTS2019 | CTSC2019」珍珠

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 有 \(n\) 个在范围 \([1, D]\) 内的整数均匀随机 ...

  8. Nginx 的变量究竟是怎么一回事?

    之前说了很多关于 Nginx 模块的内容,还有一部分非常重要的内容,那就是 Nginx 的变量.变量在 Nginx 中可以说无处不在,认识了解这些变量的作用和原理同样是必要的,下面几乎囊括了关于 Ng ...

  9. INSERT INTO语句的基本用法

    原文链接:https://www.cnblogs.com/mingmingming/p/11295200.html 一.INSERT INTO语句的基本用法 INSERT INTO 语句用于往表中插入 ...

  10. GetLastError返回值含义

    GetLastError的返回值的含义: (0)-操作成功完成. (1)-功能错误. (2)- 系统找不到指定的文件. (3)-系统找不到指定的路径. (4)-系统无法打开文件. (5)-拒绝访问. ...