Random Character Generation Error C# - c#

For some reason, when I try to generate this code all at once, the code produces the same number or letter over and over again (30 times) - see below. When I go through line by line in debug mode, however, the code works great...
private string Generate_ActiveX_name()
{
StringBuilder charBuilder = new StringBuilder("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
StringBuilder numBuilder = new StringBuilder("0123456789");
//
// Holds Active X Key (final)
//
StringBuilder activeX_builder = new StringBuilder();
// Determine charactar or number
while (activeX_builder.Length < 30)
{
Random activeX_gen = new Random();
switch (activeX_gen.Next(0, 2))
{
case 0:
Random charSelection = new Random();
int CharSelected = charSelection.Next(0, 53);
activeX_builder.Append(charBuilder[CharSelected]);
break;
case 1:
Random numSelection = new Random();
int NumSelected = numSelection.Next(0, 10);
activeX_builder.Append(numBuilder[NumSelected]);
break;
}
}
string activeX_key = activeX_builder.ToString().Substring(0, 8) + "-";
activeX_key += activeX_builder.ToString().Substring(8, 4) + "-";
activeX_key += activeX_builder.ToString().Substring(12, 4) + "-";
activeX_key += activeX_builder.ToString().Substring(16, 11);
return activeX_key;
}
Why does this code fail when I run it through all at once?
Thanks,
Evan

You need to move the Random constructor out of your loop. Change this:
while (activeX_builder.Length < 30)
{
Random activeX_gen = new Random();
To:
Random activeX_gen = new Random();
while (activeX_builder.Length < 30)
{
The issue is that, when an instance of Random is created, it uses the current system clock as a "seed" value for the random number generation. Since your routine runs very quickly, the same seed is chosen every time, so you get the same "random" value. When you're debugging, you're slowing it down (by stepping) enough that a different seed is chosen in each loop, and you get truly random values.
If you move it out of the loop, then a single Random instance will be created, which will lead to a random distribution (and more efficiency!).

Seems like you are trying to generate GUID.
You can do this with one line
var guid = Guid.NewGuid();
However, here is the fix to your code:
private static string Generate_ActiveX_name()
{
StringBuilder charBuilder = new StringBuilder("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
StringBuilder numBuilder = new StringBuilder("0123456789");
StringBuilder activeX_builder = new StringBuilder();
Random activeX_gen = new Random();
while (activeX_builder.Length < 30)
{
switch (activeX_gen.Next(0, 2))
{
case 0:
int CharSelected = activeX_gen.Next(0, 53);
activeX_builder.Append(charBuilder[CharSelected]);
break;
case 1:
int NumSelected = activeX_gen.Next(0, 10);
activeX_builder.Append(numBuilder[NumSelected]);
break;
}
}
string activeX_key = activeX_builder.ToString().Substring(0, 8) + "-";
activeX_key += activeX_builder.ToString().Substring(8, 4) + "-";
activeX_key += activeX_builder.ToString().Substring(12, 4) + "-";
activeX_key += activeX_builder.ToString().Substring(16, 11);
return activeX_key;
}
Two problems:
You don't need more than one instance of Random class: charSelection and numSelection are redundant.
Instantiate Random class one time, not inside of the while loop.
[Edit]
8-4-4-11 format:
var guidText = Guid.NewGuid().ToString();
var customGuid = guidText.Substring(0, 18) + guidText.Substring(23, 12);

Related

C# substract 2 strings without getting negatives

i need some help with my code.
i've got to make a math game with subtracting without getting negatives but my code doesn't seem to work.
int c = a - b;
if (c < 0)
{
Random ro = new Random();
a = ro.Next(10) + 1;
b = ro.Next(10) + 1;
lb_getal1.Text = a.ToString();
lb_getal2.Text = b.ToString();
}
if (txt_antwoord.Text == c.ToString())
{
MessageBox.Show("You provided the right answer!");
score += 1;
Random r = new Random();
a = r.Next(10) + 1;
b = r.Next(10) + 1;
lb_getal1.Text = a.ToString();
lb_getal2.Text = b.ToString();
}
else
{
MessageBox.Show("You were wrong!");
}
if (score == 5)
{
MessageBox.Show("You answered 5 answers correctly! Well done!");
this.Close();
RM_menu form = new RM_menu();
form.Show();
}
There are several problems in your code. The first thing to improve is: use only one instance of Random.
The Random class provides pseudo random numbers from a list. If you create an instance with the default constructor new Random(), the instance is initialized with a seed taken from the current time. Since there is not much time between your two calls, both instances probably use the same seed and you will get the same values for a and b again.
I suggest to create only one instance and store it in a member variable of your class.
Second problem: if your first try results in a negative c, you only try again once, but that does not make sure that this time it will be positive. A better approach is to compare a and b and switch if b is larger.
So the your code could look like this:
public class YourGame : Form // I guess it's a Form
{
private Random randomGenerator = new Random();
private int a;
private int b;
private int score;
public void CreateQuestion()
{
a = randomGenerator.Next(10) + 1;
b = randomGenerator .Next(10) + 1;
if (b > a)
{
// switch values
int tmp = b;
b = a;
a = tmp;
}
lb_getal1.Text = a.ToString();
lb_getal2.Text = b.ToString();
}
private void OnAnswer()
{
int c = a - b; // will never be negative as we checked a and b above
if (txt_antwoord.Text == c.ToString())
{
MessageBox.Show("You provided the right answer!");
score += 1;
CreateQuestion();
}
else
MessageBox.Show("You were wrong!");
if (score == 5)
{
MessageBox.Show("You answered 5 answers correctly! Well done!");
this.Close();
RM_menu form = new RM_menu();
form.Show();
}
}
}
I am not trying to solve this problem, but trying to give some inputs on how to make sure that the value would not be less than zero when using Random.
int a, b, c;
Random ro;
ro = new Random();
b = ro.Next(10);
a = ro.Next(b, 10);
c = a - b;
As you can see, first we set a random value to b using ro.Next(10) and then we specify a minimum value by using ro.Next(b, 10)
Doing so, it is guaranteed that the value would not be less than zero when doing a-b.
you can use Math.Abs
int c = Math.Abs (a-b);

cycle never reaching final value

This is my random unique numbers generator I try to create for my cards software. It generates numbers and write into array OK. I have problem with the loop here. when integer i reaches 29, it stops growing and code cycles infinitely and never reaches 30, which would stop the loop.
Without the if statement it works, but it won't fill the range needed.
fixed the code, now works OK, the initial value in array was the problem. now I ged needed 0-29 values
public partial class Form1 : Form
{
int[] rndCards = new int[30];
public Form1()
{
InitializeComponent();
richTextBox1.Text = #"random numbers";
}
private void button1_Click(object sender, EventArgs e)
{
int i = 0;
rndCards = new int[30];
richTextBox1.Clear();
Random rnd = new Random();
while (i < 30)
{
int cardTest = rnd.Next(0, 30);
while (rndCards.Contains(cardTest))
{
cardTest++;
if (cardTest == 31)
{
cardTest = 1;
}
}
rndCards[i] = cardTest;
i++;
}
i = 0;
while (i < 30)
{
rndCards[i] = rndCards[i] -1;
richTextBox1.Text += rndCards[i] + ", ";
i++;
}
}
}
You problem lies in the simple fact that the array already contains the number 0 when you create it (because each item of an array is initialized to the default value for its member's type) That's why you should start your i from 1 and not zero.
int i = 1;
Alternative Simpler Approach:
You can do this as a simple random number generation:
Random rnd = new Random();
rndCards = Enumerable.Range(0, 30).OrderBy(x => rnd.Next()).ToArray();
foreach(var card in rndCards)
{
// do something
}
rnd.Next(0,30) would return a random number from 0-29.
From the documentation for Random.Next(Int32, Int32):
The Next(Int32, Int32) overload returns random integers that range from minValue to maxValue – 1. However, if maxValue equals minValue, the method returns minValue.
Use int cardText = rnd.Next(0, 31);, and this should solve your issue.
The upper bound is exclusive (C# Random.Next - never returns the upper bound?).
int cardTest = rnd.Next(0, 31);

Filling array with random "cards" of enum

Classic deck of cards/poker game issue. I have classes for each card (CardClubs, CardDiamond, etc). I have an enum for Rank (Deuce = 2, etc). In my CardSet class, I have the constructor:
public SuperCard[] cardArray;
public Random myRandom = new Random();
#region Constructor
public CardSet()
{
cardArray = new SuperCard[52];
for (int i = 0; i < 13; i++)
{
cardArray[i] = new CardClubs((Rank)i + 1);
cardArray[i + 13] = new CardDiamond((Rank)i+1);
cardArray[i + 26] = new CardHeart((Rank)i + 1); ;
cardArray[i + 39] = new CardSpades((Rank)i + 1); ;
}
}
#endregion
And I have the method GetCards, which passes in the number of cards to get. I created the public random up top. GetCards is called in the Program.cs, as such:
int howManyCards = 5; // can be whatever. used this instead of # for debug purposes
SuperCard[] computerHand = myDeck.GetCards(howManyCards); // create two hands, user/comp
SuperCard[] myHand = myDeck.GetCards(howManyCards);
I am not understanding how to use random to generate the random card. here is my current GetCard method (which isn't working) also from the CardSet class. For now, its okay if it generates the same card, just want to understand the basics of random selection.
public SuperCard[] GetCards(int number)
{
SuperCard[] hand = new SuperCard[number];
for (int i = 0; i < number; i++)
{
hand[i] = cardArray[myRandom]((Rank)i + 1);
}
return hand;
}
Use the Random class (http://msdn.microsoft.com/en-us/library/system.random.aspx)
var r = new Random();
r.Next(min,max);

How to replace random number in asp.net/c with pictures?

I am trying to replace random number with pictures. for example If random number is 1 show picture black.jpg:
Cache[diceKey] = r.Next(1, 5); // random (1-4)
if (r.Next(1, 2) == 1 )
image.BackImageUrl = "Images/black.png";
is there any solutions that I can show my picture if random number is 1?
Store your image urls in an array. Generate a random index to access the image:
string[] imageUrls = new [] { "foo.png", "bar.png", "foobar.png" };
// ...
Random r = new Random();
image.BackImageUrl = imageUrls[r.Next(imageUrls.Length)];
Update (still not getting the issue, though)
Only set a certain image if the generated random number is 1:
int i = r.Next(1, 5); // random (1-4)
Cache[diceKey] = i;
if (i == 1)
{
image.BackImageUrl = "Images/black.png";
}
As I already said in my comment r.Next(1, 2) will always return 1, so you will always show that black image...
I think you should change your code to this:
var randomValue = r.Next(1, 5); // random (1-4)
Cache[diceKey] = randomValue;
if (randomValue == 1)
image.BackImageUrl = "Images/black.png";
else
image.BackImageUrl = "";

generating a batch of random passwords

Generating a random password is easy. but generating a batch is more difficult.
public static string getRandomPassword(int letters, int getallen) {
//int letters = 8;
//int getallen = 5;
char[] letterdeel = new char[letters];
int minGetal = (int)Math.Pow(10, getallen - 1);
int maxGetal = (int)Math.Pow(10, getallen);
string password;
Random r = new Random();
int test = (int)(DateTime.Now.Ticks);
for (int i = 0; i < letters; i++) {
r = new Random((int)(DateTime.Now.Ticks) + i);
bool capital = r.Next(2) == 0 ? true : false;
if (capital) {
letterdeel[i] = (char)r.Next(65, 91);
} else {
letterdeel[i] = (char)r.Next(97, 123);
}
}
password = new string(letterdeel);
password += r.Next(minGetal, maxGetal);
return password;
}
this is my method, the passwords should be in a certain letter-number format.
this works fine, however if i have a for loop pulling 100 passwords from this method, in my array i have 5-8 the same passwords, then again 5-8 the same pass.
i know WHY this is, because of the random function and the clock it depends on, but how do i fix this?
Move Random r to outside the method if you are repeatedly calling it. You are going to be hitting it several times in the same relative timeframe, so you are going to be generating the same seeds. You also want to get rid of the line below. It is unnecessary, and (again), with the nature of DateTime.Now, you would just continue to generate the same sequence of "random" numbers.
r = new Random((int)(DateTime.Now.Ticks) + i);
Define your random number generator as a static outside of the function.
How can I get true randomness in this class without Thread.Sleep(300)?
Use a set rather than whatever collection you store into and don't loop 100 times but until the set has 100 items in it.

Categories

Resources