Constantly generating unique and random values in a specific range in C# - c#

I am implementing this code in my discord bot, where I want to be able to generate unique numbers from 1 to 10 (as suggested above) whenever I input a single command.
Turns out that the values sometimes are repeated. Therefore I was suggested to add an array (used[ ]) and a loop in order to check every time if the value has been generated already.
Random random = new Random();
int[] used = new int[10];
int rng = 0;
while (!used.Contains(rng))
{
rng = random.Next(1, 10);
}
/*
I wish to store the generated value "rng" to the "used" array.
e.g.
used[0] = rng
used[1] = rng
used[2] = rng
etc.
*/
Console.WriteLine("The number generated is " + Convert.ToString(rng));
However, I don't know how to constantly add values to an array in an arranged order. (as seen by the commentations above)
In a more simple way, For 10 times I want the system to generate a number, and those numbers are randomly picked out of [1,10] and only once. If all the numbers have been generated once, all are free to be generated again.
Sorry for my bad interpretation. I have refined it with the comments that everyone has contributed.

Here is a solution, that shuffles the values and returns each value until the list is exhausted, then starts all over:
int[] GenerateNewArray(int n)
{
// Define an array of values we wish to return and populate it
int[] baseValues = Enumerable.Range(1, n).ToArray();
Random rnd=new Random();
// Shuffle the array randomly using Linq
return baseValues.OrderBy(x => rnd.Next()).ToArray();
}
void Main()
{
int nNumbers = 10;
while (true)
{
// Generate a new randomized array
var values = GenerateNewArray(nNumbers);
// Print each value
for (int i=0;i<nNumbers;i++)
{
Console.WriteLine($"The number generated is {values[i]}");
}
}
}
EDIT
Parameterized the number of unique values.

Rather than storing in an array, looking for duplicates etc., just use a HashSet
This only accepts unique values, and if you try to add a duplicate it will be simply ignored.
Or you can just do a check to see if it exists
HashSet<int> integerSet = new HashSet<int>();
if (hashSet.Contains(rng ))
// element already exists in set
else
//Doesn't exist
Of course, if you just keep generating each number randomly until you have generated everything in the range, then you might as well just simply generate an array/list of elements with every number and save yourself processing time!

