package com.evan;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class RedPacket {
private static final int MAX = 20000; //单个红包不能大于200元
private static final int BALANCE = 1; //平衡值,值越大越平衡,最新红包和最大红包的差距越小
/**
* 生成随机红包[不包含抢]
*
* @param value 红包总金额[单位分]
* @param num 红包个数
* @return
*/
public static List build(int value, int num) {
if (value <= 0) {
throw new RuntimeException("红包金额非法!");
}
if (num <= 0 || num > value) {
throw new RuntimeException("红包份数非法!");
}
if (num * MAX < value) {
throw new RuntimeException("每个红包的金额不能大于[" + (MAX / 100) + "]元!");
}
List list = new ArrayList(num);
for (int i = 0; i < num; i++) {
list.add(0);
}
while (value > 0) {
int average = value / num / BALANCE;//BALANCE的值决定瓜分的次数,次数越多越平衡
int i = 0;
while (average == 0 && value > 0) {
//当剩余金额不足以让每个红包分到钱时,将剩余金额拆成1分钱一次分给红包直到剩余金额为0
//排在前面的红包会有一分钱的固定优势,需要后期需要对所有红包进行乱序去除这种优势
int idx = (i++) % num;
int current = list.get(idx);
if (current == MAX) {
continue;
}
list.set(idx, current + 1);
value--;
}
if (value == 0) {
//当剩余金额为0时停止瓜分
break;
}
for (int idx = 0; idx < num; idx++) {
int current = list.get(idx);
if (current == MAX) {
continue;
}
//从剩余金额中随机瓜分金额到当前红包,Math.min(average, MAX - current)保证当前红包的值不会超过MAX常量
int randomValue = new Random().nextInt(Math.min(average, MAX - current)) + 1;
list.set(idx, current + randomValue);
value = value - randomValue;
if (value == 0) {
break;
}
}
}
//随机乱序
Collections.shuffle(list);
return list;
}
public static void main(String[] args) {
for (int idx = 0; idx < 20; idx++) {
List list = build(90000, 5);
for (int i : list) {
System.out.println(i);
}
System.out.println("==========");
}
}
}