1. 程式人生 > >教你程式碼實現搶紅包功能

教你程式碼實現搶紅包功能

一.場景帶入

搶紅包在現實場景中經常見到,你知道如何通過程式碼來實現嗎?

一種通常的思路是,一定金額的紅包,只要有人過來搶,就在剩餘數額內給他分配金額,直到所有錢都分陪完。

但是這樣有一個問題,最先搶的人,搶到錢多的概率會更大。

比如有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,期待你有一個更好的方案!