I have an application where it becomes extremely noticeable if my program uses an RNG that has patterns based on its seed, as it builds landscapes based on the x coordinate of the landscape. While Random
works well if you're calling Next()
every time, I need to be able to have the same output every time I use the same input, and thus can't rely on Next()
. Instead, I attempted to simply make a new Random
every time with the input seed. Not a very good idea, I know, and it showed. The patterns were extremely obvious, with alternating high and low values, and an noticeable overall trend across the entire landscape. I'd prefer not to be making new generators every time, but even so, I looked into the cryptographically secure RandomNumberGenerator
to see if I could at least use it temporarily. As expected, though, I can't seed it, leaving me without any sort of reproducible output (which is rather the point of the RandomNumberGenerator
).
In short, neither of the two common RNGs appear to suit my purpose. I need to be able to take in a a number and return a random number based on that value without noticeable patterns in the output. Is there another way to use the above two, or is there a third I haven't used before that would better suit my purpose?
For clarity, the method I'm trying to write looks like so:
public int RandomInt(int input)
{
int randomOutput;
//Be random
return randomOutput;
}
That will return the same value every time the same input
is given.
I hate to answer my own question, but a friend of mine made this suggestion off StackOverflow, and I feel that it'd be best to include it here for posterity.
What's being asked for is actually just a hashing function. If you run the input through a suitable strong hashing algorithm and convert the output to an int, random output values that correspond to their inputs will be generated.
If you are trying to make the output reproducible then you simply need to seed
Random
once with a fixed seed.You could make this seed another input in your program. That way you will know that the sequence of numbers returned by
Next
will be identical in two executions of your program (that use the same seed).You should definitely not reinitialize the random generator every time.
These two generators will always output the same results when
Next
is called. It does not matter where in the code they are declared. Or when. The only thing that matters is that theseed
(here 12) is the same.If you want another reproducible set of values, identical to the one that results from
rnd1
all you need to do is instantiaternd2
.A possible way seems to store
random.Next()
values for one run, and map them to each input. Have these values on a datastore, cache them on the next application run, and start serving them. In effect, you'll get the same random output given an input.Perlin Noise or newer Simplex Noise works well for landscape generation.
If I understand the algorithm correctly, it works by adding together noise gradients (linear interpolation between random points) of different frequencies. I also found a more detailed explanation.
I found a Simplex Noise library on Google Code,
And the implementation:
If you want 'same seed -> same num'. look at this.
This is very simple.
A
Mersenne Twister
might give better results.Here's a sample implementation that you should be able to try out fairly quickly: