I was wondering what's the best way to distribute something over a set number of objects. I'm trying to create a minesweeper game where there are a certain number of tiles, and a set number of mines, but I'm not sure the best way to randomly distribute numbers over a range.
Concretely, if I had a vector of say 400 objects, what's the best way to randomly distribute one boolean attribute so that like 30 of those 400 had true and the rest were false?
struct Tile {
bool mine;
// ...
};
std::vector<Tile> v(400);
I was thinking perhaps something like a probability system where a set number of my tiles absolutely had to have the attribute, and I could create a numbering vector of all the objects and roll random numbers, then removing those objects from the vector until the met number of mines were set.
CodePudding user response:
Generate the array with the set amount of each values you want and then shuffle them.
https://en.cppreference.com/w/cpp/algorithm/random_shuffle
CodePudding user response:
int N = 400;
int numMines = 30;
vector<bool> hasMine;
for(int i = 0; i < N; i ){
if(i < numMines) hasMine.push_back(true);
else hasMine.push_back(false);
}
random_shuffle(hasMine.begin(), hasMine.end());
If you care too much about the accuracy of your shuffle, you can use the shuffle method with a separate random generator(read more about it here). But this should be good enough for a simple game.
CodePudding user response:
What you're trying to do here is transform a randomly sampled subset of the vector. The range-v3 library has views::sample
that can be used for this purpose:
for (auto & tile : v | ranges::views::sample(30))
tile.mine = true;
Here's a demo.
This solution has the advantage that no copies of the vector need to be made, nor is any additional memory needed. Also, this works without moving around any of the objects in the vector.
This view is slated to be added to C 23, though it is only Tier 3 priority.