Aqsa Nadeem
Aqsa Nadeem

Reputation: 127

Unity keeps freezing in while loop having a random function

I am making a tic tac toe game unity And when its the computer's turn , it selects a random number if the random number is already marked then it generates another random number and checks it again , but its getting stuck in while loop i don't know why.

public void checkComputer()
{
    if ( Variab == 0 && whoseTurn == 1)
    {
        int j = 0;
        int rand = Random.Range(0, 8);
            while (markedSpaces[rand] != 1 || markedSpaces[rand] != 2)
            {
                rand = Random.Range(0, 8);
                j++;
            }

            TicTacToeButton(rand);

    }
 }

Upvotes: 0

Views: 1020

Answers (2)

Programmer
Programmer

Reputation: 125445

Similar questions keeps popping up but I wouldn't consider this as a duplicate but it's the-same issue with different solution.

You should not use Random.Range to determine when to exit a function. This is bound to fail and the result is an infinite loop. As soon as you see something like while(Random.Range(...)) in your code, you have to stop and re-evaluate how you are tackling this problem.

In your particular case, the condition in the code below has to be false in order for that random number to be considered fine:

while (markedSpaces[rand] != 1 || markedSpaces[rand] != 2)

Re-write the code and remove the need for a loop that depends on Random.Range to exist.

Create a function that loops over markedSpaces and checks if the value of markedSpaces is 1 or 2. If 1 or 2, add it to a List then return that List:

List<int> GetValidSpacesIndexes()
{
    List<int> markedSpacesIndexes = new List<int>();

    //Loop through the markedSpaces 
    for (int i = 0; i < 8; i++)
    {
        //Get indexes with 1 or 2 values
        if (markedSpaces[i] == 1 || markedSpaces[i] == 2)
        {
            markedSpacesIndexes.Add(i);
        }
    }
    return markedSpacesIndexes;
}

Now, in your checkComputer function, call the GetValidSpacesIndexes function, use Random.Range(0, validSpacesIndexes.Count) to obtain the valid index from the value. Use the returned random number to obtain the proper value returned from markedSpaces and that's what should be passed to the TicTacToeButton function.

public void checkComputer()
{
    if (Variab == 0 && whoseTurn == 1)
    {
        //Get Valid indexes
        List<int> validSpacesIndexes = GetValidSpacesIndexes();
        //Geneate Random number within valid Indexes
        int rand = Random.Range(0, validSpacesIndexes.Count);
        //Get the index value
        rand = markedSpaces[rand];

        TicTacToeButton(rand);
    }
}

Upvotes: 1

AotN
AotN

Reputation: 566

I think you should reconsider how you're doing this. Consider the scenario where the computer has only one space available. Yes, eventually, the computer will guess the right number... But, it'll have to keep generating random numbers until it gets the right one... It's a bit of a waste in terms of resources. Hypothetically, it could generate wrong numbers indefinitely... You could instead, if you want to, create an array of non-played squares and generate a random index within its bounds. This would generate only one random number.

However, as for your current issue, I think it's because you're using an 'or' instead of an 'and'. If the markedspace == 1, then markedspace != 2 is true. If markedspace == 2, then markedspace != 1 is true. If markedspace is any other number, both conditions are true. So you have an infinite loop since no matter what it generates, it'll result in a true value.

Though, if you're saying that 1 and 2 represent players and a blank square is represented by 0, then your condition needs a rewrite... It looks like you're currently trying to picking random numbers as long as the current square is 0... Which is an inverse of what you probably want to do... You should maybe change it to:

while (markedSpaces[rand] != 0)

Or, alternatively:

while (markedSpaces[rand] == 1 || markedSpaces[rand] == 2)

Upvotes: 0

Related Questions