Reputation: 113
I searched on the forum and found only shuffling solutions withing Java or Javascript. For my project, I need to be able to shuffle a 2 dimensional card deck array. It is within two dimensions to be able to have the suit and the card score available.
cardDeck[5][14]
is my array. To specify, I do not need to have every value moved to a different location, and I don't have to move between the rows because of how the array is designed. Each row represents a suit and each column is a card score from 1 to 13. I tried looking at the shuffle
function on cplusplus website, but I don't really understand how the function prototype works. Is there anyway someone could help me shuffle these rows? I appreciate your help.
The reason I have it designed this way is because for my project I am required to use composition by having a class called Deck with two objects of a previous project's card game.
cardDeck[3][5] = {0,1,2,3,4} {0,1,2,3,4} {0,1,2,3,4};
is a smaller version of what my array is. But in my program I use a member function to fill the deck for me so I don't have to write out 52 items.
Upvotes: 2
Views: 2243
Reputation: 1
Please, keep in mind that I did not compile any of these codes, so there might be some errors on the code.
Here is how you can use std::shuffle
to shuffle elements in an arbitrary array:
#include <random>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <vector>
int main()
{
// STL functions that operate over range of elements usually take
// iterators as arguments, so your data must be in an iterable
// container, like std::vector or std::array
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// initialize random number generator engine
std::random_device rd;
std::mt19937 g(rd());
// first argument is an iterator to the beginning of the vector (v[0])
// second argument is an iterator to the end of the vector (v[v.size()-1])
// third argument is the rng engine
std::shuffle(v.begin(), v.end(), g);
for (auto i : v) {
std::cout << i << " ";
}
std::cout << "\n";
}
A possible outcome would be 8 6 10 4 2 3 7 1 9 5
.
Regarding your problem, here is how I would do it. In order to use std::shuffle
you need that your data is in a iterable container such as a std::vector
, so we need to convert your initial 2D array into a vector of vector of ints (std::vector<std::vector<int>>
). Once we have this, we can use std::shuffle
to shuffle the elements of each row. When we are done, we can simply copy back the elements to the initial 2D array, if we so wish.
#include <random>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <vector>
int main()
{
int cards[5][14];
// init cards...
std::vector<std::vector<int>> cardsVec;
for (int j = 0; j < 5; ++j) {
cardsVec.push_back(std::vector<int>(cards + j * 5, cards + j * 5 + 14));
}
std::random_device rd;
std::mt19937 g(rd());
// use a range-for it iterate over cardsVec
for (auto& row: cardsVec) {
std::shuffle(row.begin(), row.end(), g);
}
for (int j = 0; j < 5; ++j) {
for (int k = 0; k < 14; ++k) {
cards[j][k] = cardsVec[j][k];
}
}
}
Now, please keep in mind that you can do everything with just the vectors if you wish, the only reason I copied the contents of arrays to the vectors and back is that you mentioned using an array in your problem. Here is how it might look if we used only vectors instead of arrays:
#include <random>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <vector>
int main()
{
std::vector<std::vector<int>> cards;
cards.resize(5); // allocates 5 rows
for (auto& row : cards) {
row.resize(14) // allocates 14 cards in this row
}
// init cards as you would init the array version...
std::random_device rd;
std::mt19937 g(rd());
// use a range-for it iterate over cards
for (auto& row: cards) {
std::shuffle(row.begin(), row.end(), g);
}
// ...
}
Finally, C++ has an array
container as well. It is basically the same as flat arrays, with the addition of being safer and iterable, like vectors, and thus can be used directly in the STL functions that take iterators as arguments. Like flat arrays, the std::array
has a fixed size which must be know in compile time, so won't be allocating it like you would the vector.
#include <random>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <array>
int main()
{
// array of 5 arrays of 14 integers
std::array<std::array<int, 14>, 5> cards;
// init cards as you would init the array version...
std::random_device rd;
std::mt19937 g(rd());
// use a range-for it iterate over cards
for (auto& row: cards) {
std::shuffle(row.begin(), row.end(), g);
}
// ...
}
Upvotes: 0
Reputation: 206717
One way to do that would be:
5*14
.0
- 5*14-1
.Upvotes: 4