【问题标题】:Recursion error in C#C#中的递归错误
【发布时间】:2016-06-05 16:42:20
【问题描述】:

我有时会在此代码上遇到递归错误。

谁能告诉我为什么?

我想做的只是在井字游戏中自动播放。 没有什么花哨。刚刚学习。

 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 { }
    }

【问题讨论】:

  • 您能否详细说明“递归错误”的含义。您的意思是程序意外停止,还是继续无限循环?在 x 次移动之后是一致的,还是完全随机的?如果是崩溃,尝试捕获异常并阅读消息catch (Exception ex) { string err = ex.Message;}
  • System.Windows.Forms.dll 中出现“System.StackOverflowException”类型的未处理异常
  • 确保没有无限循环或递归。
  • 抱歉输入混乱。试图弄清楚这个网站:-)
  • 大概,你的PerformClick() 并没有在它应该结束的时候结束游戏,这意味着这段代码会无限地调用自己。请显示PeformClick()(或事件处理程序)的代码。

标签: c# recursion stack-overflow


【解决方案1】:

通过调用您已经使用的相同方法进行递归是一个坏主意,因为您会很快得到堆栈溢出。根据已经加载的内容,您最终可能会在几百次迭代内崩溃。

解决方法是不要从自身内部调用该方法。相反,你跟踪你需要做的工作并循环,直到你没有更多的工作要做。像这样的:

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");
}

如果我需要通过目录或类似的东西递归,这实际上是我使用的,但是你的情况更简单。我认为它可以通过以下方式解决:

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 { }
}

为了兴趣,附注:Random 不是很随机。你甚至可能会发现你一直在一遍又一遍地重玩同一个游戏或一组游戏(如果你在某个地方跟踪过它们)。用计算机获得一个真正的随机数是hard不可能的,但这是一个已经写了很多的主题。

更新: 正如 Nate M. 指出的那样:上面的代码仍然很粗糙,实际上并不完整。由于多种情况,您仍然可能陷入无限循环:

  1. 游戏结束并调用此方法(即没有更多有效的移动位置)。
  2. 随机呼叫不断给出相同的号码或一组号码。
  3. 我可能还缺少一两个... :)

【讨论】:

  • 我正要说,我认为递归可以完全消除。一个额外的改进可能是迭代直到找到一个有效的单元格,然后你会运行一次并依赖一个随机种子而不是多个。使用上面列出的代码,您仍然有无限循环的“可能性”(尽管不太可能)
  • 好点@NateM。我添加了一个更新来说明这种可能性!
  • 跟进...我在其他地方查看获胜者。我记得像Randomice这样的东西。基于时间和日期的东西。我不在了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-05
  • 2018-03-30
  • 2016-05-08
  • 2013-03-07
  • 2012-06-08
  • 2021-08-15
  • 1970-01-01
相关资源
最近更新 更多