How to resolve an "IndexOutOfRange exception" error? [duplicate] - c#

This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 6 years ago.
I can't understand what's wrong.
static int WinningColumn()
{
Random rnd = new Random(46);
int[] winningnumbers = new int[6];
int[] Check = new int[46];
int i;
for (i = 0; i < winningnumbers.Length; i++)
{
winningnumbers[i] = rnd.Next(46);
Check[winningnumbers[i]]++;
if (Check[winningnumbers[i]] > 1)
{
i--;
continue;
}
The error happens here:
}
return winningnumbers[i];
}

When you exit from the for loop the indexer variable i has a value bigger than the max index possible (It is the condition that breaks the loop).
In your case the variable i has the value of 6 but the max index possible for the array winningnumbers is 5. (0 to 5 are six integer elements).
It is not clear what is your intent but supposing that your purpose is to generate six winning numbers ranging from 0 to 45 then your code should be rewritten and simplified in this way
static List<int> WinningColumn()
{
// Do not initialize Random with a fixed value
// You will get always the same 'random' sequence
Random rnd = new Random();
// Create a list to store the winners
List<int> winningnumbers = new List<int>();
int i = 0;
while(i < 6)
{
int newNumber = rnd.Next(46);
if(!winningnumbers.Contains(newNumber))
{
// If the list doesn't contain the number the add it and increment i
// Otherwise run the loop again....
winningnumbers.Add(newNumber);
i++;
}
}
// This returns the whole list to the caller,
// you can use it as an array
return winningnumbers;
}
Notice that your actual code contains a bug in the declaration of the Random number generator. You pass an initial seed and thus, everytime you call this method, the random generator starts again with the same sequence of numbers. The result would be an identical list of numbers. Not very random to me
If you don't pass anything then the generator is initialized with the system time and thus should be different every time you call this method.

I don't know what you want to achieve here.
But the loop would terminate when i becomes 6.
So you are basically trying to access winningnumbers[6] which is incorrect since winningnumbers array has length 6 so you can use index from 0 till 5.
You may try with winningnumbers [i-1]

Related

C# - Foreach Loop working when walking through code, but does not when run [duplicate]

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 4 years ago.
I have a list of a custom class, (called enemy), named enemyList. I use a foreach loop. Inside, I generate a random number between 1 and 200,000. Then I save it to a list outside of the foreach loop:
try
{
List<int> randoms = new List<int>();
foreach (enemy m in enemyList)
{
Random r = new Random();
int i = r.Next(1, 2000);
randoms.Add(i);
}
Then, when that is done, under the foreach loop, I do this:
int highest = randoms.Max();
int rate = -1;
Next, I use another foreach loop to figure out which value in randoms equals the highest number.
foreach (int number in randoms)
{
rate++;
if (highest == number)
{
return rate;
}
}
}
catch (Exception)
{
return 0;
}
When I run it, it displays which item is the highest, (example: if it is the first in the randoms list, then display 0). But for some reason, it always returns 0. But if I walk through the code, it works properly. Can anyone explain why this happens so I can fix it?
Are you trying to select a random item from your enemies list?
If so, you could just do something like this:
var rng = new Random();
var randomEnemy = enemyList[ rng.Next( enemyList.Count ) ];
If you are doing this rapidly you would want to declare your random number generator somewhere else so it isn't reseeding and constantly selecting the same value.

Fill an array with unique random integers [duplicate]

