gpt4 book ai didi

c# - 游戏设计/理论,战利品掉落几率/生成率

转载 作者:IT王子 更新时间:2023-10-29 04:28:58 29 4
gpt4 key购买 nike

我有一个非常具体且冗长的问题要问大家。这个问题既关于编程又关于博弈论。我最近在我的回合制策略游戏中添加了可生成的矿石:http://imgur.com/gallery/0F5D5Ij (对于你们中的那些人,请原谅开发纹理)。

现在,进入我一直在思考的谜题。在我的游戏中,每次创建新 map 时都会生成矿石。每次创建关卡都会生成 0-8 个矿石节点。我已经有这个工作了;除了此时它只生成“Emeraldite”,这让我想到了我的问题。

作为程序员,我将如何使节点具有特定的稀有度?考虑这个实际上不是游戏数据的简短模型:

(一个节点将是以下之一的伪概率)

Bloodstone 1 in 100
Default(Empty Node) 1 in 10
Copper 1 in 15
Emeraldite 1 in 35
Gold 1 in 50
Heronite 1 in 60
Platinum 1 in 60
Shadownite 1 in 75
Silver 1 in 35
Soranite 1 in 1000
Umbrarite 1 in 1000
Cobalt 1 in 75
Iron 1 in 15

我想让生成的节点在理论上可以是上述任何一种,但是,还要考虑几率。我希望这个问题足够清楚。我一直在努力解决这个问题,甚至试图用随机数写出一些 if 语句,但是,我总是空手而归。

基本上,我只是想让你们看看我的问题,并希望能为我提供一些关于如何以动态方式解决这个问题的见解。

如果需要任何说明,请询问;如果这令人费解,再次抱歉。

(我添加 C# 作为标签只是因为这是我在这个项目中使用的语言)

最佳答案

我首先将每种战利品类型的概率表示为一个简单的数字。纯数学中的概率通常表示为 0 到 1 范围内的 float ,但为了效率,您可以使用任何(足够大)范围内的整数(每个值是 0-1 值乘以最大值(我在这里调用 MaxProbability))。

e.g. Bloodstone (1 in 100) is 1/100 = 0.01, or MaxProbability * (1/100).
Copper (1 in 15) is 1/15 = 0.06667, or MaxProbability * (1/15).

我假设“默认(空节点)”表示没有其他节点的概率。在这种情况下,最简单的方法是不定义它 - 如果没有选择其他任何一个,您就会得到它。

如果包含“默认”,所有这些概率的总和将为 1(即 100%)(或 MaxProbability,如果使用整数)。

在您的示例中,“默认”的 1/10 概率实际上是一个矛盾,因为所有这些概率的总和不是 1(它是 0.38247619 - 在我上面的示例中计算的概率总和)。

然后您将选择一个 0 到 1 范围内的随机数(如果使用整数,则选择 MaxProbability),并且选择的战利品类型是列表中的第一个,使得概率之和它和之前所有的(“累积概率”)大于随机数。

例如

MaxProbability = 1000   (I'm using this to make it easy to read).
(For accurate probabilities, you could use 0x7FFFFFFF).

Type Probability Cumulative
---- ----------- ----------
Bloodstone 10 10 (0..9 yield Bloodstone)
Copper 67 77 (10+67) (10..76 yield Copper)
Emeraldite 29 105 (77+29)
Gold 20 125 etc.
Heronite 17 142
Platinum 17 159
Shadownite 13 172
Silver 29 200
Soranite 1 201
Umbrarite 1 202
Cobalt 13 216
Iron 67 282

Default (Empty Node) 7175 1000 (anything else)

例如如果您在 0 到 999(含)范围内的随机数是 184(或 172 到 199 范围内的任何数字),您将选择“银”(累积概率大于此的第一个)。

您可以将累积概率保存在一个数组中并循环遍历它,直到找到一个比随机数更高的数,或者到达末尾。

列表的顺序无关紧要。每个实例您只选择了一个随机数。

在列表中包含“默认(空节点)”意味着最后的累积概率将始终是 MaxProbability 并且搜索它的循环永远不会结束。 (或者,'Default' 可以省略,如果循环到达列表末尾则选择它。)

请注意,依次为每个人选择一个随机数,例如1/10 的几率是“血石”,如果不是血石,则有 1/15 的几率是铜,使概率偏向较早的项目:铜的实际概率为 (1/15) * (1 - (1/10)) - 比 1/15 少 10%。

这是执行此操作的代码(实际选择是 5 个语句 - 在方法 Choose 中)。

using System;

namespace ConsoleApplication1
{
class LootChooser
{
/// <summary>
/// Choose a random loot type.
/// </summary>
public LootType Choose()
{
LootType lootType = 0; // start at first one
int randomValue = _rnd.Next(MaxProbability);
while (_lootProbabilites[(int)lootType] <= randomValue)
{
lootType++; // next loot type
}
return lootType;
}

/// <summary>
/// The loot types.
/// </summary>
public enum LootType
{
Bloodstone, Copper, Emeraldite, Gold, Heronite, Platinum,
Shadownite, Silver, Soranite, Umbrarite, Cobalt, Iron, Default
};

/// <summary>
/// Cumulative probabilities - each entry corresponds to the member of LootType in the corresponding position.
/// </summary>
protected int[] _lootProbabilites = new int[]
{
10, 77, 105, 125, 142, 159, 172, 200, 201, 202, 216, 282, // (from the table in the answer - I used a spreadsheet to generate these)
MaxProbability
};

/// <summary>
/// The range of the probability values (dividing a value in _lootProbabilites by this would give a probability in the range 0..1).
/// </summary>
protected const int MaxProbability = 1000;

protected Random _rnd = new Random((int)(DateTime.Now.Ticks & 0x7FFFFFFF));


/// <summary>
/// Simple 'main' to demonstrate.
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
var chooser = new LootChooser();
for(int n=0; n < 100; n++)
Console.Out.WriteLine(chooser.Choose());
}
}
}

关于c# - 游戏设计/理论,战利品掉落几率/生成率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25991198/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com