C# WinForm Enum ToString - c#

// in general i take random colors from an Enum and insert that into a new array.
when i ask by BoxMessage inside the loop For each Array[i] i get random colors as expected.
If i comment (\) the message box and ask for Array[1-5] outside the loop, i get the same color for all 5 message box.
I believe it related to the fact that my message box inside the loop successfully convert the Enum into a string, when i tried to convert the whole array in the loop ( array[i].ToString(); ) it didn't quite work.
please advise....
public void GetArray()
{
array = new EnumColor[5];
for (int i = 0; i < 5; i++)
{
rnd = new Random();
int rndnum = rnd.Next(0, 4);
array[i] = (EnumColor)rndnum;
MessageBox.Show(array[i].ToString());
}
MessageBox.Show(array[0].ToString());
MessageBox.Show(array[1].ToString());
MessageBox.Show(array[2].ToString());
MessageBox.Show(array[3].ToString());
MessageBox.Show(array[4].ToString());
}

for (int i = 0; i < 5; i++)
{
rnd = new Random();
int rndnum = rnd.Next(0, 4);
array[i] = (EnumColor)rndnum;
MessageBox.Show(array[i].ToString());
}
You're overwriting elements in the array, don't do this.
Retrieve elements into a temporary local variable instead (and use .Length instead of a hardcoded length)
The bug itself is caused by Random being incorrectly seeded, it's being regerated on every iteration.
Random rnd = new Random();
for (int i = 0; i < array.Length; i++)
{
int rndnum = rnd.Next(0, 4);
EnumColor selected = (EnumColor)array[i];
MessageBox.Show( selected .ToString() );
}

You are getting the same color because you are declaring random instance each time in your loop, just move the declaration outside:
rnd = new Random();
for (int i = 0; i < 5; i++)
{ ... }
If you like to learn more about why Random class works that way you can take a look at this answer.

The problem is indeed the Random being re-created for every loop. But here's the full explanation.
When you create a Random, it uses the Environment.TickCount as seed value. (milliseconds since system startup). So if your loop is fast enough, this will always be the same value, so the rnd.Next function will always return the same value.
So now for the tricky part.. why did it work with the messagebox inside the loop? By showing the message, the loop became slower by waiting for you clicking the ok button. Therefore the next loop, the seed was indeed changed. That's why you got another value.

Related

C# - Random output from array to textbox

I'm kinda new to array and I made a char array (with 174 things in it) but I don't know how to output it in a randomize way. I'm trying to make a secured code for my system. I wanted to output 13 char from that 174 char array into a textbox, but I don't think I get the logic. Thank you in advance! Here is the code that only outputs 1 char per button click:
Random rnd = new Random();
int randomnum = rnd.Next(0, 174);
for (int x = 0; x <= 13; x++)
{
textBox11.Text = chararray[randomnum];
}
Your code is almost there, but there are a few issues:
You need to append the new character to the end of the string as apposed to just setting the Text value directly. You can do this easily with += instead of =.
You need to pick a different random character for each iteration of the loop, so move your call to .Next inside the for.
Putting this together you'd have something like this:
Random rnd = new Random();
for (int x = 0; x <= 13; x++)
{
int randomnum = rnd.Next(0, 174);
textBox11.Text += chararray[randomnum];
}
Note however, that if this is for the purpose of security, using Random isn't great. You should probably use something like the RNGCryptoServiceProvider. For example:
using (var rng = new RNGCryptoServiceProvider())
{
byte[] password = new byte[10];
rng.GetBytes(password);
textBox11.Text = Convert.ToBase64String(password).Remove(13);
}
I've attached a screenshot of this code working. I had a small typo
This will change the seed for random
int seed = 1;
Create an instance of Random, we don't need to recreate it every time we need to use it
Random r = new Random(seed);
This only initializes the characters
char[] _myChars = new char[170];
for(var i = 0; i < _myChars.Length; i++)
{
_myChars[i] = (char)(i%26 + 65);
}
This is the query you're looking for, it will query the characters and order them by a random order with r.Next()
var output = _myChars.OrderBy(o => r.Next()).Take(13).ToList();
This is only for displaying the output, you would want to use the output in your textbox
for(var i = 0; i < output.Count; i++)
{
Console.WriteLine(output[i]);
}
Console.ReadLine();

Copy odd numbers from array into another array

