C++需要帮助if!=转换为随机数

C++ need assistance with if != to a random number

本文关键字:转换 随机数 if 帮助 C++      更新时间:2023-10-16

我正在做一个项目,我被卡住了。我有两个产生随机数的变量。我想做一个检查,确保变量不是同一个数字,如果是,那么重复这个过程,直到它们不一样。这是我所拥有的:

num_enemy = 3;
int f =  rand() % num_enemy;
int m =  rand() % num_enemy;
if ( f != m )
{
enemy_ptr[f] -> fire_Weapon();
enemy_ptr[m] -> update_Status();
}

上面的代码不起作用,加上我如何使它,如果它是假的,它将再次生成随机数?

我不是在寻找答案,只是帮助我做什么。谢谢!

问题是,当它到达这个部分时。。。

if ( f != m )
{
    enemy_ptr[f] -> fire_Weapon();
    enemy_ptr[m] -> update_Status();
}

由于取模,变量fm可能具有相同的值,因此永远不会调用fire_Weapon()update_Status()函数。您将需要循环,直到两个变量都有不同的值。下面的代码应该会帮你解决问题。

const int num_enemy = 3;
int f = rand() % num_enemy;
int m;
// A do-while loop is guaranteed to be called at least once.
do
{
    m = rand() % num_enemy;
} while ( f == m ); // Repeat the loop if the values are the same
// At this point, f and m will always have different values.
enemy_ptr[f] -> fire_Weapon();
enemy_ptr[m] -> update_Status();

因为变量是以低值取模的,所以循环可能必须在f != m之前运行多次。

此外,如果您希望每次运行游戏时rand()返回的伪随机数序列不同,请在psuedo随机数生成器中调用srand( time() )一次。如果你希望每次运行游戏时序列保持不变,就保持原样。这对调试有很大帮助,如果你的游戏需要确定性,这是必需的。

在此处阅读有关rand()srand()的更多信息:http://www.cplusplus.com/reference/cstdlib/rand/

正如在另一个答案中提到的,C++11改进了随机数的生成。点击此处了解更多信息:http://www.cplusplus.com/reference/random/

"上面的代码不起作用"有点模糊。我猜你的意思是每次f == m

在这种情况下,您可能忘记种子RNG。请参阅srand的文档。或者更好的是,使用新的c++随机库来生成伪随机数。

关于CCD_ 12。。。你知道while循环吗?阅读控制结构和简单的c++语法是个好主意。

一种解决方案是

num_enemy = 3;
int f =  rand() % num_enemy;
int m =  rand() % num_enemy;
while(f==m) {
    f = rand() % num_enemy;
    //m = rand() % num_enemy;
}
enemy_ptr[f] -> fire_Weapon();
enemy_ptr[m] -> update_Status();

但你应该阅读水库采样,学习如何从一组中随机选择k个数字。您可以有一个从1到numenemy的整数数组。然后从这个数组中随机选择两个数字。这是一个n阶的解决方案,如果你的数组很小,它会很好地工作。

EDIT:根据注释编辑代码

如果你仔细想想,你可以通过从一个可能性较小的池中挑选来确保第二个随机数与第一个不同:

num_enemy = 3;
int f =  rand() % num_enemy;
// pick another non-zero number from a pool that's smaller by one than before
int next_offset =  1 + (rand() % (num_enemy-1));
// add it to the previous result (modulo the range)
int m = (f + next_offset) % num_enemy;
assert( 0 <= f && f < num_enemy);
assert( 0 <= m && m < num_enemy);
assert( f != m );
enemy_ptr[f] -> fire_Weapon();
enemy_ptr[m] -> update_Status();

当然,因为rand()不一定是一个很好的RNG,而且简单地使用%将随机数映射到某个范围通常会引入偏差,所以如果这很重要的话,您可能需要调整它的实现来处理这些问题。

如果你更喜欢循环解决方案,就没有必要一直选择两个数字(尽管我认为也没有太大危害(:

int f =  rand() % num_enemy;
int m;
do {
    m = rand() % num_enemy;
} while (f == m);

如果你想要在某种条件下重复某个东西,你需要的是一个循环,即为重复而构建的结构。在这种情况下,由于你想在检查条件之前至少做一次,我建议你做一次while循环:

 int f, m;
 do {
   f = rand() % num_enemy;
   m = rand() % num_enemy;
 } while(f == m);
 enemy_ptr[f] -> fire_Weapon();
 enemy_ptr[m] -> update_Status();
num_enemy = 3;
int f =  rand() % num_enemy;
int m =  rand() % (num_enemy-1);
m += (m>=f);
enemy_ptr[f] -> fire_Weapon();
enemy_ptr[m] -> update_Status();

其思想是f得到的任何数字都是从m的一组可能值中取出的。由于已经从m的可能集合中删除了一个值,我们通过使用% (num_enemy-1)来减少m的可能值的数量,并将为m选择的任何值调整为可能值之一。也就是说,如果m大于或等于为f选择的值,我们加一。这被"巧妙地"写成m += (m>=f);,因为布尔值被转换为零或一。

此外,rand()通常不是一个好的随机数生成器,并且使用mod不能很好地在您想要的范围内产生均匀分布。您应该使用C++11 <random>库。

#include <random>
int num_enemy = 3;
// set up decent random number engine and distributions
std::mt19937 eng;
std::uniform_int_distribution<> f_dist{0, num_enemy-1};
std::uniform_int_distribution<> m_dist{0, num_enemy-2};
int f = f_dist(eng);
int m = m_dist(eng);
m += (m>=f);