利用binarySearch实现抽奖计算逻辑
前言
我们平时抽奖总感觉想抽到最高的奖那么难,哈哈当然不会那么容易啦,正巧写了个抽奖的功能,趁着有时间把抽奖的功能实现整理一下,我们要抽奖首先要定义一个奖品的实体类,这个实体类中包含奖品的基本信息,比如奖品名称,奖品数量,抽奖权值,是否是奖品(因为要考虑到谢谢惠顾之类的未中奖情况)等等,根据需求的扩增也可以对每个人抽中奖的次数进行限制(增加抽奖次数属性),在此不做过于复杂的设计,主要说实现的逻辑。定义实体类后我们就去装填奖品信息了(去数据库增加中奖信息...),我们也可以不使用数据库只做一些模拟数据,以上都准备好后就可以开始我们的抽奖逻辑设计了。
抽奖逻辑
我们通过定义奖品信息的权值来作为后续控制中奖几率的关键,权值为整数类型,数值越小被抽中的几率越小,我们把真正的奖品设置的权值小一些,将不中奖的权值设置的大一些,然后我们将权值作为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实现抽奖计算逻辑的更多相关文章
- 利用canvas实现抽奖转盘---转载别人的
功能需求 转盘要美观,转动效果流畅. 转盘上需要显示奖品图片,并且奖品是后台读取的照片和名字. 转动动画完成后要有相应提示. 获取的奖品具体算法在数据库里操作,前端只提供最后的效果展示. 知识要点 ...
- 利用java实现抽奖转盘(着重安全控制)
本文是针对jquery 实现抽奖转盘作者的一个补充(主要用java去实现转盘结果生成及存储,解决jquery 做法 非法用户采用模拟器实现改变转盘值的风险性),针对jQuery的具体实现,请看案例:h ...
- IOS- 快速排序,冒泡排序,直接插入排序和折半插入排序,希尔排序,堆排序,直接选择排序
/*******************************快速排序 start**********************************///随即取 当前取第一个,首先找到第一个的位置 ...
- OC 实现的几个排序算法
和在VC++6.0里相比 在OC里面实现 不算困难 可是我用惯了C/C++呢 快速排序,冒泡排序,直接插入排序和折半插入排序,希尔排序,堆排序,直接选择排序 /******************** ...
- Android SurfaceView实战 带你玩转flabby bird (上)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/42965779 ,本文出自:[张鸿洋的博客] 1.概述 哈,记得以前写过Andro ...
- WEB前端学习资源清单
常用学习资源 JS参考与基础学习系列 [MDN]JS标准参考 es6教程 JS标准参考教程 编程类中文书籍索引 深入理解JS系列 前端开发仓库 <JavaScript 闯关记> JavaS ...
- [转] WEB前端学习资源清单
常用学习资源 JS参考与基础学习系列 [MDN]JS标准参考 es6教程 JS标准参考教程 编程类中文书籍索引 深入理解JS系列 前端开发仓库 <JavaScript 闯关记> JavaS ...
- Python利用带权重随机数解决抽奖和游戏爆装备问题
关于带权随机数 为了帮助理解,先来看三类随机问题的对比: 1.已有n条记录,从中选取m条记录,选取出来的记录前后顺序不管. 实现思路:按行遍历所有记录,约隔n/m条取一个数据即可 2.在1类情况下,还 ...
- C#部分---利用arraylist集合做滚动抽奖;
输入多个手机号码,放到集合中,进行三秒钟的滚动抽奖:随机显示号码,清空,再显示: 1.收集号码: 2.每隔三秒进行抽奖,及作弊代码,哈哈哈: 3.System.Threading.Thread.Sle ...
随机推荐
- java实现第五届蓝桥杯生物芯片
生物芯片 X博士正在研究一种生物芯片,其逻辑密集度.容量都远远高于普通的半导体芯片. 博士在芯片中设计了 n 个微型光源,每个光源操作一次就会改变其状态,即:点亮转为关闭,或关闭转为点亮. 这些光源的 ...
- 6.keras-基于CNN网络的Mnist数据集分类
keras-基于CNN网络的Mnist数据集分类 1.数据的载入和预处理 import numpy as np from keras.datasets import mnist from keras. ...
- 00-02.kaliLinux-配置SSH服务
KaliLinux的SSH服务默认是需要手动配置好后才能使用,否则通过xShell等工具是无法连接上的. 修改SSH服务的配置文件 root@kali:~# cd /etc/ssh root@kali ...
- python2.7 正则表达式的学习
正则表达式是一种用来匹配字符串的强有力的武器.它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的. 因正则表达式也是用字符 ...
- mysql where与 having的区别
where是针对磁盘的数据文件,having是针对存在内存的结果集的筛选. 例如: select name ,(xxx - xxx) as a from table where a > 10; ...
- 关于JSON数据体积优化的一点小心得
最近在做的一个项目里传输的json数据比较大,造成了线程间的卡顿,于是想优化一下json数据的体积. 可以看到在json文件里有很多无用的字段,这些字段占据了大量的存储空间. 对数据的结构作一下优化, ...
- SDL2 gif动态图加载
参照 https://tieba.baidu.com/p/3569073088?tpl=5&red_tag=1777318765 使用mingw工具链 #include <stdbool ...
- List作为泛型参数实现可接收存储任意类型的List对象
原文链接:https://blog.csdn.net/eeeeasy/article/details/80999650?utm_source=blogxgwz2 在项目中遇到一个问题,想要封装一个通用 ...
- 说说硬件中核心板的作用和优缺点,基于i.MX8M Mini核心处理器平台
核心板,顾名思义,即硬件构成中关键的器件和电路打包封装的一块电子主板,具有布线复杂.多层.高频信号干扰.器件密度高等特性,大多数核心板集成了处理器.内存.存储器.电源管理和引脚,通过引脚与配套基板连接 ...
- PytorchMNIST(使用Pytorch进行MNIST字符集识别任务)
都说MNIST相当于机器学习界的Hello World.最近加入实验室,导师给我们安排了一个任务,但是我才刚刚入门呐!!没办法,只能从最基本的学起. Pytorch是一套开源的深度学习张量库.或者我倾 ...