Background: I'm shuffling the elements of a vector for a simple game. It should be possible to play the same game over again by passing the same integer seed — and vice versa, different seeds should produce different games. Cryptographic security (or any rigor at all) is not a design goal; cleanliness of code is a design goal.
C++98/C++03 introduced std::random_shuffle, which is used like this:
int seed = ...;
std::srand(seed); // caveat, see below
std::vector<int> deck = ...;
std::random_shuffle(deck.begin(), deck.end());
However, as of C++14, random_shuffle has been deprecated (source: N3924). The C++14 way of shuffling a deck is
int seed = ...;
std::vector<int> deck = ...;
std::shuffle(deck.begin(), deck.end(), std::mt19937(seed));
Here are the things that detract from each approach:
The
srand/random_shuffleway is deprecated in C++14, so we shouldn't use it.On some implementations,
random_shuffleappears not to take its seed fromsrand, i.e., seeding with a different value doesn't produce different output! (libstdc++ on Linux doesn't have this issue, but Xcode on OSX 10.9.5 does.)The
shuffle/mt19937way isn't part of C++03, so we can't use it.The
shuffle/mt19937way appears to require that we pass the seed all the way down into the deck-shuffling code. For my application, I'd prefer to just "set it and forget it" via a mechanism such assrandthat hides the global variable, rather than have to define my own global PRNG of typemt19937. In other words: I don't want to be bothered with PRNG details, I just want to shuffle my vector!I am mildly worried about thread-safety (being able to simultaneously shuffle two different decks from different threads), but obviously not about thread-safety and "seedableness" at the same time. Consider thread-safety a "nice-to-have".
The first candidate I've thought of is:
bite the bullet and pass
int seedall the way down into the deck-shuffling code (avoiding global variables)use something like
#if __cplusplus >= 20110000to userandom_shufflepre-C++11 andshufflepost-C++11to work around the
srand"bug" on OSX, use the three-argument version ofrandom_shufflewith some complicated functor... this sounds ugly
The second candidate is:
- screw C++03; just drop support for any implementation that doesn't provide
std::shuffleandstd::mt19937out of the box
But is there some nice way to solve this problem? I know it's a problem that nobody has unless their program is a toy program; but there must be hundreds of toy programs out there that have hit this problem!
Aucun commentaire:
Enregistrer un commentaire