java|教你代码实现抢红包功能

一.场景带入 抢红包在现实场景中经常见到,你知道如何通过代码来实现吗?
一种通常的思路是,一定金额的红包,只要有人过来抢,就在剩余数额内给他分配金额,直到所有钱都分陪完。
但是这样有一个问题,最先抢的人,抢到钱多的概率会更大。
比如有10块钱,有甲乙丙三个人按顺序抢,
甲开始抢,这时他抢红包的数额范围是0到10,平均是5云,假设甲抢了4元。
乙开始抢,这时他抢红包的数额范围是0到6元,平均是3元,假设乙抢了4元。
丙开始抢,他抢红包的数额范围是0到2元,平均是1,剩余钱归丙,2元。
看吧,这样谁先抢,谁占的便宜就更大。
问:有没有一种好的方法可以忽略抢红包的顺序呢?
【java|教你代码实现抢红包功能】答:剩余平均法
将剩余的钱除以剩余的红包数,然后再乘以2这个范围内取随机数就可以了。比如有100块钱,10个人抢,
第一个人抢的范围是100/10*2 =20,也就是[0,20],取平均是10,假设抢到了10元
第二个人抢的范围是90/9*2 =20,也就是[0,20],取平均是10,假设抢到了10元
第三个人抢的范围是80/8*2 =20,也就是[0,20],取平均是10
。。。。。。
他们抢的红包钱的概率是一样大的,这样可以姑且认为抢红包对他们来说都是公平的,没有先后顺序之分!
二.代码实现 上面原理懂了,代码实现起来就简单了,这里设置Player就是一个个抢红包的人,它是一个线程,谁先抢到完全由机器来定。

public class HongBao {//红包类(HongBao)来实现红包的金额生成和返回剩余金额。 private AtomicInteger total = new AtomicInteger(0); private AtomicInteger count = new AtomicInteger(); private static Random random = new Random(); public void setTotal(int total, int person) { this.total.set(total); this.count.set(person); }public int getPrice() { int countDown = count.get(); if (countDown == 1) {//如果红包还剩最后一个了,剩余的钱都给最后一个玩家 return getRemainPrice(); } int rand = (total.get() / count.get()) * 2; int price = random.nextInt(rand - 1) + 1; //取值是[1,2的平均值) total.set (total.get() - price); count.decrementAndGet(); //抢走了一个,个数要减一 return price; //返回本次抢的钱 }public int getRemainPrice() { return total.get(); } }

public class Player implements Runnable {//玩家(Player)是一个线程,主要是调用了获取红包的方法 private HongBao hongBao; private String name; Player(HongBao hongBao, String name) { this.hongBao = hongBao; this.name = name; }@Override public void run() { int price = hongBao.getPrice(); //开始抢红包 System.out.println("线程[" + name + "]" + "获得<" + price + ">"); } }

public class Game {//游戏类(Game)负责红包的初始化和设置n个抢红包的玩家 public static void main(String[] args) throws InterruptedException { start(); } public static void start() { HongBao hongBao = new HongBao(); int total = 100; int count = 5; initHongBao(hongBao, total, count); //初始化红包 for (int i = 0; i < count; i++) { Player play = new Player(hongBao, String.valueOf(i)); new Thread(play).start(); } }/** * 初始化红包 * @param hongBao红包类 * @param total 金额 * @param count 总共多少个 */ private static void initHongBao(HongBao hongBao, int total, int count) { hongBao.setTotal(total, count); } }

三.总结 到此,红包算法的设计就已经完毕了。设计红包算法,需要考虑到每个玩家至少在抢的时候获取钱的几率是一样的,当然实际情况并不是每个人都抢的一样。就这个算法,我的电脑统计的qps是1000,期待你有一个更好的方案!


    推荐阅读