Using a list is a good way to start, but before continuing the comment go check out the list documentation
In small talk a list is an IEnumerable of a type you choose, in your case to declare and instanciate a list you should write like this List<int> listName = new List<int>(); and the main difference between an array and a list is that you can populate the list whenever you want without the length declaration, to do that you can add listName.Add(2); (2 : the integer value that you want to add) or remove values listName.Remove(0) (0 : the position of the list that need to be removed, ex: 0 is the first value inside the list because position 0 is the start)
Random random = new Random();
List<int> listName = new List<int>();
int rng = 0, counterOfValues = 0;
while (counterOfValues < 10)
{
rng = random.Next(1, 10);
If(!listName.Contains(rng))
{
listName.Add(rng);
Console.WriteLine("The number generated is " + listName.Last().ToString());
If(counterOfValues < 10)
{
counterOfValues++;
}
else
{
counterOfValues = 0;
}
}
}
This should probably do the work ("should" because it's some code I wrote out of my head, so sorry about caps ecc)
Let me know if it works as intended or we need to correct something!
P.S: If you want the user to select the range of the randomic values just change the value of counterOfValues in the lowest value and the 10's with the higher value

Using a HashSet is better to know the numbers that you are use. But in your case, I think it's better use a List and remove elements:
var list = new List<int>();
for (int i = 1; i <= 10; i++)
list.Add(i);
// List is 0-index
// list = 1 2 3 4 5 6 7 8 9 10
int rng = random.Next(0, list.Count - 1);
// Suppose rgn=3: You get 3 value and remove it from the list
var value = list[rgn];
list.RemoveAt(rgn);
// list = 1 2 4 5 6 7 8 9 10
// Now you get a value between 0...8 (list.Count is 9)
rng = random.Next(0, list.Count - 1);
// Suppose rgn=3: You get 4 value and remove it from the list
var value = list[rgn];
list.RemoveAt(rgn);
// list = 1 2 5 6 7 8 9 10
// Now you get a value between 0...7 (list.Count is 8)
rng = random.Next(0, list.Count - 1);
// Suppose rgn=5: You get 7 value and remove it from the list
var value = list[rgn];
list.RemoveAt(rgn);
// list = 1 2 5 6 8 9 10
...
When list has one element you don't need use random.
When your list is empty, fill again and repeat the whole process.
In this form you always get an element with each random call. Using HashSet you may try a lot of random calls to get a nonused number.
A class for that maybe:
public class RandomClass
{
private readonly List<int> _list;
private readonly Random _random;
public RandomClass()
{
this._list = new List<int>();
this._random = new Random();
}
private void PopulateList()
{
for (int i = 1; i <= 10; i++)
this._list.Add(i);
}
public int GetNumber()
{
if (this._list.Count == 0)
{
this.PopulateList();
}
if (this._list.Count > 1)
{
int rng = this._random.Next(0, this._list.Count);
var value = this._list[rgn];
this._list.RemoveAt(rgn);
return value;
}
else
{
var value = this._list[0];
this._list.RemoveAt(0);
return value;
}
}
}
UPDATE: Some about List, Arrays and other collections
Array and List are very similar. The main difference is that an array is a continuous block of memory while List (in memory) it's not a block. Array is faster to iterate (address of first element + multiply for sizeof each element) but slower when you want to add/remove elements (you must create other array and copy the elements). From the point of view of an user, both of them are used to store a list of items and iterate them.
Other collections very interesting are HashSet and Dictionary. These collections are sets, you can't access their elements using an index. You saw an example for HashSet in this page: Add a number to the set and query it if you want know if that number appear before. The key with this sets are that you access to their elements using a hash. Instead of an index, you use whatever you want as a key and an algorithm get quickly the position of the element in the set. Dictionary is like a HashSet but you can store addicional data asociated to the key.
In many cases, you'll use both of them: a list to iterate sequencially and a dictionary to direct access to elements. For example, you have a lot of Persons that you show in some order (name, surname...). You store them in a List an allow user to change the order (using Sort of the list). You use a list because you show and use that order many times: you need ordered Persons.
But you have many, many Persons. Suppose that your program allow search Persons by Id and Name. Each time a user search for Persons you must iterate a very long list. It's not efficient. So you define two Dictionary:
Dictionary<int, List<Person>> personsById;
Dictionary<string, List<Person>> personsByName;
Also, you have a List:
List<Person> allPersons;
And we need some operations:
public void AddPerson(Person person)
{
Person existingPerson;
if (personsById.TryGetValue(person.Id, out existingPerson))
{
// Already exists: don't add duplicated persons
return;
}
personsById.Add(person.Id, person);
// Maybe more than one person with the same name. It's the reason why use a List here
List<Person> list;
if (personsByName.TryGetValue(person.Name, out list))
{
// There are other persons with this name, so the list exists. Simply add person to list
list.Add(person);
}
else
{
// Is the first person with this name: create the list and associate to the name
personsByName.Add(person.Name, new List<Person> { person });
}
// Always add to main list
allPersons.Add(person);
}
public void RemovePerson(Person person)
{
if (!personsById.TryGetValue(person.Id, out _))
{
// Not exists: do nothing
return;
}
personsById.Remove(person.Id);
// NOTE: Here we are removing person assuming that you never have different instances
// of person. If you can create different instances for a person, here we must iterate
// the lists to find the person
List<Person> list;
if (personsByName.TryGetValue(person.Name, out list))
{
list.Remove(person);
}
allPersons.Remove(person);
}
public Person GetPerson(int id)
{
return this.personsById.TryGetValue(id, out Person person) ? person : null;
}
public List<Person> GetPersons(string name)
{
return this.personsByName.TryGetValue(name, out List<Person> list) ? list : null;
}
It's a very basic example but I think maybe a good one to learn about this classes.

Related

How do I randomly select a newly created string from a list?

I have a list that is filled with words in order to generate passwords. A number from 1 to 48 is to be appended to these words via the while loop. I then randomly select three elements from this list. The selected elements are saved in an Excel list. The words are saved in the Excel list, but the consecutive number from the while loop is not appended to the word or only the word is displayed in the Excel list. It does not yet work the way I want it to. How do I append a number to a string from a list and call the newly generated string, by random selection, to save it in an Excel list? I ask for your support.
Here my Method with the while-loop:
public string GeneratePassword()
{
int num = 1;
var names = new List<string> { "Ananas","Auto","Affe","Ameise","Apfel","Biene","Baum","Birne","Ball","Blume","Cello","Chips"};
int index = random.Next(names.Count);
while (num < 49)
{
string name = names[index] + num;
names.Add(name);
num++;
names.RemoveAt(index);
}
return names[index];
}
Here the section where i call the method:
Program pw = new Program();
var login = new List<string> { "Z00001", "Z00002", "Z00003" };
ws.Cells["B1"].LoadFromArrays(new List<string[]>(new[] { login.ToArray() }));
var password = new List<string> { pw.GeneratePassword(), pw.GeneratePassword(),
pw.GeneratePassword() };
ws.Cells["B2"].LoadFromArrays(new List<string[]>(new[] { password.ToArray() }));
One thing that's sometimes helpful is to break the problem down into discreet parts, then write a method that performs just a single thing for each part. In this case, we want to generate a list of names, add random numbers to the end of each name, and then pick a random item from the list (but don't pick the same item more than once).
One way to pick a random item from a list until all items are picked is to sort the list randomly, then take from the list sequentially (removing the item as you take it).
Below are some methods that I think will help. One that gets the names, one that randomly sorts the list, one that adds a random number to each item in a list, and then the main one (GetPassword), which returns and removes the first item from the list. It also generates the list if needed.
private static Random rnd = new Random();
private static List<string> passwords = new List<string>();
// Returns a list of names
public static List<string> GetNames()
{
return new List<string> {
"Ananas","Auto","Affe","Ameise","Apfel","Biene","Baum",
"Birne","Ball","Blume","Cello","Chips"};
}
// Sorts a list in random order
public static List<string> RandomSort(List<string> items)
{
return items.OrderBy(item => rnd.Next()).ToList();
}
// Returns a list of the input items with a random
// number added to the end of each item
public static List<string> AppendNumberToItems(List<string> input,
int min = 1, int max = 48)
{
var newItems = new List<string>();
foreach(var item in input) newItems.Add(item + rnd.Next(min, max + 1));
return newItems;
}
// Returns the next password in our password list
public static string GetPassword()
{
// In case we're out of passwords, generate some new ones
if (passwords.Count == 0) passwords =
AppendNumberToItems(RandomSort(GetNames()), 1, 48);
// Take the first password from the list
string password = passwords[0];
// Then remove that password from the list
passwords = passwords.Skip(1).ToList();
// And return it
return password;
}

