Java实现微信红包分配规则

作者:xiaojimanman 时间:2021-06-16 09:18:07 

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

算法介绍

一、红包金额限制

对于微信红包,我们知道没人随机的最小红包是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份的红包,我们来看一下最后的分配方案。

Java实现微信红包分配规则

完整代码


/**
*@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)));
}
}

更多精彩内容请点击《Android微信开发教程汇总》,《java微信开发教程汇总》欢迎大家学习阅读。

标签:java,微信,红包
0
投稿

猜你喜欢

  • 浅谈JAVA设计模式之享元模式

    2021-09-22 10:12:06
  • Java Synchronized锁的使用详解

    2022-10-11 12:59:33
  • java反射遍历实体类属性和类型,并赋值和获取值的简单方法

    2023-07-15 04:37:18
  • Java动态 代理的应用详解

    2023-11-25 08:15:24
  • SpringBoot+Vue项目新手快速入门指南

    2023-05-20 04:56:07
  • java生成jar包并且单进程运行的实例

    2021-08-30 00:40:55
  • 在Java中避免NullPointerException的解决方案

    2023-10-17 04:47:00
  • java poi导入纯数字等格式问题及解决

    2023-04-14 08:50:30
  • SpringBoot项目多数据源及mybatis 驼峰失效的问题解决方法

    2023-07-25 07:09:08
  • 深入解析java中的locale

    2023-11-09 18:14:20
  • java中Date类和Strng类的灵活转化

    2022-12-09 07:47:24
  • Android如何判断一个点在不在多边形区域内

    2023-07-06 14:06:13
  • SpringIOC BeanDefinition的加载流程详解

    2023-11-25 18:06:22
  • spring boot 实现配置多个DispatcherServlet最简单方式

    2023-12-18 03:24:46
  • Java常用类String的面试题汇总(java面试题)

    2023-11-23 20:40:45
  • Java8新特性之JavaFX 8_动力节点Java学院整理

    2023-03-26 02:31:28
  • java8 stream中Collectors.toMap空指针问题及解决

    2023-01-16 13:05:28
  • RabbitMQ延迟队列及消息延迟推送实现详解

    2023-11-15 15:31:31
  • Maven的几个常用plugin

    2021-12-05 13:36:28
  • 教你用Java在个人电脑上实现微信扫码支付

    2023-07-22 20:52:15
  • asp之家 软件编程 m.aspxhome.com