Generate a random number if the number matched with the previous - c#

I want to create a random number with a text in front of it, and I don't want the system displaying a number twice. So, this is that the way that I did it:
Random _rand = new Random();
private void RandomNumberGenerator()
{
int random = _rand.Next(10000);
string text = "TP0" + random;
if (random.Equals(random))
{
_rand.Next();
}
else
{
random = _rand.Next(10000);
}
MessageBox.Show(text);
}
I am not getting any displayed number twice (but I am not too sure, because I just close the program until it displayed the number 5 times (all of it are not the same number).
Is it possible from the above code to displaying a number twice with any chance?
Thank you.

EDITED to get rid of magic numbers and ensure sanity.
Random _rand = new Random();
HashSet<int> _taken = new HashSet<int>();
object _syncRoot = new object();
private int RandomNumberGenerator() {
lock (_syncRoot) {
const int MAX_NUMBER = 10000;
if (_taken.Count == MAX_NUMBER) {
throw new Exception("All possible numbers are already generated.");
}
int random = _rand.Next(MAX_NUMBER);
while (_taken.Contains(random)) {
random = (random + 1) % MAX_NUMBER;
}
_taken.Add(random);
return random;
}
}

Soner Gonul is correct, random.Equals(random) is always going to be true I think.
You could work around it (roughly) by having another int variable which will become whatever the last number generated was, then when the function goes into it's next cycle have it reference the new random number variable against the one stored in your second variable, which is the previous random number. That's one way of doing it, I can try define that a little clearer in a minute if you don't understand

Related

How to create 2 Random objects in 2 consecutive lines of code with different seeds?

I want to make 2 different Random objects in 2 consecutive lines of code. The parameterless constructer of the Random class is like this:
public Random()
: this(Environment.TickCount) {
}
It uses Environment.TickCount as the seed. TickCount represents the amount of time that has passed since the OS is switched on, right?
I tried the following:
Random r1 = new Random ();
Random r2 = new Random ();
And I found out that the 2 Random objects had the same seed because their Next methods return the same number each time. I was surprised by how fast a line of code can be executed. Then I tried:
long tick1 = Environment.TickCount;
for (int i = 0 ; i < 100000 ; i++) {
}
long tick2 = Environment.TickCount;
Console.WriteLine (tick2 - tick1);
And I get 0. So I iterated 100000 times and still, not even 1 millisecond has passed?
I just want to ask how can I create 2 different Random objects or is there another way to generate random numbers?
Base on #PankajMishra's answer, try this one:
//Function to get random number
private static readonly Random getrandom = new Random();
private static readonly object syncLock = new object();
public static int GetRandomNumber(int min, int max)
{
lock(syncLock) { // synchronize
return getrandom.Next(min, max);
}
}
lock block is effective when you use it in a multi-threading program, if you sure just one thread use it, so you can prevent lock to increase your code performance.
To me, it seems like an XY problem, because you don't need two separate Random instances - you can use the same one to generate all your random number, can't you? Just call Next again and that's it:
var rnd = new Random();
int firstRandomInt = rnd.Next();
int secondRandomInt = rnd.Next();
However, you really need 2 Random instances, you can use the first one to seed the second one:
var rnd = new Random();
var rnd2 = new Random(rnd.Next());

C# Random Image from Directory [duplicate]

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 7 years ago.
Consider this method:
private static int GenerateRandomNumber(int seed, int max)
{
return new Random(seed).Next(max);
}
On my machine, executing this loop yields the same number through 1500 iterations:
for (int i = 0; i < 1501; i++)
{
int random = GenerateRandomNumber(100000000, 999999999);
Console.WriteLine(random.ToString());
Console.ReadKey();
}
I get 145156561, for every single iteration.
I don't have a pressing issue, I was just curious about this behavior because .Next(max) says "Returns a Non Negative random number less than the specified maximum. Perhaps I am not understanding something basic.
You're always seeding a new instance with the same seed, and then grabbing the first max. By using a Seed, you're guaranteeing the same results.
If you want to have a static, random number generation that does different results, you should rework this a bit. However, since Random is not threadsafe, it requires some synchronization when used statically. Something like:
private static Random random;
private static object syncObj = new object();
private static void InitRandomNumber(int seed)
{
random = new Random(seed);
}
private static int GenerateRandomNumber(int max)
{
lock(syncObj)
{
if (random == null)
random = new Random(); // Or exception...
return random.Next(max);
}
}
Dilbert has encountered the same problem back in 2001:
http://dilbert.com/strips/comic/2001-10-25/
Coincidence?
I don't think so.
And random.org agrees : http://www.random.org/analysis/
The problem is that you are creating a new Random instance with the same seed number each time. You should create a single Random instance (store it in a static if necessary) and simply call the next method on that same instance.
Random number generation is not truly random, see this Wikipedia entry for more details.
Salam to All,
Well it drove me crazy as well. The answer is simple. Change the seed before you generate random.
Example:
I want to generate random number between 1 to 10
Random rnd = new Random(DateTime.Now.Second);
int random_number = rnd.Next(10);
Put it inside a loop and run it three times. It will give out random numbers below 10.
Pseudo-random number generator usually work by choosing a seed, and then generating a deterministic sequence based on that seed. Choosing the same seed every time, you generate the same sequence.
There are "only" 2^32 different random sequences in .NET.
Not sure how the internals work.. check wiki for it, but it's very simple.
public class MathCalculations
{
private Random rnd = new Random();
public Int32 getRandom(Int32 iMin, Int32 iMax)
{
return rnd.Next(iMin, iMax);
}
}
public class Main
{
MathCalculations mathCalculations = new MathCalculations();
for (int i = 0; i < 6; i++)
{
getRandom(0,1000);
}
}
will generate Number1, Number2, Number3, Number4, Number5, Number6 (1 seed, 1 sequence of many numbers, random*not really, but approx.*)
if you however do this:
public class MathCalculations
{
public Int32 getRandom(Int32 iMin, Int32 iMax)
{
Random rnd = new Random();
return rnd.Next(iMin, iMax);
}
}
public class Main
{
MathCalculations mathCalculations = new MathCalculations();
for (int i = 0; i < 6; i++)
{
getRandom(0,1000);
}
}
You will now get Number1, Number1, Number1, Number1, Number1, Number1 (1 seed, 6 equal sequences of many numbers, always pick the same starting number from each equal sequence).. At some point Number1 will be different, because the seed changes over time.. but you need to wait some time for this, nonetheless, you never pick number2 from the sequence.
The reason is, each time you generate a new sequence with the same seed, hence the sequence is the same over and over again, and each time your random generated will pick the first number in it's sequence, which, with the same seed, is of course always the same.
Not sure if this is technically correct by the underlying methods of the random generator, but that's how it behaves.
In the event that anyone is looking for a "quick and dirty" "solution" (and I use that term with caution) then this will suffice for most.
int secondsSinceMidnight = Convert.ToInt32(DateTime.Now.Subtract(DateTime.Today).TotalSeconds);
Random rand = new Random(secondsSinceMidnight);
var usuallyRandomId = rand.Next();
Please note my use of usually random. I agree that the item marked as the answer is a more correct way of doing this.

How can I ensure that same random numbers are not selected every time in C#?

I'm writing a trivia game player app in C#, where the user must pick 5 randomly selected trivia questions from a set of 20 available questions.
I use this code to generate an index that the app will use to fetch the questions:
private void GenerateRandomNumbers(int RandomIndex)
{
Random rand = new Random();
HashSet<int> check = new HashSet<int>();
for (int i = 1; i < RandomIndex; i++)
{
int curValue = rand.Next(1, RandomIndex);
while (check.Contains(curValue))
{
curValue = rand.Next(1, RandomIndex);
}
ChosenQuestions.Add(Questions[curValue]);
check.Add(curValue);
}
check.Clear();
}
The problem is that when the user plays the game a second time (by clicking the "PLAY AGAIN" button) and the above code is executed again, it keeps picking the same random numbers, though they are not necessarily in the same order. this causes the same trivia questions to be chosen every time. I want a fresh new set of totally random numbers every time the above code executes. How can I modify the code to accomplish this?
NOTE: I did copy this code from somewhere else here on Stack Overflow, so it's not my own original code.
Assuming RandomIndex is the number of values to pick. You want this:
rand.Next(1, RandomIndex);
to be
rand.Next(0, Questions.Length);
There is an off by one error in the loop as well. Let's just fix the whole thing:
private void GenerateRandomNumbers(int RandomIndex)
{
Random rand = new Random();
HashSet<int> check = new HashSet<int>();
for (int i = 0; i < RandomIndex; i++)
{
int curValue = rand.Next(0, Questions.Length);
while (check.Contains(curValue))
{
curValue = rand.Next(0, Questions.Length);
}
ChosenQuestions.Add(Questions[curValue]);
check.Add(curValue);
}
}
Also, if you call this in a tight loop, you will get the same values picked repeatedly. This because Random chooses a seed based on the system clock which only upadates every 15 ms or so.
I think that a shuffle would be better approach rather than checking whether indexes have already been picked.
You could seed RNG with different seeds
Random rand = new Random(newSeed);
Seed could be taken from current time, for example
Try using just one global Random object, and not creating a new Random() every time the user plays. This will ensure that isntead of initializing a new seed every time, the numbers will be a sequence created by one seed. This will make them closer to real randomness.

dont want a random number to show twice

I am trying to save random numbers in a list, the same number can not come twice.
It´s a BINGO game where this method is used to display ex B12, then the user hits enter and a new number will show. This will keep on until the user writes q.
This works, BUT the number can show up twice...
static void bingo()
{
Random rnd =new Random();
List<int> check = new List<int>();
string choice = "";
while (choice != "Q")
{
int number = rnd.Next(1, 76);
while (!check.Contains(number))
{
kontroll.Add(number);
}
if (number <=15)
{
choice = Interaction.InputBox("B" + number);
choice = choice.ToUpper();
}
else if(number <= 30)
etc.
Something like this should work (if I'm reading your question correctly)
Enumerable.Range(1,76).OrderBy(n => rnd.NextDouble())
There are a couple of ways to do this:
Keep track of what numbers have been "called" - if a number is in the list, pick a different one
Remove numbers that have been called from the original list, then pick a new one at random each time.
Sort the list of possible values by a random number and just work though the list
The easiest way to accomplish this is to use a HashSet.
var usedNumbers = new HashSet<int>();
...
int number;
do {
number = rnd.Next(1, 76);
} while (usedNumbers.Contains(number));
usedNumbers.Add(number);

Why am I getting strange results when generating Random() numbers?

My program needs to:
a. Generate an array of 20 random integers from zero to nine. Search for the first occurrence, if any, of the number 7, and report its position in the array.
b. Repeat the computation of part a 1000 times, and for each position in the array, report the number of times that the first occurrence of a 7 in the array is at that position
However whenever I run the program I get strange results (different every time) such as:
No sevens found at any position
1000 sevens found at one position and no sevens found anywhere else
Hundreds of sevens found in 2 positions, and none found anywhere else.
Does anyone have an idea what is wrong with my program?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Week_6_Project_2
{
class Program
{
static int intArrayLength = 20;
static int[] resultsArray = new int[intArrayLength];
public static Array generateRandomArray() {
int[] randomNumberArray = new int[intArrayLength];
Random random = new Random();
int popcounter = 0;
while (popcounter < intArrayLength) {
randomNumberArray[popcounter] = random.Next(0, 10);
popcounter += 1;
}
return randomNumberArray;
}
public static void searchForSevens()
{
int counter = 0;
int[] randomArray = (int[])generateRandomArray();
while (counter < intArrayLength)
{
if (randomArray[counter] == 7)
{
resultsArray[counter] += 1;
counter = intArrayLength;
}
counter += 1;
}
}
static void Main()
{
int searchCounter = 0;
while (searchCounter < 1000)
{
searchForSevens();
searchCounter += 1;
}
int displayCounter = 0;
while (displayCounter < intArrayLength)
{
Console.WriteLine("Number of first occurrence of 7 at position {0} = {1}", displayCounter, resultsArray[displayCounter]);
displayCounter += 1;
}
Console.ReadLine();
}
}
}
Your main problem is that each searchForSevens() test only takes a small fraction of time and the Random class uses auto-seeding from the clock. The clock however has a limited resolution. The result is that many (sometimes all) of your random sequences will be the same. And at most you will have 2 or 3 different result sets.
The simple fix for this single-threaded program is to use 1 static instance of Random.
You're instantiating a new instance of Random every time you call the generateRandomArray method. Since the random number generator uses the current time as a seed, instantiating two Random instances at the same time results in the same numbers being generated, which explains your unexpected results.
To solve your problem, you should only instantiate one Random instance, store it in private field, and reuse it every time you call the Next method.
The problem I assume stems from the fact, that Random() uses current time as seed. And the computation happens so fast, that each time new Random() is called, it uses same time. So you get same sequence of numbers.
To fix this, you simply need to set seed by yourself, incremmenting it every cycle should be enough.
long base = DateTime.Now.TotalMilliseconds;
Random rand = new Random(base+searchCounter);
.. something like that.
I will not answer but will try to give an analogy for the people that think that they need more then one Random instance...
Suppose that you need to fill 6 sheets of paper with random numbers from 1-6. Ask yourself this: do you need 6 dices or one to do the job? If you answer that you need more than one dice, ask yourself this: how different or more random is throwing different dice instead of same dice every time?
I mean, if you throw ONE on a dice, next throw of a dice won't have any less chance to be ONE again than it would be any other number. It goes against intuition, but it is mathematically and statistically so.
In your original code, you're calling the Random method in rapid succession [broken example based on OP's original code], thus seeding the method with the same number, resulting in duplicate "random" numbers. Creating a static member will ensure randomness simply because you're only creating a single instance of it.
Try creating a single static instance of random like this. [static member example].
static readonly Random Random = new Random();
Based on this, here's how I would solve your particular problem.
using System;
namespace Week_6_Project_2
{
class Program
{
// ******************************************
// THIS IS A SINGLE INSTANCE OF Random.
// read below as to why I'm seeding the instantiation of Random();
static readonly Random Random = new Random(Guid.NewGuid().GetHashCode());
// ******************************************
private const int IntArrayLength = 20;
static readonly int[] ResultsArray = new int[IntArrayLength];
public static Array GenerateRandomArray()
{
var randomNumberArray = new int[IntArrayLength];
var popcounter = 0;
while (popcounter < IntArrayLength)
{
randomNumberArray[popcounter] = Random.Next(0, 10);
popcounter += 1;
}
return randomNumberArray;
}
public static void SearchForSevens()
{
var counter = 0;
var randomArray = (int[])GenerateRandomArray();
while (counter < IntArrayLength)
{
if (randomArray[counter] == 7)
{
ResultsArray[counter] += 1;
counter = IntArrayLength;
}
counter += 1;
}
}
static void Main()
{
var searchCounter = 0;
while (searchCounter < 1000)
{
SearchForSevens();
searchCounter += 1;
}
var displayCounter = 0;
while (displayCounter < IntArrayLength)
{
Console.WriteLine("Number of first occurrence of 7 at position {0} = {1}", displayCounter, ResultsArray[displayCounter]);
displayCounter += 1;
}
Console.ReadLine();
}
}
}
Further reading about Random()
Beyond the answer above, sometimes it is necessary to seed Random(int); (I like to use the HashCode of a Guid) to ensure further randomness. This is because the default seed uses the clock which from the docs [microsoft] has a finite resolution. If your class is instantiated multiple times in quick succession (< 16ms), you will get the same seed from the clock... this breaks stuff.
[example of seeded Random(int) run in rapid succession with random results]
"using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers."
hear me when I say that you should NOT instantiate a new Random on every iteration of a loop -- use a static member
Another valid reason to implement your own seed is when you want to recreate a random sequence [example of two identical lists based on same seed]. Re-using the same seed will recreate the sequence since the sequence is based on the seed.
note: others might say that seeding it is not necessary [link], but I personally believe that for the additional few keystrokes and the microscopic hit on the clock, you might as well increase the probability of a unique seed. It doesn't hurt anything, and in some situations it can help.

Categories