1

I am a novice in Xamarin ,

I want to generate randomly 4 numbers which are in a list and this 4 numbers must be different .

In the example below I have a list of Ids and I am trying to pick 4 id randomly in the list and those 4 Ids must be each differents.

Here is my methode, I cannot see how I can continue and make it simple :

   public MyWordsList()
            {
                InitializeComponent();


              Dictionary<int, int> WordId = new Dictionary<int, int>();
                int u= 0;
                // TestAnswer.IsVisible = false;
                foreach (var w in mywords)
                {
                    WordId[u] = w.ID;
                    u++;
                }

                Random rnd = new Random();
// this is not ok because I can have the same number
                word11.Text = WordsList[rnd.Next(1, 20)];
                word12.Text = WordsList[rnd.Next(1, 20)];
                word13.Text = WordsList[rnd.Next(1, 20)];
                word14.Text = WordsList[rnd.Next(1, 20)];

    }

If you have a better solution, I will take. Thanks

hugo
  • 441
  • 5
  • 25
  • https://stackoverflow.com/a/43592646/1744164 – Sir Rufo Jun 16 '17 at 23:56
  • Possible duplicate of [How can I randomly fill an array with 3 different strings?](https://stackoverflow.com/questions/43592102/how-can-i-randomly-fill-an-array-with-3-different-strings) – Sir Rufo Jun 16 '17 at 23:57

3 Answers3

3

You can write a short generic function which picks X amount of random and unique items from a specified collection and returns them:

private static IEnumerable<T> GetUniqueRandomItems<T>(int count, IList<T> allItems)
{
    if (new HashSet<T>(allItems).Count < count)
    {
        throw new ArgumentException(nameof(allItems));
    }
    Random random = new Random();
    HashSet<T> items = new HashSet<T>();
    while (items.Count < count)
    {
        T value = allItems[random.Next(0, allItems.Count)];
        items.Add(value);
    }
    return items;
}

You can later use it like this:

string[] randomIds = GetUniqueRandomItems(4, WordsList).ToArray();
word11.Text = randomIds[0];
word12.Text = randomIds[1];
word13.Text = randomIds[2];
word14.Text = randomIds[3];
Deadzone
  • 793
  • 1
  • 11
  • 33
  • Thanks, but this is not working it block the program – hugo Jun 17 '17 at 00:49
  • @hugo I updated the answer, if it still doesn't work, please show me how you call the method. – Deadzone Jun 17 '17 at 00:53
  • here is how i do: var id = mywordsdatabase.SelectWords(); int[] randomIds = GetUniqueRandomItems(4, id).ToArray(); – hugo Jun 17 '17 at 01:14
  • my methods: //Select words public List SelectWords() { var Ids = (from w in conn.Table() select w.ID); return Ids.ToList(); } – hugo Jun 17 '17 at 01:15
  • @hugo Can you verify that you have only unique values in `var id = mywordsdatabase.SelectWords();`? `(new HashSet(allItems).Count < count)` if you don't have enough unique elements this line should throw an exception, otherwise it should work without a problem. – Deadzone Jun 17 '17 at 01:17
  • @hugo please make sure you have the latest version of the method from my answer too. – Deadzone Jun 17 '17 at 01:19
  • I have unique values because id have Ids of my data base and it is unique – hugo Jun 17 '17 at 01:21
  • @hugo What happens if you run your program, wait few seconds and than place a breakpoint inside the `while (items.Count < count)`? Is it stuck there? – Deadzone Jun 17 '17 at 01:26
  • I cannot stop some where because it is a xamarin project – hugo Jun 17 '17 at 01:31
  • 1
    `T value = allItems[random.Next(1, allItems.Count)];` should be `T value = allItems[random.Next(0, allItems.Count)];` Otherwise it will never choose the first entry (at index 0). – mjwills Jun 17 '17 at 01:59
0

call a method like the following:

    private int CreateUniqueRandom(int min, int max, ICollection<int> existingNums)
    {
        var rnd = new Random();
        var newNum = rnd.Next(min, max);

        while (existingNums.Contains(newNum))
            newNum = rnd.Next(min, max);

        return newNum;
    }

Passing through a list of the numbers that you have created so far

Jonathan
  • 4,916
  • 2
  • 20
  • 37
  • Thanks I have bee trying to put it in a list but without succes I tried :var idd = CreateUniqueRandom(10, 20, Ids.ToList()); – hugo Jun 17 '17 at 00:51
0

You probably won't need this, but just to show a method of unique random number generation with no duplicate check:

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var randoms = GenerateRandoms(10, 1, 10).OrderBy(v => v);
            foreach (var random in randoms)
            {
                Console.WriteLine(random);
            }

            Console.ReadLine();
        }

        private static int[] GenerateRandoms(int randomCount, int min, int max)
        {
            var length = max - min + 1;
            if (randomCount > length) { throw new ArgumentException($"Cannot generate {randomCount} random numbers between {min} and {max} (inclusive)."); }

            var values = new List<int>(length);
            for (var i = 0; i < length; i++)
            {
                values.Insert(i, min + i);
            }

            var randomGenerator = new Random();
            var randoms = new List<int>();
            for (var i = 0; i < randomCount; i++)
            {
                var val = randomGenerator.Next(0, values.Count);
                randoms.Add(values[val]);
                values.RemoveAt(val);
            }

            return randoms.ToArray();
        }
    }
}
Mert Akcakaya
  • 3,109
  • 2
  • 31
  • 42