This question already has answers here:
How to get a random number from a range, excluding some values
(11 answers)
Closed 9 years ago.
Is it possible to pick a random number from a given range (1-90), but exclude certain numbers. The excluded numbers are dynamically created but lets say they are 3, 8, and 80.
I have managed to create random number generator but couldn't identify any functions that let me fulfill my requirements.
Random r = new Random();
this.num = r.Next(1, 90);
The numbers which are to be excluded are previously generated numbers. So, if the random number is one, this would then get added to the excluded numbers list.
Using some handy extension methods here, you can create a range of numbers and select randomly from that rage. For example, with these extension methods:
public static T RandomElement(this IEnumerable<T> enumerable)
{
return enumerable.RandomElementUsing(new Random());
}
public static T RandomElementUsing(this IEnumerable<T> enumerable, Random rand)
{
int index = rand.Next(0, enumerable.Count());
return enumerable.ElementAt(index);
}
You can apply these to a filtered range of numbers:
var random = Enumerable.Range(1, 90).Except(arrayOfRemovedNumbers).RandomElement();
Create a container which holds the numbers you do not want:
var excludedNumbers = new List<int> { 1, 15, 35, 89 };
Then use do something like:
Random random = new Random();
int number;
do
{
number = r.Next(1, 90);
} while (excludedNumbers.Contains(number));
// number is not in the excluded list now
Might not be the best choice but you can use a while loop to check the numbers you don't want
Random r = new Random();
this.num = r.Next(1, 90);
do
{
this.num = r.Next(1, 90);
}
while (this.num == 3 || this.num == 8 || this.num == 90);
For much numbers you can use an array or a list and loop through them
int[] exclude = { 3, 8, 90, 11, 24 };
Random r = new Random();
this.num = r.Next(1, 90);
do
{
this.num = r.Next(1, 90);
}
while (exclude.Contains(this.num));
Your latest update, which implies that each value can only be selected once, makes the problem easy.
Create a collection of values within the range.
Randomly shuffle the collection.
To"randomly" select an item, just return the first item in the collection, and remove it from the collection.
Random r = new Random();
this.num = r.Next(1, 90);
int excluded[] = new int[] { 3,8,80 }; // list any numbers in this array you want to exclude
for (int i = 0; i < excluded.Length; i++)
{
if (this.num == excluded[i])
{
this.num = r.Next(1, 90); // or you can try doing something else here
}
}
This solution does it in O(n) worst case where n is your list of exclusions, and constant memory. The code is a little longer but might be relevant if you:
Possibly have a huge list of exclusions
Need to run this many times
Have a large range
It preserves the random distribution in the sense that it actually skips the exclusion list and generates a random number within the range excluding the set.
This is the implementation:
private static int RandomInRangeExcludingNumbers(Random random, int min, int max, int[] excluded)
{
if (excluded.Length == 0) return random.Next(min, max);
//array should be sorted, remove this check if you
//can make sure, or sort the array before using it
//to improve performance. Also no duplicates allowed
//by this implementation
int previous = excluded[0];
for (int i = 1; i < excluded.Length; i++)
{
if (previous >= excluded[i])
{
throw new ArgumentException("excluded array should be sorted");
}
}
//basic error checking, check that (min - max) > excluded.Length
if (max - min <= excluded.Length)
throw new ArgumentException("the range should be larger than the list of exclusions");
int output = random.Next(min, max - excluded.Length);
int j = 0;
//set the start index to be the first element that can fall into the range
while (j < excluded.Length && excluded[j] < min) j++;
//skip each number occurring between min and the randomly generated number
while (j < excluded.Length && excluded[j] <= output)
{
j++;
output++;
while (excluded.Contains(output))
output++;
}
return output;
}
And a test function to make sure it works (over 100k elements)
private static void Test()
{
Random random = new Random();
int[] excluded = new[] { 3, 7, 80 };
int min = 1, max = 90;
for (int i = 0; i < 100000; i++)
{
int randomValue = RandomInRangeExcludingNumbers(random, min, max, excluded);
if (randomValue < min || randomValue >= max || excluded.Contains(randomValue))
{
Console.WriteLine("Error! {0}", randomValue);
}
}
Console.WriteLine("Done");
}
Make sure excludedNumbers is a HashSet for best performance.
var random = new Random();
var exludedNumbers = new HashSet<int>(new int[] { 3, 8, 80});
var randomNumber = (from n in Enumerable.Range(int.MinValue, int.MaxValue)
let number = random.Next(1, 90)
where !exludedNumbers.Contains(number)
select number).First();
Related
I'm very new to coding and I just can't wrap my head around Loops/Arrays/Randoms. I understand the concept but when it comes to applying it, I'm just lost.
Here I'm trying to generate 100 random numbers between 1-1000 and it has to output the maximum value. Here's my code so far:
Random rnd = new Random();
int nums = rnd.Next(0, 1001);
for (int i = 1; i <= 100; i++)
{
}
Console.WriteLine(nums);
Console.ReadLine();
It's only giving me one number. :(
I'd greatly appreciate any help!
Thanks!
You can accumulate your random generated number to the array and then by using Max function of the array you can find the maximum value
class Program
{
public static void Main(string[] args)
{
Random rnd = new Random();
int[] intArr = new int[100];
for (int i = 0; i < intArr.Length; i++)
{
int num = rnd.Next(1, 1000);
intArr[i] = num;
Console.WriteLine(num);
}
Console.WriteLine();
int maxNum = intArr.Max();
Console.WriteLine("The max num is:" + maxNum);
Console.ReadLine();
}
}
Click to watch online demo
You need to call rnd.Next() inside loop.
Random rnd = new Random();
for (int i = 1; i <= 100; i++)
{
int nums = rnd.Next(0, 1001);
Console.WriteLine(nums);
}
Console.ReadLine();
A good approach would be initializing a variable that stores your max. Then generate a random number within your iterative block and if it is greater than your max, set it as the new max.
Random r = new Random();
int max = 0; //declare our max variable
for(int i = 0; i < 100; i++)
{
int rand = r.Next(0, 1001);
if(rand > max) //if the new random value is greater than our max, set max = rand
max = rand;
}
Console.WriteLine(max); //Output the maximum value
Console.ReadLine();
If you want to output every random value and then output the max out of all the values generated, simply modify the code above by outputting rand within your loop as well.
Hope this helps!
I am not sure, are you asking like this?
Random random = new Random();
int[] nums = new int[100];
// when for loop ends, nums are full of 100 numbers
for (int i = 0; i < nums.Length; i++)
{
int newNum = random.Next(1, 1000);
// show every number
Console.WriteLine(newNum);
nums[i] = newNum;
}
// get the max number
var maxNum = nums.Max();
Console.WriteLine(maxNum);
If you want to see the code for Loops/Arrays/Randoms all working together you can use the below with the comments walking through what each line is doing (Working .NET Fiddle Example)
public static void Main()
{
// Pass in what range we want our randomly generated numbers to be in
// In your case, between 1 - 1000 and we want to create 100 of them.
//(See GenerateRandomNumbers())
var random = GenerateRandomNumbers(1, 1000, 100);
//Take our newly returned randomly created numbers and
//pass them to our GetMaxNumber method so it can find the Max number
//See (GetMaxNumber())
var result = GetMaxNumber(random);
//We now have our max number; print it to the Console.
Console.WriteLine("Max: " + result);
}
public static int GetMaxNumber(params int[] inputs)
{
//Create a variable that will store the largest number we find in our array
int max = inputs[0];
//Iterate (loop) through all of the 100 values in our array that we passed in
//Here we define "input" which will hold the value for each value in inputs as we check
//if the value of input is greater than our current value of max. If it is greater than our
//current value of max, then we need to update max to now be equal to the value of our input.
//Note: it will do this comparison 100 times beginning with the first value in the inputs array
foreach (var input in inputs)
{
if (input > max)
{
//input's value is greater than the current value of max; update max so that it is equal to the current value of input.
max = input;
}
//no more code; return to top of foreach loop and set input to the next value in inputs
}
//When we get here, it means our foreach loop has completed going through and comparing all 100 values of inputs to see which value is the largest.
//now return this value to Main()
return max;
}
public static int[] GenerateRandomNumbers(int beginRange, int endRange, int maxNumbers)
{
// Instantiate random number generator
Random rnd = new Random();
//Generate and display
int[] intArr = new int[maxNumbers];
//Generate 100 numbers with numbers between 1 and 1000
for (int i = 0; i < intArr.Length; i++)
{
int num = rnd.Next(beginRange, endRange);
intArr[i] = num;
}
return intArr;
}
I have 5 fields, I want them all to have a generated number between 0 and 100. But, the sum of the 5 fields should be 100.
When I want to give a random number for one field I would do the following:
Random rnd = new Random();
int x= rnd.Next(1, 10);
But how should I do that for multiple fields that needs to have a sum of 100 together?
You can use the following approach:
generate 4 random integers in [0, 100]
sort them, let's denote the sorted values as 0 ≤ x1 ≤ x2 ≤ x3 ≤ x4 ≤ 100
use the following 5 values as the random numbers with sum 100:
N1 = x1
N2 = x2 - x1
N3 = x3 - x2
N4 = x4 - x3
N5 = 100 - x4
It basically corresponds to randomly choosing 4 sectioning points on the [0, 100] interval, and using the lengths of the 5 resulting intervals as the random numbers:
const int k = 5;
const int sum = 100;
Random rnd = new Random();
int[] x = new int[k + 1];
// the endpoints of the interval
x[0] = 0;
x[k] = sum;
// generate the k - 1 random sectioning points
for (int i = 1; i < k; i++) {
x[i] = rnd.Next(0, sum + 1);
}
// sort the sectioning points
Array.Sort(x);
// obtain the k numbers with sum s
int[] N = new int[k];
for (int i = 0; i < k; i++) {
N[i] = x[i + 1] - x[i];
}
In order to make your distribution uniform, you could try the following aproach:
Generate some random numbers.
Normalize them.
Correct the last field to get exactly the expected sum, if needed.
The code:
const int ExpectedSum = 100;
Random rnd = new Random();
int[] fields = new int[5];
// Generate 4 random values and get their sum
int sum = 0;
for (int i = 0; i < fields.Length - 1; i++)
{
fields[i] = rnd.Next(ExpectedSum);
sum += fields[i];
}
// Adjust the sum as if there were 5 random values
int actualSum = sum * fields.Length / (fields.Length - 1);
// Normalize 4 random values and get their sum
sum = 0;
for (int i = 0; i < fields.Length - 1; i++)
{
fields[i] = fields[i] * ExpectedSum / actualSum;
sum += fields[i];
}
// Set the last value
fields[fields.Length - 1] = ExpectedSum - sum;
Live example: https://dotnetfiddle.net/5yXwOP
To achieve a truly random distribution, with every element having the chance to be 100 with a total sum of 100, you can use the following solution:
public static int[] GetRandomDistribution(int sum, int amountOfNumbers)
{
int[] numbers = new int[amountOfNumbers];
var random = new Random();
for (int i = 0; i < sum; i++)
{
numbers[random.Next(0, amountOfNumbers)]++;
}
return numbers;
}
static void Main(string[] args)
{
var result = GetRandomDistribution(100, 5);
}
It increases a random number by one until the sum is reached. This should fulfill all your criterias.
After thinking about it, I prefer the following solution, because it's less likely to generate an equal distribution:
public static int[] GetRandomDistribution2(int sum, int amountOfNumbers)
{
int[] numbers = new int[amountOfNumbers];
var random = new Random();
for (int i = 0; i < amountOfNumbers; i++)
{
numbers[i] = random.Next(sum);
}
var compeleteSum = numbers.Sum();
// Scale the numbers down to 0 -> sum
for (int i = 0; i < amountOfNumbers; i++)
{
numbers[i] = (int)(((double)numbers[i] / compeleteSum) * sum);
}
// Due to rounding the number will most likely be below sum
var resultSum = numbers.Sum();
// Add +1 until we reach "sum"
for (int i = 0; i < sum - resultSum; i++)
{
numbers[random.Next(0, amountOfNumbers)]++;
}
return numbers;
}
For Example.
int sum=100;
int i = 5;
Random rnd = new Random();
while (true)
{
int cur;
--i;
if (i == 0) {
Console.WriteLine(sum + " ");
break;
} else
cur=rnd.Next(1, sum);
sum -= cur;
Console.WriteLine(cur + " ");
}
Live Example: https://dotnetfiddle.net/ltIK40
or
Random rnd = new Random();
int x= rnd.Next(1, 10);
int y= rnd.Next(x,x+10);
int y2=rnd.Next(y,y+10);
int y3=rnd.Next(y2,y2+10);
int y4=100-(x+y+y2+y3);
My approach is this:
var rnd = new Random();
var numbers = Enumerable.Range(0, 5).Select(x => rnd.Next(0, 101)).ToArray().OrderBy(x => x).ToArray();
numbers = numbers.Zip(numbers.Skip(1), (n0, n1) => n1 - n0).ToArray();
numbers = numbers.Concat(new[] { 100 - numbers.Sum() }).ToArray();
This is as uniform as I think is possible.
Create your first random number. After that you take the difference between the value of num1 and 100 as the max def of rnd. But to guarantee that their sum is 100, you have to check at the last num if the sum of all nums is 100. If not the value of your last num is the difference that their sum and 100.
And to simply your code and get a clean strcuture, put that code in a loop and instead of single numbers work with an int[5] array.
private int[] CreateRandomNumbersWithSum()
{
int[] nums = new int[5];
int difference = 100;
Random rnd = new Random();
for (int i = 0; i < nums.Length; i++)
{
nums[i] = rnd.Next(0, difference);
difference -= nums[i];
}
int sum = 0;
foreach (var num in nums)
sum += num;
if (sum != 100)
{
nums[4] = 100 - sum;
}
return nums;
}
I think this is a very simple solution:
public void GenerateRandNr(int total)
{
var rnd = new Random();
var nr1 = rnd.Next(0, total);
var nr2 = rnd.Next(0, total - nr1);
var nr3 = rnd.Next(0, total - nr1 - nr2);
var nr4 = rnd.Next(0, total - nr1 - nr2 - nr3);
var nr5 = total - nr1 - nr2 - nr3 - nr4;
}
EDIT:
Just tested it, works fine for me:
The solution is that it's not the numbers that need to be random so much as the distribution needs to be random. The randomness of the numbers will be a side effect of their random distribution.
So you would start with five random numbers in a given range. The exact range doesn't matter as long as the range is the same for all five, although a broader range allows for more variation. I'd use Random.NextDouble() which returns random numbers between 0 and 1.
Each of those individual numbers divided by the sum of those numbers represents a distribution.
For example, say your random numbers are .4, .7, .2, .5, .2. (Using fewer digits for simplicity.)
The total of those numbers is 2. So now the distributions are each of those numbers divided by the total.
.4 / 2 = .20
.7 / 2 = .35
.2 / 2 = .10
.5 / 2 = .25
.2 / 2 = .10
You'll notice that those distributions will equal 100% or really close to it if there are a lot more decimal places.
The output is going to be each of those distributions times the target number, in this case, 100. In other words, each of those numbers represents a piece of 100.
So multiplying each of those distributions times the target, we get 20, 35, 10, 25, and 100, which add up to 100.
The trouble is that because of rounding your numbers won't always perfectly add up to 100. To fix that you might add one to the smallest number if the sum is less than 100, or subtract one from the largest number of the the sum is greater than 100. Or you could choose to add or subtract on one of the numbers at random.
Here's a class to create the distributions. (I'm just playing around so I haven't exactly optimized this to death.)
public class RandomlyDistributesNumbersTotallingTarget
{
public IEnumerable<int> GetTheNumbers(int howManyNumbers, int targetTotal)
{
var random = new Random();
var distributions = new List<double>();
for (var addDistributions = 0; addDistributions < howManyNumbers; addDistributions++)
{
distributions.Add(random.NextDouble());
}
var sumOfDistributions = distributions.Sum();
var output = distributions.Select(
distribution =>
(int)Math.Round(distribution / sumOfDistributions * targetTotal, 0)).ToList();
RoundUpOutput(output, targetTotal);
return output;
}
private void RoundUpOutput(List<int> output, int targetTotal)
{
var difference = targetTotal - output.Sum();
if (difference !=0)
{
var indexToAdjust =
difference > 0 ? output.IndexOf(output.Min()) : output.IndexOf(output.Max());
output[indexToAdjust]+= difference;
}
}
}
And here's a not-perfectly-scientific unit test that tests it many times over and ensures that the results always total 100.
[TestMethod]
public void OutputTotalsTarget()
{
var subject = new RandomlyDistributesNumbersTotallingTarget();
for (var x = 0; x < 10000; x++)
{
var output = subject.GetTheNumbers(5, 100);
Assert.AreEqual(100, output.Sum());
}
}
Some sample outputs:
5, 30, 27, 7, 31
15, 7, 26, 27, 25
10, 11, 23, 2, 54
The numbers are always going to average to 20, so while 96, 1, 1, 1 is a hypothetical possibility they're going to tend to hover closer to 20.
Okay. Having been burned by my previous attempt at this seemingly trivial problem, I decided to have another go. Why not normalise all the numbers after generation? This guarantees randomness, and avoids O(n log n) performance from a sort. It also has the advantage that even with my basic maths, I can work out that the numbers are uniformly distributed.
public static int[] UniformNormalization(this Random r, int valueCount, int valueSum)
{
var ret = new int[valueCount];
long sum = 0;
for (int i = 0; i < valueCount; i++)
{
var next = r.Next(0, valueSum);
ret[i] = next;
sum += next;
}
var actualSum = 0;
for (int i = 0; i < valueCount; i++)
{
actualSum += ret[i] = (int)((ret[i] * valueSum) / sum);
}
//Fix integer rounding errors.
if (valueSum > actualSum)
{
for (int i = 0; i < valueSum - actualSum; i++)
{
ret[r.Next(0, valueCount)]++;
}
}
return ret;
}
This should also be one of the fastest solutions.
So basically, I need to have the numbers 1-10 randomly ordered upon startup into an array, and on when the form loads, it should load the first number. Each time the user clicks a button, it will load the info associated with the next number.
This is my code, but for some reason it generates a number that is not an integer a lot.
Random rng = new Random(10);
int[] QuestionOrder = new int[10];
for (int i = 0; i < QuestionOrder.Length; i++)
{
int temp = rng.Next(1,10);
while(!(QuestionOrder.Contains(temp)))
{
QuestionOrder[i] = temp;
}
}
each time it generates a number 1 - 10 and checks if it has already been stored in the array, if not, stores it and runs again.
For some reason, its generating numbers that are not integers 1 - 10, and i cant figure out why.
I think you need to overwrite the value of temp inside the while loop and change your range to 1-11 instead of 1-10 and use an if statement before the loop:
int temp = rng.Next(1, 11);
if(!QuestionOrder.Contains(temp)) QuestionOrder[i] = temp;
else
{
while(QuestionOrder.Contains(temp))
{
temp = rng.Next(1, 11);
QuestionOrder[i] = temp;
}
}
You could generate ten random numbers first, then iterate through them.
var rnd = new Random(Environment.TickCount);
var arr = Enumerable.Range(1,10).OrderBy(x => rnd.Next()).ToArray();
this does work nicely
static void Main(string[] args)
{
Random random = new Random();
var range = Enumerable.Range(1, 10).ToList();
int[] rnd = new int[10];
int j = 0;
do
{
int i = random.Next(0, range.Count);
rnd[j++] = range[i];
range.RemoveAt(i);
}
while(range.Count > 1);
rnd[j] = range[0];
}
less cpu intensive than using a contains in a loop
First, your seed is always the same. Either omit it, or use maybe the current date.
Second, you're generating numbers between 1 and 9, so you will never get 10, and one of your array cell will stay empty.
Change temp = rng.Next(1, 11);
As others have pointed out, you're not regenerating a new number when the generated number is already present in the list, leaving you with various default values of 0 in your result.
There are however better ways to 'shuffle' a list of numbers, see Randomize a List in C#:
public static IList<T> Shuffle<T>(this IList<T> list)
{
Random rng = new Random();
int n = list.Count;
while (n > 1)
{
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list;
}
Which you can call like this:
IList<int> QuestionOrder = Enumerable.Range(1, 10)
.ToList()
.Shuffle();
The best algorithm to shuffle an array is Knuth-Fisher-Yates, that can be implemented as follows:
public static class Extensions
{
public static void Shuffle<T>(this IList<T> list, Random rand)
{
for (int i = list.Count - 1; i > 0; i--)
{
int n = rand.Next(i + 1);
int tmp = list[i];
list[i] = list[n];
list[n] = tmp;
}
}
}
Usage:
// to get different random sequences every time, just remove the seed (1234)
Random rng = new Random(1234);
// create an array containing 1,2...9,10
int[] questionOrder = Enumerable.Range(1,10).ToArray();
// shuffle the array
questionOrder.Shuffle(rand);
Side note:
To know why Knuth-Fisher-Yates algorithm is better than a naive implementation, read this interesting post by Jeff
listBox1.Items.Clear();
int[] sayısal = new int[6];
Random rastgele = new Random();
for (int i = 0; i < 6; i++)
{
do
{
sayısal = rastgele.Next(1, 50);
}
while (listBox1.Items.IndexOf(sayısal) != -1);
listBox1.Items.Add(sayısal);
}
When I did like this, I take an error that calls
"Cannot implicitly convert type 'int' to 'int[]' "
in line "sayısal = rastgele.Next(1, 50);". What can I do for it?
You can generate sequence 1..50 and shuffle it (i.e. sort by random value):
Random rastgele = new Random();
int[] sayısal = Enumerable.Range(1, 50) // generate sequence
.OrderBy(i => rastgele.Next()) // shuffle
.Take(6) // if you need only 6 numbers
.ToArray(); // convert to array
Your code is not working, because you are trying to assign generated item to array variable.
sayısal = rastgele.Next(1, 50);
It should be instead:
do {
sayısal[i] = rastgele.Next(1, 50);
} while(listBox1.Items.IndexOf(sayısal[i]) != -1);
As I already pointed in comments, it's better to separate UI logic and array generation. I.e.
// generate array (optionally move to separate method)
int itemsCount = 6;
int[] items = new int[itemsCount]; // consider to use List<int>
Random random = new Random();
int item;
for(int i = 0; i < itemsCount; i++)
{
do {
item = random.Next(1, 50);
} while(Array.IndexOf(items, item) >= 0);
items[i] = item;
}
// display generated items
listBox1.Items.Clear();
for(int i = 0; i < items.Length; i++) // or use foreach
listBox1.Items.Add(items[i]);
Because Random.Next method returns an int, not int[]. And there is no implicit conersation from int[] to int.
Return Value
Type: System.Int32
A 32-bit signed integer greater than or equal to minValue and less than maxValue; that is, the range of return values includes minValue but not maxValue. If minValue equals maxValue, minValue is returned.
If you want to fill your array, you can use Enumerable.Range like lazyberezovsky mentioned.
This method takes an integer array and randomly sorts them.
So fill an array with a loop then use this to randomly sort the array.
You should credit one of the others as they were first to post with valid answers. I just thought another way to do this would be good.
amount is the amount of times you want the array to randomize. The higher the number the higher the chance of numbers being random.
private Random random = new Random();
private int[] randomizeArray(int[] i, int amount)
{
int L = i.Length - 1;
int c = 0;
int r = random.Next(amount);
int prev = 0;
int current = 0;
int temp;
while (c < r)
{
current = random.Next(0, L);
if (current != prev)
{
temp = i[prev];
i[prev] = i[current];
i[current] = temp;
c++;
}
}
return i;
}
Be careful in your choice of data structures and algorithms, pick the wrong one and you'll wind up with O(n^2). A reasonable solution IMHO is a typed hash table (i.e. dictionary) which will give you O(n):
Random rnd = new Random();
var numbers = Enumerable
.Range(1, 1000000)
.Aggregate(new Dictionary<int, int>(), (a, b) => {
int val;
do {val = rnd.Next();} while (a.ContainsKey(val));
a.Add(val, val);
return a;
})
.Values
.ToArray();
Still not ideal though as performance depends on the array size being significantly smaller than the set of available numbers and there's no way to detect when this condition isn't met (or worse yet when it's greater, in which case the algorithm will go into an infinite loop).
I'm trying to create a method that produces 10 unique random numbers, but the numbers are not unique, I get several duplicates! How can I improve the code to work as I want?
int[] randomNumbers = new int[10];
Random random = new Random();
int index = 0;
do
{
int randomNum = random.Next(0, 10);
if (index == 0)
{
randomNumbers[0] = randomNum;
index++;
}
else
{
for (int i = 0; i < randomNumbers.Length; i++)
{
if (randomNumbers[i] == randomNum)
break;
else
{
randomNumbers[index] = randomNum;
index++;
break;
}
}
}
}
while (index <= 9);
foreach (int num in randomNumbers)
System.Console.Write(num + " ");
EDIT 2: I have corrected all errors now, but this code isn't working becuase the numbers are not unique! I have updated my code above to the latest version. I preciate some help to solve this! Thanks!
The simplest way to have this is to have an array of the numbers you want (i.e. 1-10) and use a random shuffling algorithm.
The Fisher-Yates shuffle is the easiest way to do this.
EDIT:
Here's a link to a C# implementation: http://www.dotnetperls.com/fisher-yates-shuffle
random.next(0, 10) returns a random number between 0 and 10. It can happen, that it returns the same number multiple times in a row and it is not guaranteed, that you get every number between 0 and 10 exactly one time, when you call it 10 times.
What you want is a list of numbers, every number is unique, between 0 and 9 (or 1 and 10). A possible solution to this would be something like this:
//Create the list of numbers you want
var list = new List<int>();
for(var x = 0; x < 10; x++)
{
list.Add(x);
}
var random = new Random();
//Prepare randomized list
var randomizedList = new List<int>();
while(list.Length > 0)
{
//Pick random index in the range of the ordered list
var index = random.Next(0, list.Length);
//Put the number from the random index in the randomized list
randomizedList.Add(list[index]);
//Remove the number from the original list
list.RemoveAt(index);
}
Explained in words, this is what you do:
Create the list with all the numbers, that your final list should contain
Create a second empty list.
Enter a loop. The loop continues, as long as the ordered list still has numbers in it.
Pick a random index between 0 and list.Length
Put this random number in the randomized list
Remove the item at the index position from the ordered list.
Like this you create the set of numbers you want to have in your randomized list and then always pick a random entry from the ordered list. With this technique, you can also achieve, that certain values occur multiple time in the list.
I'm not sure if my code compiles against c#, as I currently do not have visual studio running here, but I think the code should be mostly correct.
Something like this?
const int maxNumbers = 10;
List<int> numbers = new List<int>(maxNumbers);
for (int i = 0; i < maxNumbers; i++)
{
numbers.Add(i);
}
Random r = new Random();
while (numbers.Count > 0)
{
int index = r.Next(numbers.Count);
Console.Write("{0} ", numbers[index]);
numbers.RemoveAt(index);
}
Console.WriteLine();
Edit: For any random numbers:
const int maxNumbers = 10;
const int biggestNumbers = 10000;
List<int> numbers = new List<int>(maxNumbers);
Random r = new Random();
while (numbers.Count < maxNumbers)
{
int index = r.Next(biggestNumbers);
if (numbers.IndexOf(index) < 0)
{
numbers.Add(index);
Console.Write("{0} ", index);
}
}
Console.WriteLine();