-
Notifications
You must be signed in to change notification settings - Fork 7.1k
/
RedPacket.java
145 lines (114 loc) · 3.71 KB
/
RedPacket.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package com.crossoverjie.red;
import java.util.LinkedList;
import java.util.List;
/**
* Function: 模拟微信红包生成,以分为单位
*
* @author crossoverJie
* Date: 03/01/2018 16:52
* @since JDK 1.8
*/
public class RedPacket {
/**
* 生成红包最小值 1分
*/
private static final int MIN_MONEY = 1;
/**
* 生成红包最大值 200人民币
*/
private static final int MAX_MONEY = 200 * 100;
/**
* 小于最小值
*/
private static final int LESS = -1;
/**
* 大于最大值
*/
private static final int MORE = -2;
/**
* 正常值
*/
private static final int OK = 1;
/**
* 最大的红包是平均值的 TIMES 倍,防止某一次分配红包较大
*/
private static final double TIMES = 2.1F;
private int recursiveCount = 0;
public List<Integer> splitRedPacket(int money, int count) {
List<Integer> moneys = new LinkedList<>();
//金额检查,如果最大红包 * 个数 < 总金额;则需要调大最小红包 MAX_MONEY
if (MAX_MONEY * count <= money) {
System.err.println("请调大最小红包金额 MAX_MONEY=[" + MAX_MONEY + "]");
return moneys ;
}
//计算出最大红包
int max = (int) ((money / count) * TIMES);
max = max > MAX_MONEY ? MAX_MONEY : max;
for (int i = 0; i < count; i++) {
//随机获取红包
int redPacket = randomRedPacket(money, MIN_MONEY, max, count - i);
moneys.add(redPacket);
//总金额每次减少
money -= redPacket;
}
return moneys;
}
private int randomRedPacket(int totalMoney, int minMoney, int maxMoney, int count) {
//只有一个红包直接返回
if (count == 1) {
return totalMoney;
}
if (minMoney == maxMoney) {
return minMoney;
}
//如果最大金额大于了剩余金额 则用剩余金额 因为这个 money 每分配一次都会减小
maxMoney = maxMoney > totalMoney ? totalMoney : maxMoney;
//在 minMoney到maxMoney 生成一个随机红包
int redPacket = (int) (Math.random() * (maxMoney - minMoney) + minMoney);
int lastMoney = totalMoney - redPacket;
int status = checkMoney(lastMoney, count - 1);
//正常金额
if (OK == status) {
return redPacket;
}
//如果生成的金额不合法 则递归重新生成
if (LESS == status) {
recursiveCount++;
System.out.println("recursiveCount==" + recursiveCount);
return randomRedPacket(totalMoney, minMoney, redPacket, count);
}
if (MORE == status) {
recursiveCount++;
System.out.println("recursiveCount===" + recursiveCount);
return randomRedPacket(totalMoney, redPacket, maxMoney, count);
}
return redPacket;
}
/**
* 校验剩余的金额的平均值是否在 最小值和最大值这个范围内
*
* @param lastMoney
* @param count
* @return
*/
private int checkMoney(int lastMoney, int count) {
double avg = lastMoney / count;
if (avg < MIN_MONEY) {
return LESS;
}
if (avg > MAX_MONEY) {
return MORE;
}
return OK;
}
public static void main(String[] args) {
RedPacket redPacket = new RedPacket();
List<Integer> redPackets = redPacket.splitRedPacket(20000, 100);
System.out.println(redPackets);
int sum = 0;
for (Integer red : redPackets) {
sum += red;
}
System.out.println(sum);
}
}