在Switch语句案例中使用随机数

时间:2017-04-18 20:49:18

标签: c++ random

我遇到某个代码段的问题,该代码段应该根据预设的难度级别向敌人提供一组随机的项目。我正在使用Bjorne随机函数的修改模板版本。当我使用他的原始版本时,我仍然遇到了问题:

Random number generator code from Stroustrup:

template<class T>
T rand_num(const T & low, const T & high)
{
    static std::default_random_engine re{};
    using Dist = std::uniform_int_distribution<T>;
    static Dist uid{};
    return uid(re, Dist::param_type{ low,high });
}

当我通过制作一个封装EnemyAI的{​​{1}}对象并将难度设置为1来测试该部分时,它始终将随机数设置为1并始终选择,在这种情况下,生命药水。如果我将第二个OffensiveEntity语句设置为if条件,它将选择该棒。

if (tempRandom == 1)

这个问题的原因是什么?这是输出:

void EnemyAI::Equip()
{
    m_offensiveEntity->ClearItems();

    std::vector<std::shared_ptr<Item>> tempItems;

    int tempRandom = 0;

    switch (m_difficultyLevel)
    {
    case 0:
    case 1:
    {
        tempRandom = rand_num<int>(1, 4);
        if ((tempRandom == 1) || (tempRandom == 2) || (tempRandom == 3) || (tempRandom == 4))
            tempItems.push_back(CreateTempItem("Health Potion : HP", 3, 3, 
-10, Result::Effect::nothing));
        if (tempRandom == 3)
            tempItems.push_back(CreateTempItem("Wooden Stick : DMG", 5, 2, 10, Result::Effect::nothing, 3, 13, Result::Effect::nothing));
        break;
    }
    case 2: ... etc

输入时:

Health Potion : HP name
3 durability
-10 total damage
3 energy cost
0 effect

继承了pastebin中的源代码 https://pastebin.com/F4Q74Gc6

1 个答案:

答案 0 :(得分:1)

您的引擎未被播种,因此每次运行程序时都使用相同的默认值。为了确保每次运行都不同,你需要播种它。

一些守旧程序员通常建议将当前系统时钟作为整数并将其用作种子,但C ++ 11特别建议您使用std::random_device,它将尝试通过读取来获取真正的随机数CPU中的温度传感器或通过一些类似的方法,如果它无法做到这一点,它将回退到伪随机方法(如抓住系统时钟或其他方法)。

template<class T>
T rand_num(const T & low, const T & high)
{
    static std::default_random_engine re{std::random_device{}()};
    using Dist = std::uniform_int_distribution<T>;
    static Dist uid{};
    return uid(re, Dist::param_type{ low,high });
}

此外,您的代码将为您用于生成数字的每种类型创建一个新引擎。例如,如果您调用rand_num<int32_t>rand_num<int64_t>rand_num<int16_t>,那三个不同的引擎将由运行时分配和维护在堆栈中。除非你觉得你肯定需要这样做,否则你最好编写看起来像这样的代码:

template<class T>
T rand_num(std::default_random_engine & re, const T & low, const T & high)
{
    using Dist = std::uniform_int_distribution<T>;
    static Dist uid{};
    return uid(re, Dist::param_type{ low,high });
}

int main() {
    std::default_random_engine engine{std::random_device{}()};
    /*...*/
    int val = rand_num<int>(engine, 1, 4);
    /*...*/
}

许多C ++实现将std::default_random_engine映射到std::mt19937,这是一个非常重的对象,包含许多必须在创建时分配和生成的状态。确保您始终重复使用引擎可以节省一些时间。