Java微信手气红包实现
Java微信手气红包实现
前言
昨天坐公交车,微信群里在发红包,突然想到在思考一个问题:微信的手气红包的算法是如何实现的
闲的没事开始尝试起来了
初次尝试
一开始的想法很简单,就是固定一个奖金池,因为要保证每个最低是有一分钱,所以把随机数的总金额减去剩下每人的0.01作为最高可以获取的红包金额,接着把奖金池减去刚生成的金额,当到最后一人时,直接去把剩余的金额全部给他
具体代码如下(金额的单位为分):
public static List<Integer> redPackRand(Integer money,Integer peopleCount){List<Integer> result=new ArrayList<Integer>();for(int i=0;i<peopleCount;i++){if(i==peopleCount-1){//判断是不是最后一个人,是的话直接把所有金额全部给他
// System.out.println("第"+(i+1)+"人,获得:"+money);result.add(money);}else {//取得随机的金额Integer getMoney =(int)((money-(peopleCount-i-1))*Math.random()+1);
// System.out.println("第"+(i+1)+"人,获得:"+getMoney);//奖金池中减去取走的部分money-=getMoney;
// System.out.println("当前剩余:"+money);result.add(getMoney);}}return result;}
测试
为了测试出红包算法的情况,我写了一个测试工具,可以循环测试N次,每次M个人,查看第1-M个人可以抢到多少钱的平均数
//分别保存进来顺序信息的创建对象
static class PackeAvg{//保存所有金额数据List<Integer> list;public PackeAvg(){list=new ArrayList<>();}//为给列表添加金额public void addList(Integer a){list.add(a);}public List<Integer> getList() {return list;}//算出平均值public Integer getAvg() {if(list.size()!=0){int sum=0;for (int num:list){sum+=num;}return sum / list.size();}return 0;}}public static void redPackRandAvg(int forCount){//用于保存次序信息的List<PackeAvg> avglist=new ArrayList<>();//循环次数forCountfor(int i =0;i<forCount;i++){//300块钱10个人抢,单位是分List<Integer> list = redPackRand(30000, 10);//标记是第几个人int j=0;for (int num:list){if(avglist.size()<j+1)avglist.add(new PackeAvg());PackeAvg packeAvg = avglist.get(j);packeAvg.addList(num);j++;}}int i=1;for (PackeAvg avg:avglist){System.out.println("第"+i+"个人的平均红包为:"+avg.getAvg()+",具体为"+new Gson().toJson(avg));i++;}}
public static void main(String[] arg){//调用20000次,看看评价情况redPackRandAvg(20000);}
结果为:
发现使用这种算法,第一次进来的人都是拿的红包大概率都是最大的,而最后抢到的大概率是最小的,而且从平均数可以看到第一个可以拿走奖金池中一半的红包,就算是按照此方法先分出红包存入数组,再让别人随机顺序领也不行,因为微信上没有出现过多人红包可以取走一半的情况(分的少不算啊)
第二次尝试
痛定思痛,因为第一次尝试发现自己想的过于简单了,当抢红包需要规定抢到的红包最大范围,我看到网上有一种是平均数x2的方法,就是100块10个人抢,第一个人可以抢到的是0.01~20块钱之间,而当红包剩下40人数还剩5人的话,下一个人可以拿到的是2*(40/5),就是0.01~16块钱,这样就可以保证红包不会一下子都被拿走,也能控制红包金额大小
为了方便,我这次专门写了一个类
public class RedPackeg {//为总金额private Integer money;//剩余金额private Integer nowMoney;//红包分了多少份private Integer packSize;//取走了多少份private Integer packNum;//保存金额信息private List<Integer> moneyList=new ArrayList<>();public List<Integer> getMoneyList() {return moneyList;}//构造函数,初始化金额和红包份数public RedPackeg(Integer money,Integer packSize){this.money=money;this.nowMoney=money;this.packSize=packSize;this.packNum=0;}//取红包,当取完之后返回-1public Integer getRedPack(){if(packSize>packNum){Integer getMoney=(int)(((nowMoney/(packSize-packNum))*2)*Math.random()+1);//如果getMoney取走后,剩下的钱不够每人0.01的,就把除去没人0.01外的钱都给他if((nowMoney-getMoney)<(packSize-packNum))getMoney = nowMoney-(packSize+packNum);packNum++;nowMoney-=getMoney;//如果是最后一个人就把金额全部给他if(packSize==packNum)getMoney+=nowMoney;moneyList.add(getMoney);return getMoney;}return -1;}//测试单次抢红包,能不能保证把红包金额全部发完//第一次忘记考虑最后一人情况,金额并没有全发完public static void main(String[] pp){RedPackeg packeg=new RedPackeg(10000,10);for (int i=0;i<10;i++){System.out.println("第"+(i+1)+"个人,获得了"+packeg.getRedPack());}List<Integer> list = packeg.getMoneyList();int sum=0;for(int a:list){sum+=a;}System.out.println("红包总数:"+sum);}
}
测试结果,感觉好像达到了自己想要的效果,赶紧循环个几次试试看,看看次序的平均红包金额吧
准备多套了一个方法,为了可以偷懒复用之前的代码
public static List<Integer> redPackGet(Integer money,Integer peopleCount){RedPackeg packeg=new RedPackeg(money,peopleCount);//从里面取10次钱,记录都会保存在list中for (int i=0;i<peopleCount;i++)packeg.getRedPack();return packeg.getMoneyList();}
public static void redPackAvg(int forCount){List<PackeAvg> avglist=new ArrayList<>();for(int i =0;i<forCount;i++){//只是改变了这里的一个方法List<Integer> list = redPackGet(30000, 10);int j=0;for (int num:list){if(avglist.size()<j+1)avglist.add(new PackeAvg());PackeAvg packeAvg = avglist.get(j);packeAvg.addList(num);j++;}}int i=1;for (PackeAvg avg:avglist){System.out.println("第"+i+"个人的平均红包为:"+avg.getAvg()+",具体为"+new Gson().toJson(avg));i++;}}public static void main(String[] arg){redPackAvg(20000);}
结果:
循环了20000次,结果非常的喜人,基本上可以保证不管是第几个抢红包平均的金额都是差不多的
当循环次数到400000次的时候,金额几乎相差无几
小结
通过上面的代码,已经实现了微信抢红包的基本逻辑,但是真实项目中还有各种问题,就比如高并发就需要对剩余金额加锁之类的,这里只是写出了一个基础部分代码
Java微信手气红包实现相关推荐
- 微信手气红包算法 php,PHP实现微信/QQ手气红包,随机算法分享
最近有个客户找我实现扫码抢手气红包,大家平时都在使用微信/QQ收发红包,玩的不亦乐乎.大家在抢红包,而程序员在研究红包算法.那么手气红包的随机分配算法是怎么实现的呢?怎么保证每个人都领得到,而且满足正 ...
- JAVA 拼手气红包 领取算法 记录
废话不多说,直接上代码 //平分红包public static final Integer normalPacket = 1;//拼手气红包public static final Integer lu ...
- 微信手气红包算法 php,微信随机生成红包金额算法php版
最近在研究发红包的功能,于是写了个红包的生成算法. 红包生成算法的需求预先生成所有的红包还是一个请求随机生成一个红包 简单来说,就是把一个大整数m分解(直接以"分为单位,如1元即100)分解 ...
- python 微信手气红包
import random total = 10 n = 5 result = [] for i in range(1,n):hb = round(random.uniform(0.01, total ...
- java微信红包_Java模拟微信发红包(普通红包、拼手气红包)
假设红包总额M元,分给N个人. 满足条件: 如果是普通红包,每个人获得的金额都一样: 如果是拼手气红包,则有所区别,但不能金额过于离谱,比如第一个获得的太多,以至于后来的人都几乎没得分. 注意点: 1 ...
- java 微信抽奖_微信随机生成红包金额算法java版
最近几年玩得最疯狂的应该是发红包了,尤其是过年的时候特别受欢迎,下面写了红包的随机算法,其实挺简单的,仅是提供一种思路,希望可以给大家一些启发. public class WxAlgorithm{ / ...
- h5拼手气红包java_Java模拟微信发红包(普通红包、拼手气红包)
假设红包总额M元,分给N个人. 满足条件: 如果是普通红包,每个人获得的金额都一样: 如果是拼手气红包,则有所区别,但不能金额过于离谱,比如第一个获得的太多,以至于后来的人都几乎没得分. 注意点: 1 ...
- 微信拼手气红包算法(二倍平均值法)实现示范代码
二倍平均值法 优势在于不需要先把每个人得多少算出来,只有拆红包的时候才会算出这个人得多少,减少实时算力 同时保证了每个人拼手气得到的平均值相同 设有10个人,红包总额100元. 100/10X2 = ...
- 模拟微信拼手气红包程序
模拟微信拼手气红包程序 有用户输入总金额与红包数,随机给每个红包分配金额 package p03.t010;import java.util.Random; import java.util.Scan ...
最新文章
- 在linux和windows下自动备份数据库
- 如何修改Admin用户名
- 基于Conditional Layer Normalization的条件文本生成
- Oracle 11g Java驱动包ojdbc6.jar安装到maven库,并查看jar具体版本号
- php搜索所有路线,php包含文件路径查找规则
- sim卡没坏但苹果手机无服务_iPhone手机无服务那些事儿
- 如何查看Oracle数据库字符集 尚未研究
- win10配置清华源——快速安装anaconda、TensorFlow和pytorch
- 免焊vga3加6接线图_高清 VGA免焊接头3+6+9 VGA快速接头 免焊公头 3排15针 15针插头...
- 软件测试技术(思维导图)
- authentication failed : unrecognized kernel32 module. / NM
- Java最佳学习途径
- c++链表——银行账户管理系统
- mathorcup历年优秀论文阿里云盘
- 二进制转八进制公式计算机,2进制转8进制(二进制转8进制公式)
- 【点云系列】综述: Deep Learning for 3D Point Clouds: A Survey
- 华为v2服务器系统安装系统,华为服务器RH 2288H v2安装系统
- 恐怖呀,恐怖....
- 猿创征文|我的Go成长之路道阻且长
- Javascript特效之可翻阅上一条下一条的动态文字