我遇到某个代码段的问题,该代码段应该根据预设的难度级别向敌人提供一组随机的项目。我正在使用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
答案 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
,这是一个非常重的对象,包含许多必须在创建时分配和生成的状态。确保您始终重复使用引擎可以节省一些时间。