-1

I am looking for a more efficient way to solve this problem. Lets say I have 10 inspirational quotes and I would like 3 to be chosen at random to be displayed. example:

string0 = "be patient";
string1 = "show resourcefulness";
string2 = "show perseverance";
string3 = "be content";
string4 = "appreciate more";
string5 = "live free";
string6 = "be optimistic";
string7 = "work with joy";
string8 = "show enthusiasm";
string9 = "do your best";

Console.WriteLine("press Enter to see 3 quotes"); 
Console.ReadLine(); 

//my own way of doing it was to have 3 new strings for the spotlight. 
//then assigning an int for each quote to signify if it was already chosen or not. 

Random rnd = new Random(); 
string display1 = "";
string display2 = "";
string display3 = "";

int quote0 = 0; 
//i wont list the other ints for this example

    flag1:
    int dice = rnd.Next(10); 
    if (dice == 0) //a quote is chosen
    {
      if (quote0 == 1) //it's a duplicate
      {
        goto flag1; //to roll another number
      }
      display1 = string0;
      quote0 = 1; 
    }
//there will be an if statement for dice 1-9 which i wont repeat
//this is repeated in flag2 for display2, and flag3 for display3
    Console.WriteLine(display1); 
    Console.WriteLine(display2); 
    Console.WriteLine(display3); 
    Console.ReadLine();
J3KB0T
  • 3
  • 3
  • fisher yates shuffle ? – Mitch Wheat Feb 16 '21 at 02:55
  • 1
    Have you considered... putting all the strings into a list, then, to get a random string from that list, set the random range from 0 to the size of the list. After you get the random string from the list, then remove that string from the list. This will avoid getting duplicate strings. – JohnG Feb 16 '21 at 02:59
  • 1
    It’s not a good idea to use goto, I would convert that to a while loop. – ekke Feb 16 '21 at 03:19
  • 2
    Enumerable.Range(1,10).OrderBy(x => rnd.Next()).Take(3).ToList(); – Kevin Feb 16 '21 at 03:26

1 Answers1

0

As I commented, adding the strings to a List<string> may make things easier. After you get a random string from the list like...

int index = rnd.Next(0, allStrings.Count);

Then remove that string from the list to avoid getting it twice...

allStrings.RemoveAt(index);

To get the three strings as you describe may look something like...

Random rnd = new Random(); // <- defined globally

Then the code to display the three strings...

List<string> allStrings = new List<string>();
allStrings.Add("be patient");
allStrings.Add("show resourcefulness");
allStrings.Add("show perseverance");
allStrings.Add("be content");
allStrings.Add("appreciate more");
allStrings.Add("live free");
allStrings.Add("be optimistic");
allStrings.Add("work with joy");
allStrings.Add("show enthusiasm");
allStrings.Add("do your best");
// get string 1
int index = rnd.Next(0, allStrings.Count);
string display1 = allStrings[index];
allStrings.RemoveAt(index);
// get string 2
index = rnd.Next(0, allStrings.Count);
string display2 = allStrings[index];
allStrings.RemoveAt(index);
// get string 3
index = rnd.Next(0, allStrings.Count);
string display3 = allStrings[index];

Console.WriteLine(display1);
Console.WriteLine(display2);
Console.WriteLine(display3);
Console.ReadLine();

Edit… for OPs comment…

There are many ways to do this. I suggest you peruse the posted duplicated answers and also @Kevin ‘s comment. If you have the List<string> then using Kevin’s example you can get all the unique “indexes” you need with one (1) line of code… like…

var uniqueIndexes = Enumerable.Range(0, allStrings.Count).OrderBy(x => rnd.Next()).Take(3).ToList();
foreach (int index in uniqueIndexes) {
  Console.WriteLine(allStrings[index]);
}
JohnG
  • 9,259
  • 2
  • 20
  • 29
  • beautifully done. i first tried this problem with 100 strings and 10 displays, as you may imagine, it was 5000+ lines of code. you did this with 3 lines per index. i am not as fluent in the language and was very curious how efficiently it could be done. thanks again for your time. – J3KB0T Feb 16 '21 at 03:50