1

I've got a random number generator function ("Rndom (min, max)"), and I have an int with 4 elements called "Data [3]". I used the for loop to generate numbers (1-4) to the elements of the "Data" int:

for (int i = 0;i < 3;i++)
{
    Data[i] = Rndom(1, 4)
}

How can I prevent that the data gets duplicated element number ? So, I don't want this: "Data" elements: 1 3 4 1 ("1" is duplicated). I want to make different numbers....

Thank you for the help !

2 Answers2

4

Since you want an array or vector of shuffled integer values, use std::shuffle to shuffle a vector (or whatever) initialized with sequential values.

#include <iostream>
#include <vector>
#include <random>
#include <algorithm>
#include <numeric>

int main() {
    std::random_device rd;
    std::mt19937 rng(rd());                       // seed rng using rd
    std::vector<int> data(3);                     // create a 3-entry vector
    std::iota(data.begin(), data.end(), 0);       // fill with sequence
    std::shuffle(data.begin(), data.end(), rng);  // mix entries using rng
    // dump the result
    for(auto r : data) { std::cout << r << ' '; }
    std::cout << '\n';
}

The outputs of 3 executions:

1 0 2

2 1 0

2 0 1

Here is a version which doesn't rely so much on the standard C++ library, and uses the C-runtime's crappy random number generator, just because I didn't have access to Rndom's source code, which is undoubtedly of a proprietary nature, so this is quite understandable:

#include <iostream>  // only for std::cout
#include <cstdlib>   // for srand, rand
#include <ctime>     // for time

namespace shuffle {
    using size_t = decltype(sizeof(1));

    bool Srndom() {
        std::srand(std::time(0));
        return true;
    }

    int Rndom(int low, int high) {
        static bool init = Srndom();
        return std::rand() % (high - low + 1) + low;
    }

    template <typename T>
    void Shuffle(T* pdata, size_t N) {
        for(size_t i=0; i<N-1; ++i) {
            const int swap_idx = Rndom(i, N-1);
            if(swap_idx != i) {
                const T t = pdata[i];
                pdata[i] = pdata[swap_idx];
                pdata[swap_idx] = t;
            }
        }
    }

    template <typename T, size_t N>
    void Shuffle(T (&data)[N]) {
        Shuffle(data, N);
    }

    template <typename T>
    void Series(T* pdata, size_t N, T start) {
        for(size_t i=0; i<N; ++i) {
            pdata[i] = start++;
        }
    }

    template <typename T, size_t N>
    void Series(T (&data)[N], T start) {
        Series(data, N, start);
    }
}

int main() {
    using namespace shuffle;

    int Data[4];     // I guess you actually want 4
    Series(Data, 1); // and maybe to start at 1.
    Shuffle(Data);   // Shuffle Data's entries.

    // Dump Data's entries
    for(size_t i=0; i<sizeof(Data)/sizeof(Data[0]); ++i) {
        std::cout << Data[i] << ' ';
    }
    std::cout << '\n';
}

The outputs of 3 executions (over 1 second apart):

2 3 1 4

4 2 3 1

2 4 3 1

Christopher Oicles
  • 3,017
  • 16
  • 11
  • lol you didn't used my function..... Bro, this is not a windows program.... I am programming a game which doesn't have such thing like "include vector....etc." – Vettel.Sebastian Jan 05 '17 at 21:03
  • 1
    Haha, you're funny. But I will go ahead and humor you with the answer you want, using my best guess at an implementation of `Rndom` and a statically-allocated array. Hang on... – Christopher Oicles Jan 05 '17 at 21:09
  • 1
    ***I am programming a game which doesn't have such thing like "include vector....etc."*** You tagged your question as `c++`. std::vector is part of the standard library in `c++`. – drescherjm Jan 05 '17 at 23:23
1

Use map or set to store the numbers generated and avoid duplication.

set<int> s;
for (int i = 0;i < 3;i++)
{
   int x;
   for(;;)
   {
      int x = Rndom(1, 4) ;

      if(s.find(x)==s.end()) 
      {
         s.insert(x);
         Data[i]=x;
         // consider it ..it is not duplicate
         break;
      }
   }
}

Also you can use set or unordered_set to realize the same thing.

The reason of using set over map is std::sets contain only the key, while in std::map there is an associated value.

user2736738
  • 30,591
  • 5
  • 42
  • 56