Avoiding 'System.OutOfMemoryException' while iterating over a IEnumerable<IEnumerable<object>>

I have the following code to get the cheapest List of objects which satisfy the requiredNumbers criteria. This list of objects can have a length varying from 1 to maxLength, i.e. there can be a combination of 1 to maxLength of objects with repitition allowed. Right now, this this iterates over the whole list of combinations (IEnumerable of IEnumerable of OBJECT) fine till maxLength = 9 and breaks after that with a "System.OutOfMemoryException" at
t1.Concat(new OBJECT[] { t2 }
I tried another approach to solve this (mentioned in the code comments), but that seems to have its own demons. What I understand right now is , I'll have to somehow know the least priced combination of objects without iterating over the whole List of combination, which I can't seem to find feasible.
Could someone suggest any changes that let the maxLength be higher(much higher ideally), without hindering the performance. Any help is much appreciated. Please let me know if I am not clear.
private static int leastPrice = int.MaxValue;
private IEnumerable<IEnumerable<OBJECT>> CombinationOfObjects(IEnumerable<OBJECT> objects, int length)
{
if (length == 1)
return objects.Select(t => new OBJECT[] { t });
return CombinationOfObjects(objects, length - 1).SelectMany(t => objects, (t1, t2) => t1.Concat(new OBJECT[] { t2 }));
}
//Gets the least priced Valid combination out of all possible
public IEnumerable<OBJECT> GetValidCombination(IEnumerable<OBJECT> list, int maxLength, int[] matArray)
{
IEnumerable<IEnumerable<OBJECT>> tempList = null;
List<IEnumerable<OBJECT>> validList = new List<IEnumerable<OBJECT>>();
for (int i = 1; i <= maxLength; i++)
{
tempList = CombinationOfObjects(list, i);
tempList = from alist in tempList
orderby alist.Sum(x => x.Price)
select alist;
foreach (var lst in tempList)
{
//This check will not be required if the least priced value is returned as soon as found
int price = lst.Sum(c => c.Price);
if (price < leastPrice)
{
if (CheckMaterialSum(lst, matArray))
{
validList.Add(lst);
leastPrice = price;
break;
//return lst;
//returning lst as soon as valid combo is found is fastest
//Con being it also returns the least priced least item containing combo
//i.e. even if a 4 item combo is cheaper than the 2 item combo satisfying the need,
//it'll never even check for the 4 item combo
}
}
}
}
//This whole thing would go too if lst was returned earlier
foreach (IEnumerable<OBJECT> combination in validList)
{
int priceTotal = combination.Sum(combo => combo.Price);
if (priceTotal == leastPrice)
{
return combination;
}
}
return new List<OBJECT>();
}
//Checks if the given combination satisfies the requirement
private bool CheckMaterialSum(IEnumerable<OBJECT> combination, int[] matArray)
{
int[] sumMatProp = new int[matArray.Count()];
for (int i = 0; i < matArray.Count(); i++)
{
sumMatProp[i] = combination.Sum(combo => combo.Numbers[i]);
}
bool isCombinationValid = matArray.Zip(sumMatProp, (requirement, c) => c >= requirement).All(comboValid => comboValid);
return isCombinationValid;
}
static void Main(string[] args)
{
List<OBJECT> testList = new List<OBJECT>();
OBJECT object1 = new OBJECT();
object1.Name = "object1";
object1.Price = 2000;
object1.Numbers = new int[] { 2, 3, 4 };
testList.Add(object1);
OBJECT object2 = new OBJECT();
object2.Name = "object2";
object2.Price = 1900;
object2.Numbers = new int[] { 3, 2, 4 };
testList.Add(object1);
OBJECT object3 = new OBJECT();
object3.Name = "object3";
object3.Price = 1600;
object3.Numbers = new int[] { 4, 3, 2 };
testList.Add(object1);
int requiredNumbers = new int[]{10,10,10};
int maxLength = 9;//This is the max length possible, OutOf Mememory exception after this
IEnumerable<OBJECT> resultCombination = GetValidCombination(testList, maxLength, requiredNumbers);
}
EDIT
Requirement:
I have a number of objects having several properties, namely, Price, Name , and Materials. Now, I need to find such a combination of these objects that the sum of all materials in a combination satisfies the user input qty of materials. Also, the combination needs to be of least price possible.
There is a constraint of maxLength and it sets the maximum total number of objects that can be in a combination, i.e. for a maxLength = 8, the combination may contain anywhere from 1 to 8 objects.
Approaches tried:
1.
-I find all combinations of objects possible (valid + invalid)
-Iterate over them to find the least priced combination. This goes out of memory while iterating.
2.
-I find all combinations possible (valid + invalid)
-Apply a validity check (i.e if it fulfills the user requirement)
-Add only valid combinations in a List of List
-Iterate over this valid List of lists to find the cheapest list and return that. Also goes out of memory
3.
-I find combinations in increasing order of objects (i.e. first all combinations having 1 object, then 2 then so on...)
-Sort the combinations according to price
-Apply validity check and return the first valid combination
-Now this works fine performance wise, but does not always return the cheapest possible combination.
If I could somehow get the optimal solution without iterating over the whole list , that would solve it. But, all of the things that I've tried either have to iterate over all combinations or simply do not result in the optimal solution.
Any help regarding even some other approach that I can't seem to think of is most welcome.

How can I always have a different random phrase selected when using a random? [duplicate]

This question already has answers here:
Randomize a List<T>
(28 answers)
Closed 5 years ago.
I have this code:
public async Task ShowTimedCard()
{
phrase = phrases[(int)AS.rand.Next(phrases.Count)];
It gets a random number and then selects a phrase from phrases which is a List of phrase rows. The List has items added and removed from it by a background process.
Each phrase has an Id field. I cannot remove phrases that I have used from the List for other reasons.
Sometimes ShowTimedCard picks the same phrase twice in a row so I decided to store the lastPhrase information in a static variable like this:
AS.phrase.id = phrase.id
How can I make it so if there are more than 1 items in the phrases List then it will not pick the same phrase twice in a row? I was thinking of some kind of while loop or until loop but not sure how to implement that. I guess it needs to compare the phrase.Id with the AS.phrase.id
Show where you create rand
You should create it just once and reuse it
I bet you are creating new and not enough tick to get a new seed
OK I may have missed the question
Just shuffle the List using Yates shuffle
This is byte but you get the idea
for (byte i = (byte)(count - 1); i >= 1; i--)
{
byte k = (byte)rand.Next(i + 1);
if (k != i)
{ // exchange the values
curVal = deck[i];
deck[i] = deck[k];
deck[k] = curVal;
}
}
Or store the used id in a hashset
Random rand = new Random();
HashSet<int> hs = new HashSet<int>();
int next;
while (hs.Contains(next = rand.Next(12))) { }
hs.Add(next)
Moving target
while (next = rand.Next(12) == lastNext) { }
lastNext = next;
It sounds like what you really want to do is sort the list randomly and then you can just take consecutive items. This will ensure that you don't see any item before all the others have been displayed, but they won't be displayed in the order they were added:
// Shuffle our list of phrases, so they're in a random order
var rnd = new Random();
phrases = phrases.OrderBy(p => rnd.NextDouble()).ToList();
You can then re-shuffle the list anytime you want, like if you add new items or when you've reached the end of the list.
Here's a quick demo using integers:
// Create a list of consecutive integers and display it
var numbers = Enumerable.Range(1, 30).ToList();
Console.WriteLine("Original list:");
Console.WriteLine(string.Join(", ", numbers));
// Shuffle the list and display it again
var rnd = new Random();
numbers = numbers.OrderBy(n => rnd.NextDouble()).ToList();
Console.WriteLine("\nShuffled list:");
Console.WriteLine(string.Join(", ", numbers));
Output

Create array without duplicates c#

So this is my code right now, and I need help so it won't makes duplicates. I need this for school so if you could explain a little bit too it would be helpful. Btw don't care about the comments it's on Swedish
int temp;
int[] myArray = new int[20]; // Array med 20 tal
Random random = new Random(); // Skapar metoden "Random"
for (int i = 0; i < myArray.Length; i++) // Forloop med 20 positioner
{
myArray[i] = random.Next(1, 100); // Ger random värden till dessa 20 positionerna
for (int j = 0; j < myArray.Length; j++)
{
if (myArray[i] > myArray[j]) // Array [i] större än Array [j]
{
//temp = myArray[j];
//myArray[j] = myArray[i];
//myArray[i] = temp;
}
}
Console.Write(myArray[i] + " ");
}
you can try linq to .Distinct() and to convert it to array use .ToArray()
var s = { 5, 7, 7, 4, 3};
var q = s.Distinct().ToArray();
At it's simplest, it looks like you probably want to
private static Random rng = new Random(); //class level definition
var myArray = Enumerable.Range(1, 20).OrderBy(X => rng.Next()).ToArray();
Alternatively, if this is for school and you need to justify your code... fill an array with the numbers 1 to 20, then use a Fisher-Yates shuffle to randomise the order of the array.
See: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
Since the array has exatly the size of the random value range (which is 20), you will get every number exactly once. It's easiest to create every number once using Enumerable.Range and only change the order in which they appear.
Changing the order can be done by OrderBy(), while random is used here.
This is all based on IEnumerable<T>. So it needs to be put into an array, which is simply done by calling ToArray().
public int[] RandomlyOrderedValues()
{
Random random = new Random();
return Enumerable.Range(1, 20).OrderBy(x => random.Next()).ToArray();
}
I'm not your teacher but hope you still play around by yourself, read the docs and finally express it in your own words.
Changed question, now the random range is larger than the array size.
It's always best to work with IEnumerable<T>, there you get the most powerful tools.
// let's create inifite number of random values:
// note that the Random instance needs to be created only once,
// so it's put into a field.
private Random random = new Random();
public IEnumerable<int> InfiniteRandomValues()
{
while (true)
{
yield return random.Next(1, 100);
}
}
public int[] GetUniqueRandomValues(int numberOfValues)
{
return InfiniteRandomValues()
// only uninque values
.Distinct()
// generate the requested number of distinct values
.Take(numberOfValues)
// put it into an array.
.ToArray();
}
How does it work? When you create random values, you don't know how many it will be, because you cannot know how many duplicates it will create. A generator for an infinite number of values has certainly enough values. Think of it as a factory. Only when the IEnumerable is iterated, the values are created.
This is called "deferred execution". Only when you iterate the IEnumerable, the values are requested by the source.
Distinct works like this. It returns only as many distinct values as are requested by its caller.
Which is Take. This one reduces the number of items that are taken, but still doesn't iterate itselves.
ToArray finally iterates its source and pulls as many values as there are. Read it backwards now: It takes all values from Take, which returns 20. Itselves it takes 20 values from Distinct, which iterates its source until it got 20 distinct values. Distinct takes its values from the InifiteRandomNumbers factory and can take as many as it needs.
When you finally understand how these things work, you can use it quite intuitively.
Another, more classic implemenation
private int[] GetRandomValues()
{
Random random = new Random();
int[] values = new int[20];
for(int i = 0; i < 20; i++)
{
// create random values until you found a distinct oune.
int nextValue;
do
{
nextValue = random.Next(1, 100);
} while (ContainsValue(values, i, nextValue))
values[i] = nextValue;
}
return values;
}
// When adding the values to a List instead of an array, it would be
// much easier, but need copying the vlaues to the array at the end.
// When using the array directly, you have to know which values you
// already generated, because it's initialized with zero.
// This method checks wether the value is in the array within
// the items until endIndex.
private bool ContainsValue(int[] values, int endIndex, int valueToFind)
{
// simple linq way:
// return values.Take(endIndex).Contains(valueToFind);
// classic way:
for(int i = 0; i < endIndex; i++)
{
if (values[i] = valueToFind) return true;
}
return false;
}

picking random name from text file in c# windows forms non repeatable

I was wondering how get on with this code, currently working on a tournament bracket system.
Currently I have created a comboBox that fetches all the lines from "log.txt" there are 16 lines in the txt file; then I created a assign button that is supposed to assign all the names into 16 textboxes called User1 --> User16, however the same name cant be repeated.
I looked at "Array of list" & "Array of string", but I seem to be stuck since I cant really figure out what to put in the code.
my random button looks like this at the moment:
private void assign_Click(object sender, EventArgs e)
{
int x;
Random rnd = new Random();
x = rnd.Next(0, 16);
User1.Text = comboBox2.Items[x].ToString();
x = rnd.Next(0, 16);
User2.Text = comboBox2.Items[x].ToString();
x = rnd.Next(0, 16);
User3.Text = comboBox2.Items[x].ToString();
x = rnd.Next(0, 16);
User4.Text = comboBox2.Items[x].ToString();
and so on untill i hit
x = rnd.Next(0, 16);
User16.Text = comboBox2.Items[x].ToString();
}
One of the simplest, but not necessarily most efficient, way to do this is to put all your strings into a List<string> and remove them randomly one-by-one. This would work a lot better if you put all your textboxes into a collection as well. For example, given a list of strings called myStrings and a collection of textboxes called myTextboxes, you could:
for (var i=0; i < myStrings.Count; i++)
{
var idx = rnd.Next(0, myStrings.Count);
myTextboxes[i].Text = myStrings[idx]; // Note: we are assuming the two collections have
// the same length
myStrings.RemoveAt(idx);
}
This is very easy to implement and very easy to get right, but it's not terribly efficient (for 16 items, it probably doesn't matter) because your collection is repeatedly resized. For a more efficient approach, first shuffle your strings using the Fisher-Yates shuffle and then just assign the first entry from your shuffled strings to the first textbox, the second to the second, and so on.
You could use a List, and after each assignment you could remove the assigned item from the list. This would prevent duplicates.
http://msdn.microsoft.com/en-us/library/cd666k3e(v=vs.110).aspx
How about removing each item after selecting it?
Try something like
comboBox1.Items.RemoveAt(x);
After adding it and each time your
x = rnd.Next(0, 16);
code will reduce to
x = rnd.Next(0, 15);
until it reaches zero.
A different approach would be after selecting one randomly loop through all the filled ones (or all in general for simpler code) and check if it is already selected. If already selected get a new one until it's different.
For that you could use an array of textboxes (store what you have in an array) and loop through them like so
for(int i=0;i<16;i++)
if(textBoxArray[i].Text==comboBox2.Items[x].toString()){
chosen=true;
}
But removing them from the combobox is much simpler and much faster as code. If you want them to still appear in your combobox you could simultaneously in a List, get your items from that List and remove it from there.
The user will not see anything.
To accomplish this, is fairly simple.
First, you know there are 16 items in total. You don't need to randomize the list but rather, randomize the index that you use to access the item of the list. This part you know.
In order to avoid repeating items, you need to keep a list of indexes that have already been used. Once you have determined an unused index, that's when you need to access your list.
Example:
class Sample
{
List<int> _usedIndexes;
public Sample()
{
_usedIndexes = new List<int>();
}
public int GetRandomIndex(int s, e)
{
Random rnd = new Random();
//Initialize with a random number
int x = rnd.Next(s, e);
//While the index exists in the list of used indexes, get another random number.
while(_usedIndexes.Exists(index => index == x))
{
x = rnd.Next(s, e);
}
//Add the number to the list of used indexes
_usedIndexes.Add(x);
return x;
}
}
Then you simply access the List of names you have with the index you have acquired as follows:
int unusedIndex = GetRandomIndex(0, 16);
User1.Text = comboBox2.Items[unusedIndex].ToString();

Categories

Resources