This question already has answers here:
Randomize a List<T>
(28 answers)
Closed 5 years ago.
I want to fill a small array with unique values from a bigger array. How do I check the uniqueness?
Here's what I have:
int[] numbers45 = new int[45];
for (int i = 0; i <= 44; i++) // I create a big array
{
numbers45[i] = i + 1;
}
Random r = new Random();
int[] draw5 = new int[5]; //new small array
Console.WriteLine("The 5 draws are:");
for (int i = 1; i <= 4; i++)
{
draw5[i] = numbers45[r.Next(numbers45.Length)]; //I fill the small array with values from the big one. BUT the values might not be unique.
Console.WriteLine(draw5[i]);
}
There are multiple ways to do what you are asking.
First off, though, I would recommend to use one of the classes which wraps the array type and adds some extra functionality you could use (in this case a List would probably be a perfect structure to use)!
One way to handle this is to check if the value is already in the draw5 array. This can be done with (for example) the List<T>.Contains(T) function, and if it exists, try another.
Personally though, I would probably have randomized the first array with the OrderBy linq method and just return a random number, like:
numbers45.OrderBy(o => random.Next());
That way the numbers are already random and unique when it is supposed to be added to the second list.
And a side note: Remember that arrays indexes starts on index 0. In your second loop, you start at 1 and go to 4, that is, you wont set a value to the first index.
You could just run for (int i=0;i<5;i++) to get it right.
Inspired by Jite's answer, I changed to use Guid to randomize the numbers
var randomized = numbers45.OrderBy(o => Guid.NewGuid().ToString());
Then you could take the draws by:
var draws = randomized.Take(5).ToArray;
HashSet<int> hs = new HashSet<int>();
int next = random.next(45);
while(hs.Length <=5)
{
if(!hs.Contains(array[next]))
hs.Add(array[next]);
next = random next(45);
}

how to create a random int[] [duplicate]

This question already has answers here:
Most efficient way to randomly "sort" (Shuffle) a list of integers in C#
(13 answers)
Closed 5 years ago.
I need to create a random array of int with certain parameters.
int[] test = new int[80];
Random random = new Random();
I need to assign 1's and 0's, randomly to the array. I know how to do that.
test[position] = Random.Next(0,2);//obviously with a for loop
But I need to have exactly 20 1's, but they need to be randomly positioned in the array. I don't know how to make sure that the 1's are randomly positioned, AND that there are exactly 20 1's. The rest of the positions in the array would be assigned 0.
I think you need to turn your thinking around.
Consider:
var cnt = 20;
while (cnt > 0) {
var r = Random.Next(0, 80);
if (test[r] != 1) {
test[r] = 1;
cnt--;
}
}
Expanding explanation based on comments from CodeCaster. Rather than generate a random value to place in the array, this code generates and index to set. Since C# automatically initializes the test array to 0 these values are already set. So all you need is to add your 1 values. The code generates a random index, tests it to see if it isn't 1, if so it sets the array element and decrements a count (cnt). Once count reaches zero the loop terminates.
This won't properly function if you need more values than 0 and 1 that is true. Of course the questions explicitly stated that these were the needed values.
"This causes horrible runtime performance". What!? Can you produce any prove of that? There is a chance that the index generated will collide with an existing entry. This chance increases as more 1's are added. Worst case is there is a 19/80 (~23%) chance of collision.
If you know you need exactly 20 of one value, a better way to go about this is to pre-populate the array with the required values and then shuffle it.
Something like this should work:
int[] array = new int[80];
for (int i = 0; i < 80; i++)
{
int val = 0;
if (i < 20)
{
val = 1;
}
array[i] = val;
}
Random rnd = new Random();
int[] shuffledArray = array.OrderBy(x => rnd.Next()).ToArray();
You can do
for (int i = 0; i < 20; i++)
{
var rand = random.Next(0,80);
if (test[rand] == 1)
{
i--;
continue;
}
test[rand] = 1;
}
Remaining are automatically zero.

Generate random numbers from 1 to 6 and stop at the last one

