题目: 小红在群里(15人)发了100元,10个的拼手气红包,如何实现?
一、题目分析
- 会有人抢不到,因为群人数大于了红包个数,需要考虑加🔐
- 如何更加合适的随机,多数人应该在10元左右
- 如果有人随机到了0,则取1分钱
二、代码构思
- 设计一个红包类
- 包含的属性应该有金额,个数,还有随机功能
- 实例方法,每次拆一个,返回拆得的金额
三、代码编写
package RedPackage;
import java.util.Random;
public class RedPackage {
private int remainMoney;
private int remainCount;
private Random random;
public RedPackage(int remainMoney, int remainCount) {
this.remainMoney = remainMoney;
this.remainCount = remainCount;
this.random = new Random();
}
//获取下一个红包的值
public int nextPackage() {
if(this.remainCount == 1) {
return this.remainMoney;
}
int currentMoney = Math.max(1, this.random.nextInt(this.remainMoney));
this.remainMoney -= currentMoney;
this.remainCount--;
System.out.println(currentMoney);
return currentMoney;
}
}
测试代码:
package RedPackage;
public class RedPackageTest {
public static void main(String[] args) {
RedPackage redPackage = new RedPackage(100, 10);
int sum = 0;
int currentMoney;
for(int i = 0; i<10; i++) {
currentMoney = redPackage.nextPackage();
System.out.println("currentMoney: " + currentMoney);
sum += currentMoney;
}
System.out.println("数据之和是:" + sum);
}
}
代码测试:
执行后,发现报错了。分析一下前两次拆的金额过大,导致后面的人不够分了,出现了边界值为0的情况。
再次观察真实的微信拆红包的效果,其中最大的值是11.5大致在(0~100/16 * 2)的范围内,并不是之前考虑的每次都从剩余金额中随机。所以可以对程序做如下优化:
int currentMoney = Math.max(1, this.random.nextInt(this.remainMoney / 10 * 2));
再次进行测试:
发现剩余的总是比较多,还是有问题,
this.remainMoney / 10
这里10不应该是定值,应该随着拆的剩余的红包个数变化而变化。
int currentMoney = Math.max(1, this.random.nextInt(this.remainMoney /this.remainCount * 2));
测试效果如下:
最后转换成我们可以理解的方式输出
package RedPackage;
import java.math.BigDecimal;
public class RedPackageTest {
public static void main(String[] args) {
RedPackage redPackage = new RedPackage(100*100, 10);
BigDecimal b = new BigDecimal(0);
int currentMoney;
for(int i = 0; i<10; i++) {
currentMoney = redPackage.nextPackage();
BigDecimal res = BigDecimal.valueOf(currentMoney);
BigDecimal yuan = res.divide(BigDecimal.valueOf(100));
System.out.println(yuan + "元");
b = b.add(yuan); //BigDecimal的累加方式
}
System.out.println("数据之和是:" + b);
}
}
运行结果