防止扫雷克隆中的堆栈溢出

时间:2013-05-12 19:56:08

标签: c# .net

我正在创建一个扫雷克隆。到目前为止,当点击的瓷砖没有相邻的地雷时,我已经开始显示相邻的瓷砖,下面是我揭露地雷的方法。

struct data
{
    public Button tile;
    public bool mine, flag, clicked;
    public int adjMines;
}

data[,] dat;
//Defaults
Size gridSize = new Size(16, 16);
Size tileSize = new Size(16, 16);
int mines = 40, flags = 0;

bool valid(int x, int y)
{
    return (x >= 0 && y >= 0 && y < gridSize.Height && x < gridSize.Width);
}    


void reveal(Button btn)
{
    btn.BackColor = Color.DimGray;
    start = true;
    btn.Enabled = false;

    //find button clicked, forget everything you ever learned about efficiency.
    for (int i = 0; i < gridSize.Width; i++)
        for (int j = 0; j < gridSize.Height; j++)
            if (dat[i, j].tile == btn)
            {
                if (dat[i, j].adjMines == 0)
                {
                    for (int ii = -1; ii <= 1; ii++)
                        for (int jj = -1; jj <= 1; jj++)
                            if (valid(i + ii, j + jj))
                                reveal(dat[i + ii, j + jj].tile);
                }
                else
                    btn.Text = dat[i, j].adjMines.ToString();
            }
}

当我运行它时,我一直得到StackOverflowException,这并不会让人感到意外,但我不知道如何修复它而不去掉struct,是一个要求。有什么想法吗?

3 个答案:

答案 0 :(得分:7)

问题在于,当你“揭露”时,你会揭示所有的邻居。当邻居被揭示时,它会显示所有邻居,包括第一个邻居,现在你有一个无限递归。

诀窍是:在你揭示第一个之前,制作一个“正在进行中显示”的哈希集。在递归之前,将当前按钮添加到“进行中”设置。在揭示方法如果按钮已在进行中集中,则立即返回。你知道它的所有邻居都已经被揭露了,所以没有工作要做。

答案 1 :(得分:5)

如果您没有递归尝试显示相同的图块,那可能会有所帮助:

                for (int ii = -1; ii <= 1; ii++)
                    for (int jj = -1; jj <= 1; jj++)
                        if (valid(i + ii, j + jj) && !(ii == 0 && jj == 0))
                            reveal(dat[i + ii, j + jj].tile);

请注意添加的!(ii == 0 && jj == 0)测试 - 这将阻止堆栈溢出原因之一。除此之外,你还需要在递归之前将节点标记为“已启用”,否则它将继续反复播放。

这不是您选择实施的非常有效的方法,但它应该适用于此修复。

答案 2 :(得分:0)

看起来你正在从内部透露调用揭示。揭示每个瓷砖。您为所有相邻的瓷砖调用它,然后通过每个瓷砖然后调用所有相邻的瓷砖。我建议你仔细研究一下你的递归。