利用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实现Prim算法
1 问题描述 何为Prim算法? 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex ...
- Java实现 蓝桥杯 历届试题 最大子阵
问题描述 给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大. 其中,A的子矩阵指在A中行和列均连续的一块. 输入格式 输入的第一行包含两个整数n, m,分别表示矩阵A的行数和 ...
- Java实现第九届蓝桥杯等腰三角形
等腰三角形 题目描述 本题目要求你在控制台输出一个由数字组成的等腰三角形. 具体的步骤是: 1. 先用1,2,3,...的自然数拼一个足够长的串 2. 用这个串填充三角形的三条边.从上方顶点开始,逆时 ...
- java实现第六届蓝桥杯熊怪吃核桃
熊怪吃核桃 题目描述 森林里有一只熊怪,很爱吃核桃.不过它有个习惯,每次都把找到的核桃分成相等的两份,吃掉一份,留一份.如果不能等分,熊怪就会扔掉一个核桃再分.第二天再继续这个过程,直到最后剩一个核桃 ...
- 「MoreThanJava」机器指令到汇编再到高级编程语言
「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...
- cocos2dx 实现遮罩
参考博文:http://blog.csdn.net/myarrow/article/details/19913653 参考博文:http://blog.csdn.net/song_hui_xiang/ ...
- HDU - 2546 饭卡 题解
题目大意 电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额.如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够) ...
- [原创][开源] SunnyUI.Net 国际化
SunnyUI.Net, 基于 C# .Net WinForm 开源控件库.工具类库.扩展类库.多页面开发框架 Blog: https://www.cnblogs.com/yhuse Gitee: h ...
- java第三阶段作业总结
Java第三阶段总结 前言 到这里,Java课程学习进入了尾声,在这学习过程中,我学习到很多,也发现了自己的很多不足,这篇博客主要针对的是Java整门课程学习的总结. 课程收获 对整门课程的学习,我有 ...
- 在CentOS7上源码安装OpenResty
您必须将这些库perl 5.6.1+libreadlinelibpcrelibssl安装在您的电脑之中. 对于 Linux来说, 您需要确认使用 ldconfig 命令,让其在您的系统环境路径中能找到 ...