-2

i am making a horse racing game. Every 500ms i display the race lanes and add a random position between 1-4 to every horse, but it seems like almost everytime 5 wins, its like a 70%.

The same on another game named roullete, the average number that gets picked is 11.

I am using Mersenne Twister generator and this is the method i am using:

int random(int a, int b)  {
    static std::random_device rd;
    static std::mt19937 generator(rd());
    std::uniform_real_distribution<> distribution( a, b );
    return distribution(generator);
}

any tips on making the numbers even more random?

stephan
  • 9
  • 3
  • Why aren't you using `std::uniform_int_distribution` ? https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution – Richard Critten Dec 03 '21 at 19:26
  • Why are you using a `uniform_real_distribution` to create a random integer? – Nathan Pierson Dec 03 '21 at 19:26
  • You should use https://www.cplusplus.com/reference/random/uniform_int_distribution/ – Pepijn Kramer Dec 03 '21 at 19:27
  • Also the distributions have an internal state you should not be creating and destroying them every call to `random` see `std::uniform_int_distribution::reset` https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution/reset – Richard Critten Dec 03 '21 at 19:28
  • Please read [ask] with a [mcve]. – Richard Critten Dec 03 '21 at 19:30
  • Simplify the problem by just calling `random` a bunch of times and looking at the values that it returns. If the result looks suspicious (it probably will), post **that code**. – Pete Becker Dec 03 '21 at 19:31
  • @PepijnKramer one issue, number goes to -1882470725 everytime – stephan Dec 03 '21 at 19:33
  • Is it really necessary to maintain a persistent distribution? For instance is [this](https://stackoverflow.com/a/21238187/12334309) accepted answer incorrect? – Nathan Pierson Dec 03 '21 at 20:01
  • I wouldn't say it's great, especially if you're calling that function in a loop. Granted, I don't think a function like that is necessary at all. Keep your PRNG somewhere that's accessible for the lifetime of your program. When you need a range, that's where you instantiate your distribution. Joining the two together in a function is limiting. – sweenish Dec 03 '21 at 20:17

1 Answers1

0

As Richard said, you will need to keep the instance of the distribution around as long as a and b don't change. So best wrap that state in a class, after that the distribution of numbers is fine. This is the output for 100000 numbers from the example below.

value : 1, occured 24911 times
value : 2, occured 25044 times
value : 3, occured 25012 times
value : 4, occured 25033 times

#include <array>
#include <random>
#include <iostream>

// wrap your number generation in a helper class so it can maintain state.
class random_t
{
public:
    // initialize generator and distribution
    random_t(const int min, const int max) :
        m_generator{ std::random_device{}() },
        m_distribution{ min,max }
    {
    }

    // get next random number
    int operator()()
    {
        return m_distribution(m_generator);
    }

private:
    std::mt19937 m_generator;
    std::uniform_int_distribution<int> m_distribution;
};

// run random generator and create a histogram
int main()
{
    random_t random(1, 4);
    std::array<int, 5> histogram{};

    for (std::size_t n = 0; n < 100000; ++n)
    {
        auto value = random();
        //std::cout << value << " ";
        histogram[value]++;
    }

    for (std::size_t n = 1; n < 5; ++n )
    {
        std::cout << "value : " << n << ", occured " << histogram[n] << " times\n";
    }

    return 0;
}
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19