Reputation: 1
I have been looking online without any luck.
Can one rearrange/shuffle elements in a 2d array randomly? How about a 2d array made of Objects? The 2d array is located in a constructor. The 2d array contains object elements. These elements will be replaced by 'card face' objects. I already have made a class of 'card face' objects, that I duplicated and put inside of a 2d array. Each card face has a pair/match in the array. I thought it easier to loop the card object and their copy into the array to replace each element, then shuffle the array afterward.
SO that example...
[[ AH, AH, 2C],
[ 2C, 3D, 3D],
[ 4S, 4S, X]]
would become...
[[ 2C, AH, 2C],
[ AH, 3D, 4S],
[ 4S, 3D, X]]
?
Upvotes: 0
Views: 283
Reputation: 1045
If we assume the objects we are trying to change are of type std::string, then we can use the approach shown below. The methods used for randomizing the order of your elements are templates, so they should work with the type of your choice.
#include <iostream>
#include <string>
#include <random>
template <typename T> void swap(T* a, T* b) {
T temp = *a;
*a = *b;
*b = temp;
}
// Shuffle the old fashioned way
template <typename T> void randomize(T arr[], size_t n) {
if (n == 0)
return;
srand((unsigned)time(NULL));
for (size_t i = n - 1; i > 0; --i) {
size_t j = rand() % (i + 1);
swap(arr + i, arr + j);
}
}
// Shuffle the c++11 way
template <typename T> void randomize_c11(T arr[], size_t n) {
if (n == 0)
return;
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(arr, arr + n, g);
}
template <typename T> void print_array(T arr[], size_t rows, size_t cols) {
std::string indent = " ";
std::cout << "[" << std::endl;
for (size_t row = 0; row < rows; ++row) {
std::cout << indent << "[";
for (size_t col = 0; col < cols; ++col) {
if (col != 0)
std::cout << ", ";
std::cout << *(arr + row*cols + col);
}
std::cout << "]" << std::endl;
}
std::cout << "]" << std::endl;
}
int main()
{
std::string array[4][3] = { { "AH", "AH", "2C"},
{"2C", "3D", "3D"},
{"AAAA", "BBB", "CC"},
{"4S", "4S", "X"} };
// Convert to 1d array (a pointer)
std::string* array2 = (std::string*)array;
// Calculate the size of the array
size_t count = sizeof(array) / sizeof(array[0][0]);
size_t rows = sizeof(array) / sizeof(array[0]);
size_t cols = count / rows;
// Show the 1d-array before sorting
print_array((std::string*)array, rows, cols);
// Shuffle the array the old fashioned way
randomize(array2, count);
// You can use the variable array directly and avoid using the variable array2:
// randomize((std::string *)array, count);
// You can also do it using the C++11 way:
// randomize_c11((std::string *)array, count);
// Show the array after sorting
print_array((std::string*)array, rows, cols);
return 0;
}
Here is an example of running the program:
Note that the old fashioned way of randomizing using rand() isn't optimal. See:
Pseudo-random number generation in C++
std::random_device
And for shuffling see also:
std::random_shuffle, std::shuffle
Upvotes: 1
Reputation: 229
Just mentally unroll the array into 1D, then randomize it like any other:
Pick a random number n between 0 and num_items-1
Copy from the first index to index n in the output array
Pick another random number from a range 0 to num_empty_slots -1 (so 1 lower than before)
Count empty slots from the beginning of the array to the end and copy to the n'th empty slot.
Go back to 3
You don't actually need steps 1 and 2 because 3-5 covers every case, but I included them to make it more intuitive.
Upvotes: 0