Search code examples
c++functionrandomgenerator

random number generator that doesn't repeat it self (cpp/c++)


I want to make a function that generates numbers but doesn't repeat it self. If every number is generated the array can be emptied and it can start over again.

This is the code I made but it doesn't work. The comments in the code explains the code a little. The largest number that is allowed is "howManyWords". This is used to display words which are stored in an array

I want to use it like this: array\[random()\]

#include <stdio.h>
#include <iostream>
#include <string>
#include <stdlib.h>

using namespace std;
//public scope
int howManyWords; // how many words you have enter

int random(){
    int random;
    int numbers[howManyWords];
    srand(time(0)); //changing the algorithm
    random = rand() % howManyWords;
    numbers[random] = random; // store the digit in the position in the array equal to the digit that is generated
    for(int i=0; i<howManyWords; i++){ // going through every element in the array
        if(numbers[i] == random){ // if the number is already generated, generate a different number
        random = rand() % howManyWords;
        }
    }
    return random;
}

Solution

  • Rather than your function, which discards the state of which numbers it has returned each time it is called, you should use a function object.

    struct random_t {
        random_t(int max) : values(max), current(max) {
            std::iota(values.begin(), values.end(), 0); 
        }
    
        template<typename URBG = std::random_device &>
        int operator()(URBG&& urbg = default_random) {
            if (current == values.size()) { 
                shuffle(std::forward<URBG>(urbg));
            } 
            return values[current++]; 
        }
    private:
        template<typename URBG>
        void shuffle(URBG&& urbg) { 
            std::shuffle(values.begin(), values.end(), std::forward<URBG>(urbg));
            current = 0; 
        }
    
        std::vector<int> values;
        std::vector<int>::size_type current;
        static thread_local std::random_device default_random;
    };
    

    See it live