2

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

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();
}

上面的代码不起作用加上我怎样才能使它,如果它是假的,它会再次生成随机数?

我不是在寻找答案,只是帮助我确切地需要做什么。谢谢!

4

6 回答 6

5

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

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

...由于模数,变量fm可能具有相同的值,因此永远不会调用您的fire_Weapon()andupdate_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()此外,如果您希望每次运行游戏时返回的伪随机数序列都不同,请在伪随机数生成器中调用srand( time() )一次。如果您希望每次运行游戏时序列保持不变,请保持原样。这可以极大地帮助调试,如果您的游戏需要确定性,这是必需的。

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

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

于 2013-05-15T05:17:12.140 回答
4

一种解决方案是

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();

但是您应该阅读Reservoir sampling来了解如何从一组中随机选择 k 个数字。你可以有一个从 1 到 num_enemy 的整数数组。然后从这个数组中随机选择两个数字。这是一个 order n 解决方案,如果您的阵列很小,它会很好用。

编辑:根据评论编辑代码

于 2013-05-15T05:12:41.977 回答
4

“上面的代码不起作用”有点含糊。我猜你f == m每次都是这个意思?

在这种情况下,您可能忘记播种RNG。请参阅srand. 或者更好的是,将新的 c++随机库用于伪随机数生成器。

至于如何在f == m......你知道while循环时重新生成随机数吗?阅读控制结构和简单的 c++ 语法是个好主意。

于 2013-05-15T05:14:23.567 回答
2

如果您考虑一下,您可以通过从可能性较小的池中挑选来确保第二个随机数与第一个不同:

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);
于 2013-05-15T05:29:59.700 回答
1

如果您想要在某些条件下重复某些内容,那么您需要的是一个循环,即为重复而构建的结构。在这种情况下,由于您想在检查条件之前至少执行一次此操作,因此我建议使用 do-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();
于 2013-05-15T05:20:08.900 回答
0
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减少了可能值的数量,并将选择的任何值调整为可能值之一。也就是说,如果大于或等于为 选择的值,我们加一。这是“聪明”的写法,因为布尔值被转换为零或一。m% (num_enemy-1)mmfm += (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);
于 2013-05-15T07:11:03.770 回答