import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
/**
* 奖品类,封装奖品名称和概率
*/
class Prize {
private final String name;
private final double probability; // 使用double类型精确表示百分比概率
public Prize(String name, double probability) {
this.name = name;
this.probability = probability;
}
public String getName() {
return name;
}
public double getProbability() {
return probability;
}
}
/**
* 抽奖系统核心类
*/
public class LotterySystem {
// 使用线程安全的随机数生成器
private static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current();
// 奖品池配置(需确保总概率为100%)
private static final List<Prize> PRIZE_POOL = new ArrayList<>();
static {
// 初始化奖品配置(按顺序添加)
PRIZE_POOL.add(new Prize("三国主武器皮肤自选卡", 0.10));
PRIZE_POOL.add(new Prize("三国副武器皮肤自选卡", 0.15));
PRIZE_POOL.add(new Prize("三国近战皮肤自选卡", 0.12));
PRIZE_POOL.add(new Prize("三国玩偶自选卡", 0.12));
PRIZE_POOL.add(new Prize("奉先无双投掷皮肤自选卡", 0.20));
PRIZE_POOL.add(new Prize("最终消灭无双", 0.10));
PRIZE_POOL.add(new Prize("消灭音效一无双", 0.15));
PRIZE_POOL.add(new Prize("抛物线一无双", 1.00));
PRIZE_POOL.add(new Prize("狙击枪线一无双", 0.15));
PRIZE_POOL.add(new Prize("【音效卡】AK47-奉先-现代战场", 0.12));
PRIZE_POOL.add(new Prize("【光效】AK47-奉先-无双湖光", 0.50));
PRIZE_POOL.add(new Prize("【命中特效】AK47-奉先一无双之殇", 0.15));
PRIZE_POOL.add(new Prize("【命中数字】AK47-奉先一无双之印", 0.15));
PRIZE_POOL.add(new Prize("【武留按键】AK47-奉先-无双之触", 0.15));
PRIZE_POOL.add(new Prize("【喷漆】无双动态喷漆", 0.80));
PRIZE_POOL.add(new Prize("【挂饰】奉先无双挂饰", 0.50));
PRIZE_POOL.add(new Prize("无双兑换币*10", 3.50));
PRIZE_POOL.add(new Prize("无双兑换币*8", 4.50));
PRIZE_POOL.add(new Prize("无双兑换币*5", 9.00));
PRIZE_POOL.add(new Prize("无双兑换币*3", 27.50));
PRIZE_POOL.add(new Prize("无双兑换币*1", 51.04));
// 验证概率总和
validateTotalProbability();
}
/**
* 抽奖核心方法
*
@Return 中奖奖品名称
*/
public static String draw() {
// 生成0-100之间的随机浮点数(保留4位小数精度)
double randomValue = RANDOM.nextDouble(0, 100.0001);
// 遍历奖品池进行概率区间匹配
double cumulativeProbability = 0.0;
for (Prize prize : PRIZE_POOL) {
cumulativeProbability += prize.getProbability();
// 使用高精度比较避免浮点数误差
if (BigDecimal.valueOf(randomValue)
.compareTo(BigDecimal.valueOf(cumulativeProbability).setScale(4, RoundingMode.HALF_UP)) < 0) {
return prize.getName();
}
}
// 理论上不会执行到此处(概率总和已校验)
throw new IllegalStateException("抽奖逻辑异常");
}
/**
* 验证总概率必须严格等于100%
*/
private static void validateTotalProbability() {
BigDecimal total = BigDecimal.ZERO;
for (Prize prize : PRIZE_POOL) {
total = total.add(BigDecimal.valueOf(prize.getProbability()));
}
//System.out.println(total);
// 使用BigDecimal避免浮点精度问题
if (total.setScale(2, RoundingMode.HALF_UP).compareTo(BigDecimal.valueOf(100.00)) != 0) {
throw new IllegalArgumentException("奖品概率总和不等于100%,当前总和:" + total + "%");
}
}
/**
* 测试方法(包含概率分布验证)
*/
public static void main(String[] args) {
// 模拟10次抽奖
int totalTimes = 10;
for (int i = 0; i < totalTimes; i++) {
String prize = draw();
System.out.println("抽奖结果:" + prize);
}
}
}