java 按百分比机会从列表中随机获取

问题描述 投票:0回答:1

我有一个清单:

public List<Map<Integer, Rarity>> classes = Arrays.asList(
  Collections.singletonMap(0, new Rarity("rarity_default", "Default!", 55.0)),
  // ...
);

在此列表中,55.0 的可能性为 55%。

我想从这个类别中获得一个随机的稀有类别,但通过机会获得它。

例如我有这些机会:

  • 稀有度_A:55.00%
  • 稀有度_B:35.00%
  • 稀有度_C:12.00%
  • 稀有度_D:6.00%
  • 稀有度_E:3.00%
  • 稀有度_F:0.10%

另外,我不希望它总是像我尝试自己编码一样获得物品,但它的工作效率高达 12.00%,低于它不会给我带来稀有性。而且它也会给我最高机会的稀有性,而不是什么都没有,因为我不想总是得到它。

目前这是我的代码:

  private final Map<Integer, Rarity> classes = new HashMap<>();

  private final Random random = new Random();

  public MobKillListener() {
    for (Map<Integer, Rarity> rarityMap : SchemePlugin.getInstance().getSchemeConfig().classes) {
      classes.putAll(rarityMap);
    }
  }

  @EventHandler
  public void onMobKill(EntityDeathEvent event) {
    if (!(event.getEntity().getKiller() instanceof Player))
      return;

    Map<Rarity, Double> rarities = new HashMap<>();

    for (Map.Entry<Integer, Rarity> entry : classes.entrySet()) {
      rarities.put(entry.getValue(), entry.getValue().rarity); // i need to remake the map
    }
    
    Rarity rarity = random(rarities);
    if (rarity != null) {
      // do my stuff
    }
  }

  // i don't want to see this function ever again, this made me so mad..
  public <T> T random(Map<T, Double> map) {
    double rand = (double) new Random().nextInt(10000001) / 100000.0D;
    double total = 0.0D;

    for (T t : map.keySet()) {
      double chance = map.get(t) / 4.0D;
      total += chance;

      if (total >= rand) {
        System.out.println("(" + chance + ") " + "Got " + total + ", rand: " + rand);
        return t;
      }
    }
    System.out.println("Got " + total + ", rand: " + rand);

    return null;
  }

是的,我正在为 Spigot 插件执行此操作。

java bukkit spigot
1个回答
0
投票

@迈克尔

我这样做了,但我觉得可能性很低,但实际上却很高。 此外,我仍然收到最高的机会而不是空,因为最低的机会太高了。你能修改我的代码并给出解释吗?

private <T> T random(Map<T, Double> map) {
  List<T> items = new ArrayList<>(map.keySet());
  List<Double> chances = new ArrayList<>(map.values());

  double sum = 0;
  for (int i = 0; i < chances.size(); i++) {
    sum += chances.get(i);
    chances.set(i, sum);
  }

  Random random = new Random();
  double randomNumber = random.nextDouble();

  for (int i = 0; i < chances.size(); i++) {
    System.out.println(randomNumber + " < " + chances.get(i));

    if (randomNumber < chances.get(i)) {
      return items.get(i);
    }
  }
  return null;
}

private void handle_event(String[] args) {
  Map<String, Double> rarityMap = Map.of(
      "Item1", 20.0,
      "Item2", 35.0,
      "Item3", 15.0,
      "Item4", 10.0,
      "Item5", 5.0,
      "Item6", 10.0,
      "Item7", 3.0,
      "Item8", 2.0
  );

  System.out.println(random(rarityMap));
}
© www.soinside.com 2019 - 2024. All rights reserved.