Random Unique Values and Arrays

Hello everyone,
I've been working with arrays, and brushing up on my C++ skills while attempting to solve previously difficult problems. One issue I encountered is trouble with randomized unique values, while replacing redundant values.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <time.h>
#include <windows.h>
#include <iostream>

using namespace std;

//random function to return numbers in specific range
int random(int low,int high)
{
    //sample usage: die1=random(1,6);
    return rand()%(high-low+1)+low;
}

int main()
{
    int array[10];//declare array of 10 int values
    srand(time(NULL));//set random # seed

    for (int i=0;i<10;i++)
    {
        array[i]=random(0,9);
        for (int y=0;y<10;y++)
        {
            if (array[i]==array[y])
            {//repeat outer loop when duplicate value is found
                i--;
                break;
            }
        }
    }
    //output values
    for (int i=0;i<10;i++)
        cout<<array[i]<<endl;

}//end of main 


I tried perusing the existing forum threads about this topic, and adapting the code there to my needs, but it just hangs and doesn't give any output. Perhaps I am approaching this issue incorrectly, but any help would be appreciated. After solving this problem, then the code could be adapted to fit a variety of purposes. Thanks.
Last edited on
If you're generating 0-9 in an array size 10, this is a horrible way of doing it. My preferred method would be to declare the array and put in number 0 - 9 (just fill it with a loop or something). Then, to randomly swap elements around a few times and then you have a randomized array with unique numbers! Here is an example of a shuffle I wrote for to help someone else. This particular example shuffles an array with exactly two of each value, but it's easy enough to adapt it to your needs.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <ctime>
#include <random>

int main()
{
    srand(time(NULL));
    int n[16] = {1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8};
    int x = 0, y = 0, z = 0, swaps = 0, temp = 0;
    swaps = rand() % 10 + 10; //Number of random swaps we are going to do.
    while(x < swaps)
    {
        y = rand() % 16;
        temp = n[y];
        z = rand() % 16;
        n[y] = n[z];
        n[z] = temp;
        ++x;
    }
    for(x = 0;x < 16;++x)
    {
        std::cout << n[x] << "\n";
    }
    return 0;
}


Edit: And why o why are you including the massive header file <windows.h> ? <cstdlib> or <random> is standard to include for rand() function.
Last edited on
Hi Mats,
Eventually I intend to work with much larger arrays and values, but wanted to get the concept working correctly in the first place. For instance, a card game may use 52 values to represent each card, but no value can be repeated twice. Still, sorting has it's uses, but it seems a shame to have to initialize the values into place and then swap them around. Isn't there a better way? I also tried another approach, but with similar results as the previous attempt. I left the random function out of this sample of code, as it is the same as above.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int main()
{
    int array[10],num;//declare array of 10 ints and int num
    bool unique=true;
    srand(time(NULL));//set random # seed

    for (int i=0;i<10;i++)
    {
        do
        {
            num=random(0,9);
            for (int i2=0;i2<i;i2++)
            {
                if (array[i2]==num)
                {
                  unique=false;
                  break;
                }

            }
        } while (!unique);
        array[i]=num;
    }

    for (int i=0;i<10;i++)
    {
        cout<<array[i]<<" ";
    }
}//end of main 


Still, I see your point that swapping values assigned to the array (by initialization or a loop) can accomplish much of what I was attempting. Mostly I just wanted to tackle how to scan for and replace redundant values when generated in this thread, and both attempts at doing this seem to hang instead of behaving as expected. As far as the included libraries, I didn't include the functions I didn't use in this case that rely on the other libraries, and forgot to remove them from the code when copying to the forum.
Last edited on
For shuffling a deck of cards, a shuffle is still much better as it takes less time on average. Anyway, here is the method you were trying to sort out (I did it for 52 elements, like a deck of cards would have).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include<iostream>
#include <ctime>
#include <random>

int main()
{
    srand(time(NULL));
    int n[52] = {0}; //The array of 'cards' 
    int x = 1, y = 0, z = 0;//Make sure x = 1 so we can do the first generation outside the loop. 
    n[0] = rand() % 52 + 1; //Do not need to do anything with the first number as it is assured to be unique.
    do
    {
        n[x] = rand() % 52  + 1;
        y = 0;
        while(y < x) //Iterate through the array to see if the number already exists in the array. 
        {
            if(n[y] == n[x])//If this number already exists in the array.
            {
                --x; //Generate this number again.
                break;
            }
            ++y;
        }
        ++x;
    }while(x < 52);
    for(x = 0;x < 52;++x) //Output the array.
    {
        std::cout << n[x] << "\n";
    }
    return 0;
}


but it seems a shame to have to initialize the values into place and then swap them around. Isn't there a better way?


If by better, you mean faster, then I haven't seen the method (and would be very interested if someone could show me it).
Still, with such small amounts of shuffles, both methods seem fast, because processors are fast. If many randomizations are required though, iterating along the array each time to find duplicates becomes noticeably slower.
Last edited on
Hi Mats,
I tried adapting the code sample above, but get unexpected behavior again. The sort seems to work, but I wind up with large values that shouldn't be in the array, and sometimes the program hangs.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
int main()
{
    int array[52]={0},num;
    int x=1,y=0;
    srand(time(NULL));//set random # seed

    array[0]=rand()%52+1;

    do
    {
        array[x]=rand()%52+1;
        y=0;
        while (y<x)
        {
            if (array[y]==array[x])
            {
                --x;
                break;
            }
            ++y;
        }
        ++x;
    } while (x<52);

    for (x=0;x<52;x++)
    {
        cout<<array[x]<<" ";
        if (x%13==0)
            cout<<endl;
    }
}//end of main 


EDIT: I forgot to adapt the array size to the full deck of 52 cards (duh!). After doing so, the program works perfectly. Thanks for the replies and feedback. There was one minor issue with this code, though.Despite the fact that I used "(x%13==0)" to determine when to go to the next line when outputting values (line 28), the first value always showed up alone on it's own line and I couldn't pinpoint why at first. However, adding 1 to x in this condition solved that problem, and with a bit more experimentation I made further modifications and wound up with the following code that ensures correct spacing and output.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
int main()
{
    int array[52]={0};//array of cards
    int x=1,y=0;//ensure x is 1 so that first number is generated outside of loops
    srand(time(NULL));//set random # seed

    array[0]=rand()%52+1;//first number assigned

    do
    {
        array[x]=rand()%52+1;//value generated for x's position
        y=0;
        while (y<x)
        {//iterate through array while checking for duplicate values
            if (array[y]==array[x])
            {//if duplicate is found, generate another value for this position
                --x;
                break;
            }
            ++y;//increment y to check additional array positions
        }
        ++x;//increment x to assign values to additional array positions
    } while (x<52);//continue loop until whole deck is assigned
    //formatted output
    for (x=0;x<52;x++)
    {
        cout<<array[x]<<" ";
        cout<<((array[x]<10) ? " " : "");//add additional space for single digit values
        cout<<(((x+1)%13==0) ? "\n" : "");//go to next line after each set of 13 values
    }
}//end of main 

Sample Output:
49 47 39 52 41 33 31 17 24 30 12 45 7
37 6  4  3  38 44 16 18 35 51 1  26 48
25 19 14 43 13 27 46 9  21 11 42 50 34
29 8  22 28 23 15 32 36 5  10 40 20 2  
Last edited on
Topic archived. No new replies allowed.