Im new to programming and struggling with this task:
In array X [20] random numbers from 1 to 30 are entered, in array Y enter only odd numbers from array X.
Print down Y.
int[] x = new int[20];
Random rnd = new Random();
int counter = 0;
int[] y;
for (int i = 0; i < x.Length; i++)
{
x[i] = rnd.Next(1, 30);
if (x[i] % 2 !=0 )
{
y = new int[counter];
counter++;
y[counter] = x[i];
}
}
foreach (int number in y)
{
Console.WriteLine(number);
}
Im having problems to fill Y array with odd numbers without defining length of Y, I tried with adding counter but getting some errors all the time,
If someone can help me with some suggestions that would be helpful, thank you!
This looks like homework, so I guess using a more appropriate collection such as a List<int> is out of the question, just as using Linq.
At y = new int[counter]; you're reinitializing the array. This happens each iteration, so your final array only holds the latest added value, and all values before that will be set to their default: 0.
You could've seen this by debugging your code by setting breakpoints, stepping through the code and inspecting your variables. You could then also have provided a more proper problem description than "getting some errors".
If you know the input is never larger than 20, you can initialize the output array to the same size and keep a counter of how many values you copied (the latter of which you already do).
Then when printing, only print the elements up till that count with a for loop instead of foreach.
So something like this:
int[] x = new int[20];
int[] y = new int[x.Length];
Random rnd = new Random();
int counter = 0;
for (int i = 0; i < x.Length; i++)
{
x[i] = rnd.Next(1, 30);
if (x[i] % 2 != 0)
{
y[counter] = x[i];
counter++;
}
}
for (int i = 0; i < counter; i++)
{
Console.WriteLine(y[i]);
}
Your problem is that you create a new y array for each odd number you find. You need to create the array only once and then fill it.
Since you don't know how many odd numbers there will be, I suggest to use a List<int> instead:
int[] x = new int[20];
Random rnd = new Random();
List<int> y = new List<int>(); // create the list before the loop
for (int i = 0; i < x.Length; i++)
{
x[i] = rnd.Next(1, 30);
if (x[i] % 2 !=0 )
y.Add(x[i]); // add odd number to list
}
foreach (int number in y)
{
Console.WriteLine(number);
}
See, In your case you are not aware about the number of odd numbers in that random array. so Array will not be a right choice here if you are following the current implementation. If you want the output as array, then Why not a simple LINQ with Where like this example:
First you collect all random numbers to your array as you are doing currently:
int[] randomIntegers = new int[20];
Random rnd = new Random();
for (int i = 0; i < randomIntegers.Length; i++)
{
randomIntegers[i] = rnd.Next(1, 30);
}
Now you have the all random numbers in x now perform the following operation:
int[] oddValues = randomIntegers.Where(a=> a % 2 !=0).ToArray();

ArgumentsOutOfRangeExeption in a list<T>

