3

Hello everyone I got a problem selecting random numbers to shuffke a deck of cards. To shuffle randomly we tried to pick a random card in every loop, but it seems like if we ran out of one kind, we cannot pick a different kind randomly. It goes into infinite loop. Any suggestions?

(Translation: Maca=spade, sinek=club, kupa=heart, karo=diamond, vale=jack, kiz=queen, papaz=king)

    public class KartKarma : MonoBehaviour {
    public GameObject[] Deste;
    public static GameObject KupaAs, Kupa2, Kupa3, Kupa4, Kupa5, Kupa6, Kupa7, Kupa8, Kupa9, Kupa10, KupaVale, KupaKiz, KupaPapaz;
    public static GameObject KaroAs, Karo2, Karo3, Karo4, Karo5, Karo6, Karo7, Karo8, Karo9, Karo10, Karo11, Karo12, Karo13;
    public static GameObject SinekAs, Sinek2, Sinek3, Sinek4, Sinek5, Sinek6, Sinek7, Sinek8, Sinek9, Sinek10, Sinek11, Sinek12, Sinek13;
    public static GameObject MacaAs, Maca2, Maca3, Maca4, Maca5, Maca6, Maca7, Maca8, Maca9, Maca10, Maca11, Maca12, Maca13;
    public GameObject[] Kupa = {KupaAs, Kupa2, Kupa3, Kupa4, Kupa5, Kupa6, Kupa7, Kupa8, Kupa9, Kupa10, KupaVale, KupaKiz, KupaPapaz};
    public GameObject[] Karo = {KaroAs, Karo2, Karo3, Karo4, Karo5, Karo6, Karo7, Karo8, Karo9, Karo10, Karo11, Karo12, Karo13};
    public GameObject[] Sinek = {SinekAs, Sinek2, Sinek3, Sinek4, Sinek5, Sinek6, Sinek7, Sinek8, Sinek9, Sinek10, Sinek11, Sinek12, Sinek13};
    public GameObject[] Maca = {MacaAs, Maca2, Maca3, Maca4, Maca5, Maca6, Maca7, Maca8, Maca9, Maca10, Maca11, Maca12, Maca13};
    List<GameObject> deste = new List<GameObject>();

// Use this for initialization
void Start () {
    int i = 0;
    while(i < 26){
        int a = Random.Range(1,5);
        if (a == 1) {
            int b = Random.Range(0,13);
            if(Maca != null){
                while(Maca[b] == null){
                    b = Random.Range(0,13);
                }
                deste.Add(Maca[b]);
                Maca[b] = null;
            }
            else {
                while(a == 1)
                    a = Random.Range(2,5);
            }
        }

        if (a == 2) {
            int b = Random.Range(0,13);
            if(Sinek != null){
                while(Sinek[b] == null)
                    b = Random.Range(0,13);
                deste.Add (Sinek[b]);
                Sinek[b] = null;
            }
            else {
                while(a == 2)
                    a = Random.Range(1,5);
            }
        }

         if (a == 3) {
            int b = Random.Range(0,13);
            if(Karo != null){
                while(Karo[b] == null)
                    b = Random.Range(0,13);
                deste.Add (Karo[b]);
                Karo[b] = null;
            }
            else {
                while(a == 3)
                    a = Random.Range(1,5);
            }
        }

        if (a == 4) {
            int b = Random.Range(0,13);
            if(Kupa != null){
                while(Kupa[b] == null){
                    b = Random.Range(0,13);
                }
                deste.Add(Kupa[b]);
                Kupa[b] = null;
            }
            else {
                                    while(a == 4)
                    a = Random.Range(1,5);
            }
        }
        i++;
    }
}

void Update () {

}

}

the_drow
  • 18,571
  • 25
  • 126
  • 193
user3279394
  • 141
  • 7
  • 2
    What is `Random.Range`? In general, don't create new random instances in the method but reuse an instance variable or pass it as argument. Otherwise you get the same values since the random will be seeded by the current time which is the same if called repeatedly in a loop. – Tim Schmelter Feb 06 '14 at 12:27
  • use `Random.Next` on behalf of `Random.Range` then try. – Govinda Rajbhar Feb 06 '14 at 12:29
  • also, your code only handles `a` from 1 to 4, while for the Range method your sending parameters 1 and 5, whatever they mean. Where did you get that 5 from? – Tarec Feb 06 '14 at 12:30
  • What were you thinking – TJF Feb 06 '14 at 12:31
  • Throw this away, and start again - even ignoring the fact that it's running forever if you run out of cards of a certain suit, that's far from the only problem. Your random shuffler isn't even random. You start out by randomly picking a suit, each having a 25% of being picked; but then when you draw the next card, there's still a 25% chance of you picking a suit, when that should no longer be the case because one of those suits now only has 12 cards left. – Chris Feb 06 '14 at 12:34

3 Answers3

3

Use a proper shuffle algorithm, such as Knuth's (aka Fisher-Yates):

/// <summary>Used to shuffle collections.</summary>

public class Shuffler
{
    /// <summary>Shuffles the specified array.</summary>
    /// <typeparam name="T">The type of the array elements.</typeparam>
    /// <param name="array">The array to shuffle.</param>

    public void Shuffle<T>(IList<T> array)
    {
        for (int n = array.Count; n > 1; )
        {
            int k = _rng.Next(n);
            --n;
            T temp = array[n];
            array[n] = array[k];
            array[k] = temp;
        }
    }

    private readonly Random _rng = new Random();
}

Then:

var shuffler = new Shuffler();
...
shuffler.Shuffle(deste);

As the link posted by @Paul does indicate - be aware that Random is not a particularly great random number generator. You can substitute a better one if you want, but the underlying shuffle algorithm remains the same.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
2
while(a == 1)
    a = Random.Range(2,5);

Here's your infinite loop reason. Also, that part:

while(Sinek[b] == null)
    b = Random.Range(0,13);

is also nasty, because it does not guarantee the condition will be ever met.

Tarec
  • 3,268
  • 4
  • 30
  • 47
0

I think lines having

while(a == 1)
while(a == 2)
while(a == 3)
while(a == 4)

causing this issue. Please recheck your logic.

Amit
  • 882
  • 6
  • 13