random_shuffle не совсем случайный

Я использую random_shuffle на векторе, как это:

#include <algorithm>
vector <Card> deck;
//some code to add cards to the deck here
random_shuffle ( deck.begin(), deck.end() );

При запуске содержимое колоды перемешивается, но этот порядок смешивания сохраняется при перезапуске программы.

Я что-то пропустил? Как я могу сделать это действительно случайным?

9

Решение

Вам нужно сначала запустить генератор псевдослучайных чисел, используя srand.

#include <algorithm>
#include <cstdlib>

...

std::srand(std::time(0));

vector <Card> deck;
//some code to add cards to the deck here
random_shuffle ( deck.begin(), deck.end() );

Примечание по ссылке выше:

Вообще говоря, генератор псевдослучайных чисел должен быть только
Сеял один раз, перед любыми вызовами rand () и запуском программы.
Он не должен быть повторно посеян или повторно посеян каждый раз, когда вы хотите
генерировать новую партию псевдослучайных чисел.

14

Другие решения

С текущим C ++ (т.е. C ++ 11) вы можете использовать shuffle Алгоритм, который может принять объект генератора псевдослучайных чисел (PRNG) (который вы можете заполнить) в качестве третьего параметра:

#include <iostream>
#include <random>
#include <algorithm>
#include <vector>
#include <string>
#include <ctime>
using namespace std;

int main(int argc, char **argv)
{
vector<string> v;
for (int i = 1; i<argc; ++i)
v.push_back(argv[i]);
mt19937 g(static_cast<uint32_t>(time(0)));
shuffle(v.begin(), v.end(), g);
for (auto &x : v)
cout << x << ' ';
cout << '\n';
}

(для GCC 4.8.2 вам нужно скомпилировать его через g++ -std=c++11 -Wall -g shuffle.cc -o shuffle)

В приведенном выше примере PRNG засевается с текущим системным временем.

Для компиляторов до C ++ 11 у вас есть только random_shuffle алгоритм в STL — но даже с этим вы можете дополнительно указать объект / функцию генератора чисел для него. Обратите внимание, что вы не можете просто вставить объект PRNG, как mtl19937 в него (потому что он не обеспечивает operator()(U upper_bound) членом).

Таким образом, вы можете поставить свой собственный адаптер следующим образом:

#include <iostream>
#include <random>
#include <algorithm>
#include <vector>
#include <string>
#include <ctime>
using namespace std;

struct Gen {
mt19937 g;
Gen()
: g(static_cast<uint32_t>(time(0)))
{
}
size_t operator()(size_t n)
{
std::uniform_int_distribution<size_t> d(0, n ? n-1 : 0);
return d(g);
}
};

int main(int argc, char **argv)
{
vector<string> v;
for (int i = 1; i<argc; ++i)
v.push_back(argv[i]);
random_shuffle(v.begin(), v.end(), Gen());
for (vector<string>::const_iterator i = v.begin(); i != v.end(); ++i)
cout << *i << ' ';
cout << '\n';
}
8

Поместите строку:

srand (time (0));

в вашем коде, прежде чем сделать что-нибудь еще, например, в начале main(),

Без этого всегда будет использоваться начальное значение по умолчанию, равное 1, что приводит к идентичным последовательностям из rand() и все, что его использует.

3
По вопросам рекламы [email protected]