我可以在C++中从一个数组中随机选择一个元素吗?

3

这件事一直困扰着我好几天了:

#include <iostream>
using namespace std;

string words[] = {"cake", "cookie", "carrot", "cauliflower", "cherries", "celery"};
string word = words[rand() % 6];
string guess;
int lives = 3;

int main()
{
    std::cout << "Can you guess what word I'm thinking of? I'll give you a hint: it's a food that starts with the letter C. You have three tries. Good luck!" << std::endl;

    while(lives > 0)
    {
        std::cin >> guess;
        std::cout << std::endl;

        if(guess == word)
        {
            std::cout << "Wow, That's actually correct! Good job!" << std::endl;
            break;
        }
        else
        {
            lives--;

            std::cout << "Nope! You now have " << lives << " lives left." << std::endl;
        }
    }

    if(lives <= 0)
    {
        std::cout << "And... you lose!" << std::endl;
    }

    return 0;
}

我目前正在开发一个猜词游戏,但当我尝试从我的words数组中随机选择一个元素时,它卡在了第1个元素上(即“cookie”)。我使用的代码是:

string words[] = {"cake", "cookie", "carrot", "cauliflower", "cherries", "celery"};
string word = words[rand() % 6];

需要帮助,感激不尽。


1
你没有使用srand初始化rand,所以它总是返回相同的数字,我猜在你的平台上是6的倍数加1。 - Alan Birtles
1
你需要为随机数生成器提供种子 - "...std::srand() 会为 rand() 使用的伪随机数生成器提供种子。如果在调用 srand() 之前使用 rand(),则 rand() 的行为就像它被 srand(1) 种子初始化一样...." 参见 https://zh.cppreference.com/w/cpp/numeric/random/rand - Richard Critten
1
这个回答解决了你的问题吗?如何在C++中生成随机数? - prehistoricpenguin
为什么要在 main 之外声明任何东西?对于 words,我有点明白你为什么这样做,但对于其他任何东西,这几乎没有意义,实际上会将逻辑分散到比必要更大的代码区域中,使其有点难以理解。 - fabian
4个回答

4
如果你想以C++的方式实现,可以使用 "" 和 "" 库。对于维护来说,我认为使用 std::vector 是一个不错的选择。
#include <iostream>
#include <vector>
#include <string>
#include <random>

int main()
{
    std::vector<std::string> words{ "cake", "cookie", "carrot", "cauliflower", "cherries", "celery" };

    // gets 'entropy' from device that generates random numbers itself
    // to seed a mersenne twister (pseudo) random generator
    std::mt19937 generator(std::random_device{}());

    // make sure all numbers have an equal chance. 
    // range is inclusive (so we need -1 for vector index)
    std::uniform_int_distribution<std::size_t> distribution(0, words.size() - 1);

    for (std::size_t n = 0; n < 40; ++n)
    {
        std::size_t number = distribution(generator);
        std::cout << words[number] << std::endl;
    }
}

我建议不要使用std::random_device来生成随机数。它会清空熵池并且非常慢。相反,只需使用一次来播种伪随机生成器,例如:std::mt19937 rd(std::random_device{}()); - 除此之外,回答很好。它实际上使用现代的C++ random库以随机顺序生成单词。 - Ted Lyngmo
1
不知道使用随机设备会对性能造成负面影响。所以我已经更新了代码。希望C++11及以后的示例有一天会成为常态 :) - Pepijn Kramer

2

rand()是一个伪随机数生成器。这意味着,给定相同的起始条件(种子),它每次都会生成相同的伪随机数序列。

因此,更改随机数生成器的种子(例如,使用当前时间作为随机数生成器的起始条件)。

#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;

static const string words[] = {"cake", "cookie", "carrot", "cauliflower", "cherries", "celery"};

int main() {
   //variables moved to inside main()
   string guess;
   int lives = 3;

   srand(time(NULL));
   string word = words[rand() % 6];

0

在C++中,你不应该使用rand,因为有更好的随机引擎。

#include <iostream>
#include <array>
#include <random>

using namespace std;

// use std::array as a better alternative to C arrays
array words {"cake", "cookie", "carrot", "cauliflower", "cherries", "celery"};
string guess;
int lives = 3;

int main()
{
    std::mt19937 gen{std::random_device{}()}; // generates random numbers
    std::uniform_int_distribution<std::size_t> dist(0, words.size() - 1); // maps the random number to [0..number of words]
    
    int index = dist(gen);
    string word = words[index];

    ...
}

你需要对 gen 进行种子初始化,否则每次启动程序都会得到相同的单词序列。此外,由于你在 minmax 中混合使用了类型,因此 uniform_int_distribution 的模板参数推导可能会失败。 - Ted Lyngmo

0
如果您没有使用srand()函数生成随机数种子,
您的程序将自动使用种子1进行生成。
因此,您可以按照以下方式进行操作:
#include<cstdlib>
#include<ctime>
...
int main()
{
    srand(time(NULL));
    ....
}

不是0或其他东西,而是1:https://zh.cppreference.com/w/cpp/numeric/random/rand - Alan Birtles

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接