I am working on an openGL project and my rand function is not giving me a big enough random range. I am tasked with writing a diamond program to where one diamond is centered on
As WhozCraig mentioned, seeding your random number generator with the time every time you call myDisplay (...)
is a bad idea. This is because time (NULL)
has a granularity of 1 second, and in real-time graphics you usually draw your scene more than one time per-second. Thus, you are repeating the same sequence of random numbers every time you call myDisplay (...)
when less than 1 second has elapsed.
Also, using modulo arithmetic on a call to rand (...)
adversely affects the quality of the returned values. This is because it changes the probability distribution for numbers occurring. The preferred technique should be to cast rand (...)
to float and then divide by RAND_MAX, and then multiply this result by your desired range.
GLfloat x = rand() % 50 + 10; /* <-- Bad! */
/* Consider this instead */
GLfloat x = (GLfloat)rand () / RAND_MAX * 50.0f + 10.0f;
Although, come to think of it. Why are you using GLfloat
for x and y if you are going to store them in an integer data structure 2 lines later?
This has no business being in this function:
srand(time(0));
This should be called once at the beginning of your program (a good place is just inside main()
); and most-certainly not in your display routine. Once the seed is set, you should never do it again for your process unless you want to repeat a prior sequence (which by the looks of it, you don't).
That said, I would strongly advise using the functionality in <random> that comes with your C++11 standard library. With it you can establish distributions (ex: uniform_int_distribution<>) that will do much of your modulo work for you, and correctly account for the problems such things can encounter (Andon pointed out one regarding likeliness of certain numbers based on the modulus).
Spend some time with <random>
. Its worth it. An example that uses the three ranges you're using:
#include <iostream>
#include <random>
using namespace std;
int main()
{
std::random_device rd;
std::default_random_engine rng(rd());
// our distributions.
std::uniform_int_distribution<> dist1(50,60);
std::uniform_int_distribution<> dist2(200,300);
std::uniform_int_distribution<> dist3(0,100);
for (int i=0;i<10;++i)
std::cout << dist1(rng) << ',' << dist2(rng) << ',' << dist3(rng) << std::endl;
return EXIT_SUCCESS;
}
Output (obviously varies).
58,292,70
56,233,41
57,273,98
52,204,8
50,284,43
51,292,48
53,220,42
54,281,64
50,290,51
53,220,7
Yeah, it really is just that simple. Like I said, that library is this cat's pajamas. There are many more things it offers, including random normal distributions, different engine backends, etc. I highly encourage you to check into it.