Я пытаюсь построить игру в покер, используя C ++. Функция перетасовки колоды дает мне некоторые проблемы. Каждый раз, когда я запускаю программу, которая инициализирует колоду, перемешивает ее и затем печатает колоду, я получаю один и тот же вывод:
Shuffling the cards and dealing...
Printing deck...
KD
6S
7D
QD
5C
JH
9S
6D
7H
JD
QH
3C
7S
3H
TC
5D
5S
3D
AD
7C
4H
6H
JC
TS
4D
JS
QC
AH
9C
2D
5H
8C
TD
4S
2S
KS
2C
8D
KC
2H
9H
6C
KH
3S
QS
8S
8H
4C
AS
AC
9D
TH
Используя классы Deck и Card I, соответствующие функции определены следующим образом:
Deck::Deck(){
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 13; j++) {
cards[i * 13 + j].suit = i;
cards[i * 13 + j].rank = j;
}
}
Card::suits[0] = "D";
Card::suits[1] = "S";
Card::suits[2] = "H";
Card::suits[3] = "C";
Card::ranks[0] = "2";
Card::ranks[1] = "3";
Card::ranks[2] = "4";
Card::ranks[3] = "5";
Card::ranks[4] = "6";
Card::ranks[5] = "7";
Card::ranks[6] = "8";
Card::ranks[7] = "9";
Card::ranks[8] = "T";
Card::ranks[9] = "J";
Card::ranks[10] = "Q";
Card::ranks[11] = "K";
Card::ranks[12] = "A";
}
void Deck::print(){
cout << "Printing deck..." << std::endl;
for (int i = 0; i < 52; i++) {
cout << Card::ranks[cards[i].rank] << Card::suits[cards[i].suit] << endl;
}
cout << endl;
}
void Deck::shuffle(){
top = 51;
int x;
Card tempCard;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 13; j++) {
cards[i * 13 + j].suit = i;
cards[i * 13 + j].rank = j;
}
}
cout << "Shuffling the cards and dealing..." << endl;
for (int i = 0; i < 52; i++) {
x = rand() % 52;
tempCard = cards[i];
cards[i] = cards[x];
cards[x] = tempCard;
}
}
Есть ли что-то, что я делаю не так? Почему я всегда получаю один и тот же результат, когда он должен быть случайным? Благодарю.
Предполагая, что вы можете использовать функции C ++ 11, вы можете использовать это (взято из https://stackoverflow.com/a/19728404/341065):
#include <random>
std::random_device rd; // only used once to initialise engine
std::mt19937 rng(rd); // random-number engine used
std::uniform_int_distribution<int> uni(min,max); // guaranteed unbiased
auto random_integer = uni(rng);
Ваш код имеет несколько проблем в отношении случайности:
Вы не сеете свой рандомизатор с srand
, так что ваш генератор случайных чисел всегда будет начинаться с начального значения по умолчанию. Обычная практика состоит в том, чтобы сеять это с текущим временем srand(time(NULL))
, Обратите внимание, что Вы должны посеять рандомизатор только один раз в вашей программе.
Ты используешь x = rand() % 52;
, Это плохо, потому что:
типичный rand()
реализации являются печально известен тем, что не очень случайный в своих младших битах.
Количество потенциальных результатов от rand()
(RAND_MAX+1
) вряд ли будет делиться на 52. Чтобы понять, почему это проблема, представьте крайний случай, когда rand()
абсолютно равномерно, может возвращать только один из {0, 1, 2}, и что вы делаете rand() % 2
, Должно быть ясно, что это скорее даст 0, чем 1. Вы можете исправить это с помощью цикла, как описано в SO ответе R ...
Для каждой карты вы всегда случайным образом меняете ее на одну из 52 карт. Этот наивный алгоритм тасования близок к тому, чтобы быть правильным, но немного ошибочным, что приведет к предвзятости. Вы должны вместо этого использовать Алгоритм тасования Фишера-Йейтса. Поскольку вы используете C ++, вы можете просто использовать std::random_shuffle
/std::shuffle
,
Вам нужно запустить генератор случайных чисел. Специально позвонить srand()
один раз в начале программы. Один из распространенных способов сделать это:
srand(time(NULL));
метод rand (), если не инициализирован, возвращает всегда одно и то же «случайное» число. Вы должны инициализировать начальную точку генерации чисел с помощью функции srand ().
Эта функция принимает параметр, который позволяет генерировать разные числа.
Поместите эту строку
srand(time(0));
перед функцией ранда и у вас всегда будут разные цифры.
(время (0) — это системное время. Вы можете указать здесь число, например, 100, но у вас всегда будет один и тот же номер. со временем (0) число будет меняться каждый раз).