Java实现仿微信红包分配规则

来源:互联网 发布:加加林死亡 知乎 编辑:程序博客网 时间:2024/06/10 17:36



这篇文章主要为大家详细介绍了Java实现仿微信红包分配规则,介绍一种随机红包分配策略,感兴趣的小伙伴们可以参考一下

最近过年发红包拜年成为一种新的潮流,作为程序猿对算法的好奇远远要大于对红包的好奇,这里介绍一种自己想到的一种随机红包分配策略,还请大家多多指教。

算法介绍

一、红包金额限制

      对于微信红包,我们知道没人随机的最小红包是1分,最大金额是200元,这里我们同样来设置红包的范围,下面代码我们统一金钱的单位为分。

//最小红包额度 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; } 

三、随机产生一个红包
      这里我们采用随机的方式产生一个在MINMONEY和MAXMONEY之间的一个红包,产生红包之后,我们需要判断剩余的钱是否是合法红包,如果不是合法红包,我们就重新产生分配方案,在重新产生分配方案的时候,我们需要确定一个事情,是产生的红包过大还是过小,如果红包过大,下次就随机一个小值到本次红包金额的一个红包,如果红包金额过小,我们就产生一个红包金额到大值的一个红包。

private int random(int money, int minS, int maxS, int count) {  //红包数量为1,直接返回金额  if (count == 1) {  return money;  }  //如果最大金额和最小金额相等,直接返回金额  if (minS == maxS) {  return minS;  }  int max = maxS > money ? money : maxS;  //随机产生一个红包  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) {  //递归调用,修改红包最大金额  return random(money, minS, one, count);  }else if (avg > MAXMONEY) {  //递归调用,修改红包最小金额  return random(money, one, maxS, count);  }  }  return one; } 

四、实现红包分配
      这里为了避免某一个红包占用大量资金,我们需要设定非最后一个红包的最大金额,我们把他设置为红包金额平均值的N倍;有了一、二、三中的方法,我们就可以来实现红包的分配了。

//每个红包最大是平均值的倍数 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; } 

红包分配方案评估

      上面介绍了红包的基本算法,下面我们就对算法进行一次验证,假设有一个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;  //每个红包最大是平均值的倍数  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) {  //红包数量为1,直接返回金额  if (count == 1) {  return money;  }  //如果最大金额和最小金额相等,直接返回金额  if (minS == maxS) {  return minS;  }  int max = maxS > money ? money : maxS;  //随机产生一个红包  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) {  //递归调用,修改红包最大金额  return random(money, minS, one, count);  }else if (avg > MAXMONEY) {  //递归调用,修改红包最小金额  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)));  } } 
原创粉丝点击