【问题标题】:How do I properly develop a Probability System?如何正确开发概率系统?
【发布时间】:2016-02-18 06:03:44
【问题描述】:

所以我正在开发一款在线游戏,这款游戏的特色之一(与许多其他 MMORPG 一样)是掉落系统和升级系统。

掉落系统决定了怪物被杀死时会掉落哪些物品。 升级系统决定一个项目是否会成功升级到下一个级别。

他们都需要能够使用概率来确定:

  1. 物品掉落
  2. 物品升级成功。

我开发了一个系统,可以生成一个介于 0 和 100000 之间的随机数。在这个系统中,上述任何一种情况发生的 1% 的概率用 1000 表示。同样,0.5% 的概率是 500... 50% 就是 50000。

这是这段代码的核心......

int RandomValueInRange(const int start, const int end)
{
   std::random_device rd;
   std::mt19937 generator(rd());
   const int stable_end = ((end < start) ? start : end);
   std::uniform_int_distribution<int> distribution(start, stable_end);

   return distribution(generator);
}

现在,如果一件物品成功掉落或升级,我需要做的就是这个...

const int random_value = RandomValueInRange(0, 100000);
const int probability = item.GetProbability();//This simply returns an integer stored in a config file which represents the probability of this item being dropped/upgraded.
if(random_value <= probability)
{
    std::cout << "Probability Success!" << endl;
}
else
{
    std::cout << "Probability Failed!" << endl;
}

我希望上述方法可以正常工作,但无论出于何种原因,它似乎都有问题......玩家能够轻松获得概率为 0.1% 的物品(这几乎永远不会发生!)。

有谁知道更好的系统或我如何改进这个系统以真正遵循概率指南......

【问题讨论】:

  • 0.1% 的概率并不是真的“几乎从不”,它预计每 1000 次试验会发生 1 次。如果你有 100 名玩家,他们每个人每天杀死 10 件东西,那么你会期望有 1 人每天获得这样的物品掉落。而大约4个月后,基本上每个人都得到了这样的下降。
  • 你似乎在这里重新发明轮子。如果您需要 1000 分之一的机会,请使用 uniform_int_distribution(0, 1000) 并检查它是否出现 0。如果您需要 500 分之一的机会,请使用 uniform_int_distribution(0, 500)。换句话说,直接做对。您似乎正在使用uniform_int_distribution(0, 100000),然后必须修复 1/100000 的机会。 (对于 M 中的 N 机会,您检查结果是否为

标签: c++ random probability


【解决方案1】:
std::random_device rd;
std::mt19937 generator(rd());
...
return distribution(generator);

我认为这里有问题,std c++ library 给你均匀分布 如果您确实重用了 random_device 和 mt19937,但每次都重新创建它们, 这不是它们应该如何使用的方式。 保存在某处这个std::random_device rd和这个std::mt19937和这个distribution

【讨论】:

  • std::random_device 本身会生成一个随机数,然后将其用作生成器的随机种子。如果您每次都使用新的随机种子重新创建生成器,那么最终您仍然应该得到来自分布的随机数。正确的? (就像它不是很好的做法,但它不应该是不正确的)
  • @Oxinabox 但是所有这些使用 3 对象的构造都会生成伪随机数,而这个伪随机数只有在你按顺序调用它们时才会均匀分布,这就是为什么这个对象,他们在里面持有一些状态。如果你每次重新创建它们,它们都会给出随机数,这个随机数会在范围内,但是这个数字序列不应该是均匀分布的,可能是正常的?
【解决方案2】:

好的,所以您的代码的问题是您选择了一个介于 0 到 100,000 之间的随机数。任何人都可以在 1 到 100 之间获得一点运气,因为,如果你仔细想想,100 是一个相当大的数字,应该不会太难获得。

此外,如果您回到小学/小学(或任何您想称呼它的)学校数学书籍,您将在“概率和机会”一章中看到一些问题,例如:

如果一个袋子里有6个球,3个红色,1个绿色和2个蓝色,那么选择蓝色的机会是多少?

当然,你会回答 2/6 或 1/3。在 C++ 中,这可以更改为:

#include <iostream>
#include <ctime>
#include <algorithm>
#include <random>

using namespace std;


// Be sure to have this in to get a truly random number

class MoreProbability {


    // Be sure to have this in to get a truly random number



    void GetProbability(int min, int max, int probability) {
        const int arrayMax = max;
        int probabilityArray[100000];
        for (int i = 0; i < max; i++) {
            if (i >= 0 && i <= probability) {
                probabilityArray[i] = 1;
            }
            else {
                probabilityArray[i] = 0;
            }
        }
        // Arrays go from 0 to max-1 to account for the 0
        std::random_shuffle(&probabilityArray[0], &probabilityArray[max - 1]);

        // Check if the first element of the randomly shufffled array is equal to 1
        if (probabilityArray[0] == 1) {
            cout << "Probability Successful" << endl;
        }
        else {
            cout << "Probability Failed" << endl;
        }
    }
    int main() {
        srand(time(0));

        GetProbability(0, 100000, 100);

        return 0;
    }
};

它可能会产生 StackOverflowException。要解决此问题,只需增加“堆栈保留大小”即可。

编辑:


在稍微更改代码以根据结果返回 1 或 0 并将其放入重复自身 1000 次的 for 循环之后(我确实 建议尝试这样做,因为这需要一段时间完成),我得到了 1 的输出,清楚地表明这段代码运行良好。

【讨论】:

  • @Ricky 请您查看并选择正确答案。
猜你喜欢
  • 1970-01-01
  • 2018-08-09
  • 1970-01-01
  • 2013-05-26
  • 1970-01-01
  • 2018-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多