I have the following code :
int GetRandNumber()
{
Random r = new Random();
return r.Next() % 6 + 1;
}
I am developing a windows store app. I have a textbox in which a single number from 1 to 6 is generated. For every number I have made a specific event. I need to make sure that every number is generated only once so that the events do not repeat.
Looks like you just need to shuffle numbers. I'd suggest to create an array of numbers from 1 to 6 and just shuffle the array. You can see some code here for how to shuffle an array/list.
First of all you need to be careful with this implementation, if you call GetRandomNumber() multiple times very close together it will give you the same result. A better function would be
int GetRandNumber(Random r)
{
return r.Next(1, 7); //This does the same as "r.Next() % 6 + 1" but removes bias.
}
//used like
Random rand = new Random();
foreach(var foo in bar)
{
//The same instance of rand is used for each call instead of a new one each time.
foo.SomeProp = GetRandNumber(rand);
}
However that is completely separate from what you need to do, you should not be generating random numbers between 1 though 6. What you need to do is make a list of 1 though 6 then shuffle the list, not use random numbers at all (well you will likely use them during the shuffle but that is a implementation detail)
List<int> numbers = new List<int>();
for(int i = 1; i <= 6; i++)
{
numbers.Add(i);
}
MyShuffleListFunction(numbers);
There are plenty of examples on this site on how to make a shuffle function.
Maybe I'm wrong, but as I understand you want something like this as an output:
344213266125
To achieve this you should keep track which numbers are already generated, and stop if all has been "rolled" at least once.
So let's have a bool array initialized to 6 false values, and after each random number generation (after each roll) set the array's corresponing element to true. Check if there are any false values in the array, if not then "roll again".
Also, you might consider generating the numbers according to the other answers, as they are of course right: this is not an ideal way.
Update
Okay, based on your question's update I also update my pseudocode (or maybe I should call this prose):
Keep track of the already "rolled" numbers (as above). When generating a new number check if it has been already generated or not. If it's been rolled before, then roll again, until you roll a new one: then update the array accordingly. Also be sure to check if there is a valid number or all has been rolled before at the beginning of the roll...
But now it seems for me that what you really are looking for is simply a shuffle, which has been proposed in other answers.
Perhaps this will work for you. The approach is to record the random results in a List and to skip the output if the results already exists in the list.
class Program
{
static int tmp;
static void Main(string[] args)
{
List<int> alreadyFired = new List<int>();
while (alreadyFired.Count != 6)
{
Random rng = new Random();
int diceresult = rng.Next(1,7);
foreach (var item in alreadyFired)
{
if (item == diceresult)
{
tmp = item;
}
}
if (!(tmp == diceresult))
{
alreadyFired.Add(diceresult);
Console.WriteLine(diceresult);
}
}
Console.WriteLine("no events left");
Console.ReadKey();
}
}

How random function inside random class generates an integer? [duplicate]

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 9 years ago.
I have an array of strings that I want to pick one variable randomly from the list. Although I am using random function but I would like to know whether it will pick value zero ever or not? (Element zero from my array)
string randomString = a[new Random().Next(a.Length)];
Random should be random, so getting an A should be Random
One thing to note is if you're calling
string randomString = a[new Random().Next(a.Length)];
in quick succession e.g. in a loop, then create a class field, else Next() will be the same.
private Random _random = new Random();
then in your function call
string randomString = a[_random.Next(a.Length)];
The Random class simply uses pseudorandom number generation to give you a number that fits your specifications and seems random. Your code is fine, but with (in theory) 26 possible results, getting one of them shouldn't occur too often.
I believe the issue you're experiencing is that you're creating new Random objects in a loop, and they're ending up with the same seed, try declaring it in your class:
Random rnd = new Random();
And using it like so:
string randomString = a[rnd.Next(a.Length)];
The benefit of using this (as opposed to your current method) is that if you run it inside a loop you don't risk getting the same answer multiple times in a row.
Hope this helped, cheers!
~Winderps
How can you say rarely?
try this:
String[] myArray = new String[] { "A", "B", "C" };
Random rd = new Random();
Int32 aCounter = 0;
Int32 bCounter = 0;
Int32 cCounter = 0;
for (int i = 0; i < 25000; i++)
{
Int32 retVal = rd.Next(myArray.Length);
switch (retVal)
{
case 0:
aCounter++;
break;
case 1:
bCounter++;
break;
case 2:
cCounter++;
break;
}
}
As expected in my test, as expected aCounter, bCounter and cCounter always have same values between 8000 and 8500.
Perahps you called your new Random().Next() too soon use a single object Random and call Next() each time on the same object

Categories