Estou procurando uma maneira genérica e reutilizável de embaralhar um std::vector
em C ++. É assim que eu faço atualmente, mas acho que não é muito eficiente porque precisa de um array intermediário e precisa saber o tipo de item (DeckCard neste exemplo):
srand(time(NULL));
cards_.clear();
while (temp.size() > 0) {
int idx = rand() % temp.size();
DeckCard* card = temp[idx];
cards_.push_back(card);
temp.erase(temp.begin() + idx);
}
rand()
, existem melhores APIs RNG disponíveis (Boost.Random ou 0x<random>
).Respostas:
Do C ++ 11 em diante, você deve preferir:
Live example on Coliru
Certifique-se de reutilizar a mesma instância de em
rng
todas as chamadas parastd::shuffle
se pretende gerar permutações diferentes a cada vez!Além disso, se quiser que seu programa crie diferentes sequências de embaralhamento cada vez que for executado, você pode semear o construtor do mecanismo aleatório com a saída de
std::random_device
:Para C ++ 98, você pode usar:
fonte
std::random_shuffle
.std::random_shuffle
se isso for um problema.random_shuffle
. Este comportamento é normal e intencional.#include <algorithm>
http://www.cplusplus.com/reference/algorithm/shuffle/
fonte
std::random_device
?Além do que @Cicada disse, você provavelmente deve semear primeiro,
Por comentário de @FredLarson:
Então YMMV.
fonte
random_shuffle()
é definida pela implementação, portanto, ela pode nem ser usadarand()
. Entãosrand()
não teria efeito. Já deparei com isso antes.random_shuffle
usa para gerar números aleatórios é definido pela implementação. Isso significa que na sua implementação ele usarand()
(e portanto srand () funciona), mas na minha ele pode usar algo totalmente diferente, o que significa que na minha implementação, mesmo com srand, toda vez que executar o programa, obterei os mesmos resultados.Se você estiver usando boost, você pode usar esta classe (
debug_mode
está definida comofalse
, se você quiser que a randomização seja previsível entre a execução, você deve defini-la comotrue
):Então você pode testá-lo com este código:
fonte
std::random_device
?Pode ser ainda mais simples, a propagação pode ser totalmente evitada:
Isso produzirá uma nova ordem aleatória cada vez que o programa for executado. Também gosto dessa abordagem devido à simplicidade do código.
Isso funciona porque tudo o que precisamos
std::shuffle
é de umUniformRandomBitGenerator
, cujos requisitosstd::random_device
atenda.Nota: se embaralhar repetidamente, pode ser melhor armazenar o
random_device
em uma variável local:fonte
random_device
...random_device
é projetado para ser chamado apenas uma vez para semear PRNGs, não para ser chamado repetidamente (o que pode exaurir a entropia subjacente rapidamente e fazer com que ela mude para um esquema de geração abaixo do ideal)Dependendo do padrão que você deve seguir (C ++ 11 / C ++ 14 / C ++ 17), esta página "cppreference" fornece exemplos muito bons: https://en.cppreference.com/w/cpp/algorithm/ random_shuffle .
fonte