简体   繁体   中英

Recursion error in C#

I am, sometimes, getting an recursion error on this code.

Can somebody tell me why?

What i am trying to make is just autoplay in Tic Tac Toe. Nothing fancy. Just learning.

 private void Auto_play()
    {
        try
        {
            Random rnd = new Random();
            int d = rnd.Next(0, 9);
            label3.Text = d.ToString();

            if (d == 0 && A1.Enabled)
                A1.PerformClick();
            else if (d == 1 && A2.Enabled)
                A2.PerformClick();
            else if (d == 2 && A3.Enabled)
                A3.PerformClick();
            else if (d == 3 && B1.Enabled)
                B1.PerformClick();
            else if (d == 4 && B2.Enabled)
                B2.PerformClick();
            else if (d == 5 && B3.Enabled)
                B3.PerformClick();
            else if (d == 6 && C1.Enabled)
                C1.PerformClick();
            else if (d == 7 && C2.Enabled)
                C2.PerformClick();
            else if (d == 8 && C3.Enabled)
                C3.PerformClick();
            else
                Auto_play();
        }
        catch { }
    }

Doing recursion via calling the same method you are already in is a bad idea, because you will get a stack overflow quite quickly. Depending on what is already loaded, you could end up crashing within a couple hundred iterations.

The fix is to not call the method from within itself. Instead, you keep track of the work you need to do and loop until you have no more work to do. Something like this:

Queue<string> queue = new Queue<string>();
queue.Enque(startingValue);

while (queue.Any())
{
    string val = queue.Deque();
    // work with string
    queue.Enque("new string found to do additional work with");
}

That is actually what I use if I need to recurse through directories or something similar, however yours is a simpler case. I'm thinking it could be solved with something like this:

private void Auto_play()
{
    try
    {
        bool foundMove = false;

        while (!foundMove)
        {
            foundMove = true;

            Random rnd = new Random();
            int d = rnd.Next(0, 9);
            label3.Text = d.ToString();

            if (d == 0 && A1.Enabled)
                A1.PerformClick();
            else if (d == 1 && A2.Enabled)
                A2.PerformClick();
            else if (d == 2 && A3.Enabled)
                A3.PerformClick();
            else if (d == 3 && B1.Enabled)
                B1.PerformClick();
            else if (d == 4 && B2.Enabled)
                B2.PerformClick();
            else if (d == 5 && B3.Enabled)
                B3.PerformClick();
            else if (d == 6 && C1.Enabled)
                C1.PerformClick();
            else if (d == 7 && C2.Enabled)
                C2.PerformClick();
            else if (d == 8 && C3.Enabled)
                C3.PerformClick();
            else
                foundMove = false;
        }
    }
    catch { }
}

A side note for interest sake: Random is not very random. And you might even find you keep replaying the same game or set of games over and over (if you tracked them somewhere). Getting a truly random number with a computer is hard impossible, but that is a subject that much has already been written on.

Update: As Nate M. points out: the above code is rough still and not actually complete. You could still get into an endless loop due to a number of conditions:

  1. The game has ended and this method is called (ie no more valid move locations).
  2. The Random call keeps giving the same number or set of numbers.
  3. There is probably another one or two I'm missing... :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM