教你程式碼實現搶紅包功能
阿新 • • 發佈:2018-12-22
一.場景帶入
搶紅包在現實場景中經常見到,你知道如何通過程式碼來實現嗎?
一種通常的思路是,一定金額的紅包,只要有人過來搶,就在剩餘數額內給他分配金額,直到所有錢都分陪完。
但是這樣有一個問題,最先搶的人,搶到錢多的概率會更大。
比如有10塊錢,有甲乙丙三個人按順序搶,
甲開始搶,這時他搶紅包的數額範圍是0到10,平均是5雲,假設甲搶了4元。
乙開始搶,這時他搶紅包的數額範圍是0到6元,平均是3元,假設乙搶了4元。
丙開始搶,他搶紅包的數額範圍是0到2元,平均是1,剩餘錢歸丙,2元。
看吧,這樣誰先搶,誰佔的便宜就更大。
問:有沒有一種好的方法可以忽略搶紅包的順序呢?
答:剩餘平均法
將剩餘的錢除以剩餘的紅包數,然後再乘以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,期待你有一個更好的方案!