Java實現(xiàn)微信紅包分配規(guī)則
最近過年發(fā)紅包拜年成為一種新的潮流,作為程序猿對算法的好奇遠遠要大于對紅包的好奇,這里介紹一種自己想到的一種隨機紅包分配策略,還請大家多多指教。
算法介紹
一、紅包金額限制
對于微信紅包,我們知道沒人隨機的最小紅包是1分,最大金額是200元,這里我們同樣來設(shè)置紅包的范圍,下面代碼我們統(tǒng)一金錢的單位為分。
//最小紅包額度 private static final int MINMONEY = 1; //最大紅包額度 private static final int MAXMONEY = 200 * 100;
二、判斷紅包金額是否合法
注意這一步伴隨著整個算法,我們不僅要在分配紅包之前要判斷金額是否合法,同樣要在每個人暫定隨機金額后也要判斷剩余的金額是否合法。
private boolean isRight(int money, int count) { double avg = money / count; if (avg < MINMONEY) { return false; } if (avg > MAXMONEY) { return false; } return true; }
三、隨機產(chǎn)生一個紅包
這里我們采用隨機的方式產(chǎn)生一個在MINMONEY和MAXMONEY之間的一個紅包,產(chǎn)生紅包之后,我們需要判斷剩余的錢是否是合法紅包,如果不是合法紅包,我們就重新產(chǎn)生分配方案,在重新產(chǎn)生分配方案的時候,我們需要確定一個事情,是產(chǎn)生的紅包過大還是過小,如果紅包過大,下次就隨機一個小值到本次紅包金額的一個紅包,如果紅包金額過小,我們就產(chǎn)生一個紅包金額到大值的一個紅包。
private int random(int money, int minS, int maxS, int count) { //紅包數(shù)量為1,直接返回金額 if (count == 1) { return money; } //如果最大金額和最小金額相等,直接返回金額 if (minS == maxS) { return minS; } int max = maxS > money ? money : maxS; //隨機產(chǎn)生一個紅包 int one = ((int)Math.rint(Math.random() * (max - minS) + minS)) % max + 1; int money1 = money - one; //判斷該種分配方案是否正確 if (isRight(money1, count -1)) { return one; } else { double avg = money1 / (count - 1); if (avg < MINMONEY) { //遞歸調(diào)用,修改紅包最大金額 return random(money, minS, one, count); }else if (avg > MAXMONEY) { //遞歸調(diào)用,修改紅包最小金額 return random(money, one, maxS, count); } } return one; }
四、實現(xiàn)紅包分配
這里為了避免某一個紅包占用大量資金,我們需要設(shè)定非最后一個紅包的最大金額,我們把他設(shè)置為紅包金額平均值的N倍;有了一、二、三中的方法,我們就可以來實現(xiàn)紅包的分配了。
//每個紅包最大是平均值的倍數(shù) private static final double TIMES = 2.1; public List<Integer> splitRedPackets(int money, int count) { if (!isRight(money, count)) { return null; } List<Integer> list = new ArrayList<Integer>(); //紅包最大金額為平均金額的TIMES倍 int max = (int) (money * TIMES / count); max = max > MAXMONEY ? MAXMONEY : max; for (int i = 0; i < count; i++) { int one = random(money, MINMONEY, max, count - i); list.add(one); money -= one; } return list; }
紅包分配方案評估
上面介紹了紅包的基本算法,下面我們就對算法進行一次驗證,假設(shè)有一個200元100份的紅包,我們來看一下最后的分配方案。
完整代碼
/** *@Description: */ package com.lulei.weixin.util; import java.util.ArrayList; import java.util.List; import com.lulei.util.JsonUtil; public class RedPacketUtil { //最小紅包額度 private static final int MINMONEY = 1; //最大紅包額度 private static final int MAXMONEY = 200 * 100; //每個紅包最大是平均值的倍數(shù) private static final double TIMES = 2.1; /** * @param money * @param count * @return * @Author:lulei * @Description: 拆分紅包 */ public List<Integer> splitRedPackets(int money, int count) { if (!isRight(money, count)) { return null; } List<Integer> list = new ArrayList<Integer>(); //紅包最大金額為平均金額的TIMES倍 int max = (int) (money * TIMES / count); max = max > MAXMONEY ? MAXMONEY : max; for (int i = 0; i < count; i++) { int one = random(money, MINMONEY, max, count - i); list.add(one); money -= one; } return list; } /** * @param money * @param minS * @param maxS * @param count * @return * @Author:lulei * @Description: 隨機紅包額度 */ private int random(int money, int minS, int maxS, int count) { //紅包數(shù)量為1,直接返回金額 if (count == 1) { return money; } //如果最大金額和最小金額相等,直接返回金額 if (minS == maxS) { return minS; } int max = maxS > money ? money : maxS; //隨機產(chǎn)生一個紅包 int one = ((int)Math.rint(Math.random() * (max - minS) + minS)) % max + 1; int money1 = money - one; //判斷該種分配方案是否正確 if (isRight(money1, count -1)) { return one; } else { double avg = money1 / (count - 1); if (avg < MINMONEY) { //遞歸調(diào)用,修改紅包最大金額 return random(money, minS, one, count); }else if (avg > MAXMONEY) { //遞歸調(diào)用,修改紅包最小金額 return random(money, one, maxS, count); } } return one; } /** * @param money * @param count * @return * @Author:lulei * @Description: 此種紅包是否合法 */ private boolean isRight(int money, int count) { double avg = money / count; if (avg < MINMONEY) { return false; } if (avg > MAXMONEY) { return false; } return true; } public static void main(String[] args) { // TODO Auto-generated method stub RedPacketUtil util = new RedPacketUtil(); System.out.println(JsonUtil.parseJson(util.splitRedPackets(20000, 100))); } }
更多精彩內(nèi)容請點擊《Android微信開發(fā)教程匯總》,《java微信開發(fā)教程匯總》歡迎大家學習閱讀。
以上就是本文的全部內(nèi)容,希望對大家學習java程序設(shè)計有所幫助。
相關(guān)文章
基于Java的Socket多客戶端Client-Server聊天程序的實現(xiàn)
這篇文章主要介紹了基于Java的Socket多客戶端Client-Server聊天程序的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-03-03java 中 System.out.println()和System.out.write()的區(qū)別
這篇文章主要介紹了 java 中 System.out.println()和System.out.write()的區(qū)別.的相關(guān)資料,需要的朋友可以參考下2017-04-04Spring?Boot應用程序中如何使用Keycloak詳解
這篇文章主要為大家介紹了Spring?Boot應用程序中如何使用Keycloak詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05