Random Number Issue C# - c#

I am learning to use C# at the moment, and am just making random things I think of, so basically this is a "credit card generator" which obviously doesn't make real card numbers, just a random 16 digit number, with the CVV and Exp date.
So far, I can get it to print the Exp date, but as for the credit card number, I am getting an error which says -
"Cannot convert from long to int" and also a message stating the best overloaded method.
I am also having some problems with the date function, I can get it to generate 6 numbers ok, eg, day and year, but if i try to add another 2 numbers, it spits out 6 still.
Here is my code, sorry if this makes no sense, like I said, I am new to this :)
Thanks in advance for any help.
private void button1_Click(object sender, EventArgs e)
{
Random rnd = new Random();
double cardNumber = rnd.Next(4572000000000000, 4999999999999999);
int cvv = rnd.Next(001, 999);
int expDay = rnd.Next(1, 30);
int expMonth = rnd.Next(1, 12);
int expYear = rnd.Next(2011, 2015);
textBox1.Text = cardNumber.ToString();
textBox2.Text = cvv.ToString();
textBox3.Text = expDay.ToString() + expMonth.ToString() + expYear.ToString();
}
I will say this again just to make this clear, this in no way makes real credit card numbers, they are just randomly generated digits.....

Random.Next takes int. Since 4999999999999999 and 4572000000000000 are larger than int.MaxValue (2147483647) but less than long.MaxValue (9223372036854775807) they are automatically treated as indicating you want a long (as if you'd put an L on the end), but that can't be turned back into a number between -2147483648 and 2147483647. And that wouldn't be much use to you if it could.
You could produce a series of shorter numbers and add them together.
For greater verisimilitude, you could produce one less numbers than you need for your credit-card number (typically 16, so you'd produce 15 numbers, though card numbers from 14-digit to 19-digit have been used in the past) and then do a reverse Luhn to produce the final number, so you'd have a valid credit card number that passed a Luhn check. (This even has a practical use; it can be useful to special-case a Luhn-valid number outside of the range used by any real card issuer in debug-builds, so that you've a test number that most of your code treats as a valid number, but the final step knows not to try to purchase anything with).

As others have stated, the issue is that int doesn't work with numbers that big. As you say that you are just playing around and not creating real card numbers, what about creating a loop to create a single digit, then calling that 16 times. Each time you call the function, you can append the result to a string and hold that value for later.
Also, I don't think anyone has pointed it out yet, but you are using double as the type for your card number. That is an imprecise data type, and would not be appropriate here, where you need a precise number. the value you want may be 1234567891234567, but what is actually stored in memory is 123456789123456.0000000000001.
Random rnd = new Random();
string cardNumber = string.Empty;
for(int i = 0; i < 16; i++)
{
cardNumber += rnd.Next(0,9).ToString();
}

This is the code I am using now, but I want to take a look at the loop as suggested above, it seems a much cleaner solution.
Random rnd = new Random();
int cardNumber1 = rnd.Next(4572, 4999);
int cardNumber2 = rnd.Next(1000, 9999);
int cardNumber3 = rnd.Next(1000, 9999);
int cardNumber4 = rnd.Next(1000, 9999);
int cvv = rnd.Next(100, 999);
int expDay = rnd.Next(1, 30);
int expMonth = rnd.Next(1, 12);
int expYear = rnd.Next(2015, 2019);
textBox1.Text = cardNumber1.ToString() + cardNumber2.ToString() + cardNumber3.ToString() + cardNumber4.ToString();
textBox2.Text = cvv.ToString();
textBox3.Text = expDay.ToString() + "/" + expMonth.ToString() + "/" + expYear.ToString();

Related

Random string collision after using Fisher-Yates algorithm (C#)

I am doing an exercise from exercism.io, in which I have to generate random names for robots. I am able to get through a bulk of the tests until I hit this test:
[Fact]
public void Robot_names_are_unique()
{
var names = new HashSet<string>();
for (int i = 0; i < 10_000; i++) {
var robot = new Robot();
Assert.True(names.Add(robot.Name));
}
}
After some googling around, I stumbled upon a couple of solutions and found out about the Fisher-Yates algorithm. I tried to implement it into my own solution but unfortunately, I haven't been able to pass the final test, and I'm stumped. If anyone could point me in the right direction with this, I'd greatly appreciate it. My code is below:
EDIT: I forgot to mention that the format of the string has to follow this: #"^[A-Z]{2}\d{3}$"
public class Robot
{
string _name;
Random r = new Random();
string alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string nums = "0123456789";
public Robot()
{
_name = letter() + num();
}
public string Name
{
get { return _name; }
}
private string letter() => GetString(2 ,alpha.ToCharArray(), r);
private string num() => GetString(3, nums.ToCharArray(), r);
public void Reset() => _name = letter() + num();
public string GetString(int length,char[] chars, Random rnd)
{
Shuffle(chars, rnd);
return new string(chars, 0, length);
}
public void Shuffle(char[] _alpha, Random r)
{
for(int i = _alpha.Length - 1; i > 1; i--)
{
int j = r.Next(i);
char temp = _alpha[i];
_alpha[i] = _alpha[j];
_alpha[j] = temp;
}
}
}
The first rule of any ID is:
It does not mater how big it is, how many possible value it has - if you just create enough of them, you will get a colission eventually.
To Quote Trillian from the Hithchikers Guide: "[A colission] is not impossible. Just realy, really unlikely."
However in this case, I think it is you creating Random Instances in a Loop. This is a classical beginners mistake when workign with Random. You should not create a new random isntance for each Robot Instance, you should have one for the application that you re-use. Like all Pseudorandom Number Generators, Random is deterministic. Same inputs - same outputs.
As you did not specify a seed value, it will use the time in milliseconds. Wich is going to the same between the first 20+ loop itterations at last. So it is going to have the same seed and the same inputs, so the same outputs.
The easiest solution for unique names is to use GUIDs. In theory, it is possible to generate non-unique GUIDs but it is pretty close to zero.
Here is the sample code:
var newUniqueName = Guid.NewGuid().ToString();
Sure GUIDs do not look pretty but they are really easy to use.
EDIT: Since the I missed the additional requirement for the format I see that GUID format is not acceptable.
Here is an easy way to do that too. Since format is two letters (26^2 possibile values) and 3 digits (10^3 possible values) the final number of possible values is 26^2 * 10^3 = 676 * 1000 = 676000. This number is quite small so Random can be used to generate the random integer in the range 0-675999 and then that number can be converted to the name. Here is the sample code:
var random = new System.Random();
var value = random.Next(676000);
var name = ((char)('A' + (value % 26))).ToString();
value /= 26;
name += (char)('A' + (value % 26));
value /= 26;
name += (char)('0' + (value % 10));
value /= 10;
name += (char)('0' + (value % 10));
value /= 10;
name += (char)('0' + (value % 10));
The usual disclaimer about possible identical names applies here too since we have 676000 possible variants and 10000 required names.
EDIT2: Tried the code above and generating 10000 names using random numbers produced between 9915 and 9950 unique names. That is no good. I would use a simple static in class member as a counter instead of random number generator.
First, let's review the test you're code is failing against:
10.000 instances created
Must all have distinct names
So somehow, when creating 10000 "random" names, your code produces at least two names that are the same.
Now, let's have a look at the naming scheme you're using:
AB123
The maximum number of unique names we could possibly create is 468000 (26 * 25 * 10 * 9 * 8).
This seems like it should not be a problem, because 10000 < 468000 - but this is where the birthday paradox comes in!
From wikipedia:
In probability theory, the birthday problem or birthday paradox concerns the probability that, in a set of n randomly chosen people, some pair of them will have the same birthday.
Rewritten for the purposes of your problem, we end up asking:
What's the probability that, in a set of 10000 randomly chosen people, some pair of them will have the same name.
The wikipedia article also lists a function for approximating the number of people required to reach a 50% propbability that two people will have the same name:
where m is the total number of possible distinct values. Applying this with m=468000 gives us ~806 - meaning that after creating only 806 randomly named Robots, there's already a 50% chance of two of them having the same name.
By the time you reach Robot #10000, the chances of not having generated two names that are the same is basically 0.
As others have noted, you can solve this by using a Guid as the robot name instead.
If you want to retain the naming convention you might also get around this by implementing an LCG with an appropriate period and use that as a less collision-prone "naming generator".
Here's one way you can do it:
Generate the list of all possible names
For each robot, select a name from the list at random
Remove the selected name from the list so it can't be selected again
With this, you don't even need to shuffle. Something like this (note, I stole Optional Option's method of generating names because it's quite clever and I couldn't be bother thinking of my own):
public class Robot
{
private static List<string> names;
private static Random rnd = new Random();
public string Name { get; private set; }
static Robot()
{
Console.WriteLine("Initializing");
// Generate possible candidates
names = Enumerable.Range(0, 675999).Select(i =>
{
var sb = new StringBuilder(5);
sb.Append((char)('A' + i % 26));
i /= 26;
sb.Append((char)('A' + i % 26));
i /= 26;
sb.Append(i % 10);
i /= 10;
sb.Append(i % 10);
i /= 10;
sb.Append(i % 10);
return sb.ToString();
}).ToList();
}
public Robot()
{
// Note: if this needs to be multithreaded, then you'd need to do some work here
// to avoid two threads trying to take a name at the same time
// Also note: you should probably check that names.Count > 0
// and throw an error if not
var i = rnd.Next(0, names.Count - 1);
Name = names[i];
names.RemoveAt(i);
}
}
Here's a fiddle that generates 20 random names. They can only be unique because they are removed once they are used.
The point about multitheading is very important however. If you needed to be able to generate robots in parallel, then you'd need to add some code (e.g. locking the critical section of code) to ensure that only one name is being picked and removed from the list of candidates at a time or else things will get really bad, really quickly. This is why, when people need a random id with a reasonable expectation that it'll be unique, without worrying that some other thread(s) are trying the same thing at the same time, they use GUIDs. The sheer number of possible GUIDs makes collisions very unlikely. But you don't have that luxury with only 676,000 possible values

C# needing a six digit number beginning with two 0's

I'm making a program where products are searched for by there batch number. I want to the batch number to be a random 6 digit code starting with 00, for example 002142; at the moment it is only making a random 6 digit code.
Here is the code I have tried:
public string getRandomNumber()
{
Random random = new Random(100000);
string randomNumber = random.Next(999999).ToString("D6");
return randomNumber;
}
public string getRandomNumber()
{
Random random = new Random();
string randomNumber = "00"+random.Next(10000).ToString("D4");
return randomNumber;
}
You should not set a fix seed in the Random, because it will allways generate the same random number sequence. For example if you call your function in a loop it will allways return the same number, thus not being random.
Also the parameter in the Next() function is the upper bound exclusive so use 10000 instead 9999 so you can get 9999 as a random number as well.
why is everybody creating 6 digit ? what really is needed is create 4 and concat.
int random = new Random().Next(1000, 9999);
string code = "00" + random.ToString();
EDIT:
Thanks for marking as correct answer but my code is wrong. If you don't pass minimum value to next method, you can get numbers from 1 to 999 which you don't want. I edited my answer. Hope it's not late for anything.
You wrote .Next(999999) so i assume you want random values from 0 to 999999.
First you should write 1000000 because .Next() determines a random number from 0 to exclusive the input value.
Then you should
replace
string randomNumber = random.Next(1000000).ToString("D6");
with
string randomNumber = random.Next(999999).ToString().PadLeft(6, '0');
to fill the missing digits with 0
Another possibility is "000000" format string (six digits, leading zeros are mandatory):
random.Next(10000) - last 4 digits are random
ToString("000000") - 6 digits are returned (at least 2 leading zeros)
Implementation
string randomNumber = random.Next(10000).ToString("000000");
Another issue is that you should not declare random locally:
// Simplest, but not thread safe
private static random = new Random();
...
public static string getRandomNumber()
{
return random.Next(10000).ToString("000000");
}
You were close. What you really want is a random four digit number, padded with two leading zeroes (to six places) . So use Random.Next(10000).ToString("D6") or . ToString("000000")
Note however for numbers less than 1000, you will end up with more than two leading zeroes. To avoid that, you can do Random.Next(1000,10000) where the first number is inclusive, and the second exclusive.
Note also that the way you are initializing the random is incorrect if you are going to be calling this method more than once! Make your Random object a class member (preferably static) and only seed/initialize it once (don't pass 100000 to its constructor) Otherwise if this method is called more than once, it is going to return the same value each time.
Use new Random() . If you are going to seed it the way you do, it must be a static variable (or at least a class member--however for each instance of the class you will end up with the same values being generated)
I would do something like this:
var rnd = new Random(); // the internal seed is good enough
var rndNums = string.Join("", Enumerable.Range(0, 4).Select(x => rnd.Next(10)));
return "00" + rndNums;
Then you can easily change the amount you want, like this:
string GetRandomBatch(int numberOfRandomNumbers)
{
var rnd = new Random(); // the internal seed is good enough
var rndNums = string.Join("", Enumerable.Range(0, numberOfRandomNumbers).Select(x => rnd.Next(0, 9)));
return "00" + rndNums;
}
With interpolated string (C# 6.0) you can do it like this :
Random random = new Random();
string randomNumber = $"00{random.Next(9999)}";
Your ToString("D6") does exactly what it appears that you want, but since you are passing a large upper bound for your random.Next, there will in many scenarios not be anything to pad.
As others have indicated, you may prefix "00", or you could simply set a lower upper bound, since the "D6" will take care of your padding:
string randomNumber = random.Next(9999).ToString("D6");
If you want the number to always be 4 digits and not, say, "000123", you'll need to specify a lower bound as well:
string randomNumber = random.Next(1000, 9999).ToString("D6");
Also note that if you are specifying a hardcoded seed as in your example, you will always get the same random number back.
Something like this will do.
public static void Main()
{
Random rnd = new Random();
string Value = rnd.Next(1, 9999).ToString("D6");
Console.WriteLine(Value);
}
Or with lower possibility of getting the same number would be
public static void Main()
{
Random rnd = new Random(DateTime.Now.Millisecond);
string Value = rnd.Next(1, 9999).ToString("D6");
Console.WriteLine(Value);
}
public string RandomNum()
{
return "00"+ new Random().Next(9999).ToString("D4");
}
you can also give minimum and maximum number to Next() function. Like:
return "00"+ new Random().Next(1,9999).ToString("D4");

Why is there a strong correlation between random number and correct guesses?

In trying to test whether knowing the history of a random number could help predict the future results, I found a strong, unexpected correlation between the average of the number generated, and the number of correct guesses.
The test was supposed to simulate flipping a coin (heads = 0, tails = 1) and if previous attempts were biased towards heads then guess tails and vice versa.
Why is the sum of the generated numbers always nearly equal to the number of correct guesses in the following LinqPad program?
void Main()
{
var rnd = new Random();
var attempts = 10000000;
var correctGuesses = 0;
long sum = 0;
decimal avg = 0.5m;
for (int i = 0; i < attempts; i++)
{
var guess = avg < 0.5m ? 1 : 0;
var result = rnd.Next(0, 2);
if (guess == result)
{
correctGuesses += 1;
}
sum += result;
avg = (decimal)sum/(decimal)attempts;
}
attempts.Dump("Attempts");
correctGuesses.Dump("Correct Guesses");
avg = (decimal)sum / (decimal)attempts;
avg.Dump("Random Number Average");
}
Have a made an error in the code? Is this a natural relationship? I expected the averages to converge at 0.5 as I increased the number of attempts because the distribution is fairly even - I tested this with 10bn calls to Random.Next(0,2) - but I did not expect the sum of generated numbers to correlate to the number of correct guesses.
Your error is this line:
avg = (decimal)sum/(decimal)attempts;
Makes no sense to divide the sum (based over i to that point) by attempts. Divide by i (EDIT: more precisely i+1) instead for avg to give you something meaningful.
The Random class, without a seed, generates a random number using the current time as seed, meaning that a call of the rnd.Next method in your cycle will result in the same number several times over, depending on how fast your machine goes through the cycle.

Random number distribution is uneven / non uniform

I have noticed a strange issue with the random number generation in c#, it looks like sets (patterns) are repeated a lot more often than you would expect.
I'm writing a mechanism that generates activation codes, a series of 7 numbers (range 0-29).
Doing the math, there should be 30^7 (22billion) possible combinations of activation codes. Based on this it should be extremely unlikely to get a duplicate activation code before the 1 billionth code is generated. However running my test, I start getting duplicate codes after about 60,000 iteration, which is very surprising. I have also tried using RNGCryptoServiceProvider with similar results, I get duplicates at about 100,000 iterations.
I would really like to know if this is a bug/limitation of the random number generation in .Net or if I'm doing something wrong.
The following code is a test to validate the uniqueness of the generated codes:
static void Main(string[] args)
{
Random rand = new Random();
RandomActivationCode(rand, true);
Console.Out.WriteLine("Press enter");
Console.ReadLine();
}
static void RandomActivationCode(Random randomGenerator)
{
var maxItems = 11000000;
var list = new List<string>(maxItems);
var activationCodes = new HashSet<string>(list);
activationCodes.Clear();
DateTime start = DateTime.Now;
for (int i = 0; i < maxItems; ++i)
{
string activationCode = "";
for (int j = 0; j < 7; ++j)
{
activationCode += randomGenerator.Next(0,30) + "-";
}
if (activationCodes.Contains(activationCode))
{
Console.Out.WriteLine("Code: " + activationCode);
Console.Out.WriteLine("Duplicate at iteration: " + i.ToString("##,#"));
Console.Out.WriteLine("Press enter");
Console.ReadLine();
Console.Out.WriteLine();
Console.Out.WriteLine();
}
else
{
activationCodes.Add(activationCode);
}
if (i % 100000 == 0)
{
Console.Out.WriteLine("Iteration: " + i.ToString("##,#"));
Console.Out.WriteLine("Time elapsed: " + (DateTime.Now - start));
}
}
}
My workaround is to use 10 number activation codes, which means that the test runs without any duplicate values being generated. The test runs up to 11 million iterations (after which point it runs out of memory).
This is not at all surprising; this is exactly what you should expect. Your belief that it should take a long time to generate duplicates when the space of possibilities is large is simply false, so stop believing that. Start believing the truth: that if there are n possible codes then you should start getting duplicates at about the square root of n codes generated, which is about 150 thousand if n is 22 billion.
Think about it this way: by the time you have generated root-n codes, most of them have had roughly a root-n-in-n chance to have a collision. Multiply root-n by roughly root-n-in-n, and you get... roughly 100% chance of collision.
That is of course not a rigorous argument, but it should give you the right intution, to replace your faulty belief. If that argument is unconvincing then you might want to read my article on the subject:
http://blogs.msdn.com/b/ericlippert/archive/2010/03/22/socks-birthdays-and-hash-collisions.aspx
If you want to generate a unique code then generate a GUID; that's what they're for. Note that a GUID is not guaranteed to be random, it is only guaranteed to be unique.
Another choice for generating random seeming codes that are not actually random at all, but are unique, is to generate the numbers 1, 2, 3, 4, ... as many as you want, and then use the multiplicative inverse technique to make a random-looking unique encoding of those numbers. See http://ericlippert.com/2013/11/14/a-practical-use-of-multiplicative-inverses/ for details.

how to generate a voucher code in c#?

I need to generate a voucher code[ 5 to 10 digit] for one time use only. what is the best way to generate and check if been used?
edited: I would prefer alpha-numeric characters - amazon like gift voucher codes that must be unique.
When generating voucher codes - you should consider whether having a sequence which is predictable is really what you want.
For example, Voucher Codes: ABC101, ABC102, ABC103 etc are fairly predictable. A user could quite easily guess voucher codes.
To protect against this - you need some way of preventing random guesses from working.
Two approaches:
Embed a checksum in your voucher codes.
The last number on a credit card is a checksum (Check digit) - when you add up the other numbers in a certain way, lets you ensure someone has entered a number correctly. See: http://www.beachnet.com/~hstiles/cardtype.html (first link out of google) for how this is done for credit cards.
Have a large key-space, that is only sparsely populated.
For example, if you want to generate 1,000 vouchers - then a key-space of 1,000,000 means you should be able to use random-generation (with duplicate and sequential checking) to ensure it's difficult to guess another voucher code.
Here's a sample app using the large key-space approach:
static Random random = new Random();
static void Main(string[] args)
{
int vouchersToGenerate = 10;
int lengthOfVoucher = 10;
List<string> generatedVouchers = new List<string>();
char[] keys = "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890".ToCharArray();
Console.WriteLine("Vouchers: ");
while(generatedVouchers.Count < vouchersToGenerate)
{
var voucher = GenerateVoucher(keys, lengthOfVoucher);
if (!generatedVouchers.Contains(voucher))
{
generatedVouchers.Add(voucher);
Console.WriteLine("\t[#{0}] {1}", generatedVouchers.Count, voucher);
}
}
Console.WriteLine("done");
Console.ReadLine();
}
private static string GenerateVoucher(char[] keys, int lengthOfVoucher)
{
return Enumerable
.Range(1, lengthOfVoucher) // for(i.. )
.Select(k => keys[random.Next(0, keys.Length - 1)]) // generate a new random char
.Aggregate("", (e, c) => e + c); // join into a string
}
Building on the answers from Will Hughes & Shekhar_Pro (and just because I found this question interesting) here's another implementation but I've been a bit liberal with your requirement for the length of the voucher code.
Using a base 32 encoder I found you can use the Tick value to generate alpha-numeric strings. The encoding of a tick count to base 32 produces a 13 character string which can be formatted to make it more readable.
public void GenerateCodes()
{
Random random = new Random();
DateTime timeValue = DateTime.MinValue;
// Create 10 codes just to see the random generation.
for(int i=0; i<10; ++i)
{
int rand = random.Next(3600)+1; // add one to avoid 0 result.
timeValue = timeValue.AddMinutes(rand);
byte[] b = System.BitConverter.GetBytes(timeValue.Ticks);
string voucherCode = Transcoder.Base32Encode(b);
Console.WriteLine(string.Format("{0}-{1}-{2}",
voucherCode.Substring(0,4),
voucherCode.Substring(4,4),
voucherCode.Substring(8,5)));
}
}
Here's the output
AARI-3RCP-AAAAA
ACOM-AAZF-AIAAA
ABIH-LV7W-AIAAA
ADPL-26FL-AMAAA
ABBL-W6LV-AQAAA
ADTP-HFIR-AYAAA
ACDG-JH5K-A4AAA
ADDE-GTST-BEAAA
AAWL-3ZNN-BIAAA
AAGK-4G3Y-BQAAA
If you use a known seed for the Random object and remember how many codes you have already created you can continue to generate codes; e.g. if you need more codes and want to be certain you won't generate duplicates.
Here's one way: Generate a bunch of unique numbers between 10000 and 9999999999 put it in a database. Every time you give one to a user, mark it as used (or delete it if you're trying to save space).
EDIT: Generate the unique alpha-numeric values in the beginning. You'll probably have to keep them around for validation (as others have pointed out).
If your app is limited to using only Numerical digits then i think Timestamps (DateTime.Now.Ticks) can be a good way to get unique code every time. You can use random nums but that will have overhead of checking every number that its been issued already or not. If you can use alphabets also then surely go with GUID.
For checking if its been used or not you need to maintain a database and query it to check for validity.
If you prefer alphanumerical, you could use Guid.NewGuid() method:
Guid g = Guid.NewGuid();
Random rn = new Random();
string gs = g.ToString();
int randomInt = rn.Next(5,10+1);
Console.WriteLine(gs.Substring(gs.Length - randomInt - 1, randomInt));
To check if it was not used store somwhere previously generated codes and compare.
private void AutoPurchaseVouNo1()
{
try
{
int Num = 0;
con.Close();
con.Open();
string incre = "SELECT MAX(VoucherNoint+1) FROM tbl_PurchaseAllCompany";
SqlCommand command = new SqlCommand(incre, con);
if (Convert.IsDBNull(command.ExecuteScalar()))
{
Num = 100;
txtVoucherNoInt1.Text = Convert.ToString(Num);
txtVoucherNo1.Text = Convert.ToString("ABC" + Num);
}
else
{
Num = (int)(command.ExecuteScalar());
txtVoucherNoInt1.Text = Convert.ToString(Num);
txtVoucherNo1.Text = Convert.ToString("ABC" + Num);
}
con.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex, "Error !!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Try this method for creating Voucher Number like ABC100, ABC101, ABC102, etc.
Try this code
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var stringChars = new char[15];
for (int i = 0; i < stringChars.Length; i++)
{
stringChars[i] = chars[random.Next(chars.Length)];
}

Categories

Resources