Im getting this exeption thrown when the method is invoked. the list contains exactly 52 objects(number of cards).
Any suggestions what may cause it? maybe the Add and RemoveAt Methods? Or maybe the Random?
The compiler also tell the the problem is in deck.Add(temp[j]); line.
public void Shuffle()
{
List<Card> temp = new List<Card>();
Random rand = new Random();
for (int i = 0; i < 52; i++)
{
for (int j = rand.Next(i, 52); j < 52; j++)
{
temp.Add(deck[j]);
deck.RemoveAt(j);
deck.Add(temp[j]);
}
}
}
Ok, let's imagine we are on the first run through the loops. First iteration of both the outer and inner loop. i is 0, and Rand(i, 52) produces 13.
So we have:
i - 0
j - 13
temp - empty list
deck - assume this is a list with 52 elements
Now let's run the three lines of code inside the loop:
temp.Add(deck[j]);
Get the 13th item of deck and add it to temp. Ok, done. temp now has 1 item.
deck.RemoveAt(j);
Remove the 13th item in deck. Ok, fine.
deck.Add(temp[j]);
Get the 13th item in temp and add it to, wait, what?1? temp only has 1 item! Exception! Exception!.
There isn't a need for the temp list in the first place. There is a very good shuffling algorithm that involves going through the original list of items once (not N times). And you just need one temp variable to hold a value while you swap it with another. Like this:
public void Shuffle()
{
Card temp;
Random rand = new Random();
for (int i = deck.Length; i >= 1; i--)
{
int j = rand.Next(0, i + 1);
temp = deck[i];
deck[i] = deck[j];
deck[j] = temp;
}
}
Done.
If you want to shuffle list of items then you can use the following method:
public static void Shuffle<T>(IList<T> arr, Random rnd)
{
for (var i = 0; i < arr.Count; i++)
{
var j = rnd.Next(i, arr.Count);
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
This method will help you shuffle your deck without ArgumentsOutOfRangeExeption
temp[j] does not neccessarily exist. You will need to initialize temp so it has at least j+1 entries or you need to change the line of temp[j] to something more fitting.
When you call rand.Next(i, 52), the result could be 52, which would be out of range for your deck and temporary deck.
Also, you need to initialize your temp list, as #nvoigt points out. List has a constructor that takes an integer for the initial size. You could pass in 52. See: http://msdn.microsoft.com/en-us/library/dw8e0z9z(v=vs.110).aspx.
You could have also easily debugged this yourself by looking at the value of j in your debugger.

C# Random number code check

The below code is copied from a paper, undergrad work was linked to from a wikipedia page. I believe I've spotted some flaws in the paper and some in the code but as I have no C# experience I just want to double check.
My understanding is that this code was meant to create a large psuedo totally random number but instead I believe it creates a large number which is a reoccuring smaller random number.
ie. 123123123 instead of 123784675. Can someone please confirm what the code does.
What I read here http://csharpindepth.com/Articles/Chapter12/Random.aspx and on Stackoverflow in various posts makes me believe that it's using the same seed and hence getting the same number each iteration and just appending that same number over and over.
Random randomNumber = new Random();
counter = 0;
for (int j = 0; j < 1; j++)
{
StringBuilder largeRandomNumber = new StringBuilder();
for (int i = 0; i < 40000; i++)
{
int value = randomNumber.Next(11111, 99999);
largeRandomNumber.Append(value);
}
}
Creates instance of random and loops through creating the next random number using random.Next(int min, int max) and appends this on the end of a string. Essentially, it just creates one huge number for something. Outer loop is garbage, not needed at all. Random doesn't need to be seeded again after creation...keeps same seed and progresses correctly using the Next method. Everything about this code "works" but seems pointless in any application besides learning about the random class.
The code is fine.
Try it here: http://www.compileonline.com/compile_csharp_online.php
using System.IO;
using System;
using System.Text;
class Program
{
static void Main()
{
Random randomNumber = new Random();
for (int j = 0; j < 1; j++)
{
StringBuilder largeRandomNumber = new StringBuilder();
for (int i = 0; i < 40; i++)
{
int value = randomNumber.Next(11111, 99999);
Console.WriteLine(value);
}
}
}
}
It is correct. Yes, Seed is same but this line will make sure that you get different number on different run :
int value = randomNumber.Next(11111, 99999);
and since you are appending this number to a string to create large random number, this does what it was supposed to do.
randomNumber is seeded on construction. randomNumber.Next is returning the next random integer between the two given integers based on the initial seed, and is not reseeded, thus giving 40000 new random numbers and appending them.
Not sure what the outer loop is for, it only runs once anyway
Yes, it is most likely that it will generate the same number if called quickly in succession, since Random is seeded with the current time. Unless they instantiated the randomNumber instance inside the loop however, for purposes of an example it works fine.
For example, if the code is plugged into a function like this
public string GetLargeRandomNumber()
{
Random randomNumber = new Random();
StringBuilder largeRandomNumber = new StringBuilder();
for (int j = 0; j < 1; j++)
{
for (int i = 0; i < 40000; i++)
{
int value = randomNumber.Next(11111, 99999);
largeRandomNumber.Append(value);
}
}
return largeRandomNumber.ToString();
}
And called from a main function in quick succession it will return the same random number.

frostDays doesn't exist

I want to end up with 100 frostDays but I think I put it wrong.
Its only a for loop + Array code.
for (int i = 0; i < 100; i++)
{
System.Random RandNum = new System.Random();
int nyrHiti = RandNum.Next(-10, 50);
Console.WriteLine(nyrHiti);
int[] frostDays = new int[100];
}
Console.ReadLine();
Console.WriteLine(frostDays[0]);
Console.ReadLine();
I have no idea what you're doing, but your code has several common errors that we can easily fix:
System.Random RandNum = new System.Random();
int[] frostDays = new int[100];
for (int i = 0; i < 100; i++) {
int nyrHiti = RandNum.Next(-10, 50);
Console.WriteLine(nyrHiti);
frostDays[i] = nyrHiti;
}
Console.ReadLine();
Console.WriteLine(frostDays[0]);
Console.ReadLine();
This probably gets you close to what you intended. You need to declare your instance of Random outside of the loop, and frostDays outside the for so it's still in scope when you need afterwards, and you need to assign to frostDays[i] in the loop otherwise it's just the zero array of length 100.
This will not work because frostDays has local scope to your for-loop. It must be declared outside of the loop to be able to be used by Console.WriteLine(...). But, it is going to be full of 0's so I am not sure what you intended to do here.
Your array is declared inside the loop, its visibility is restricted to this loop. Declare it outside the loop and it will work.
int[] frostDays = new int[100];
for (int i = 0; i < 100; i++)
{
System.Random RandNum = new System.Random();
int nyrHiti = RandNum.Next(-10, 50);
Console.WriteLine(nyrHiti);
}
Console.ReadLine();
Console.WriteLine(frostDays[0]);
Console.ReadLine();
However, as you don't do anything with it, it will return 0 each time. Maybe what you want is to set the ith value of the tab to the random number you just picked ? In this case, use frostDays[i] = nyrHiti at the end of the loop's body.
You have to define frostDays outside the loop.

Categories

Resources