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

本文关键字:堆栈 栈溢出 扫雷 | 更新日期: 2023-09-27 18:13:09

我正在创建一个扫雷克隆。到目前为止,当我点击的砖块没有相邻的地雷时,我就会显示相邻的砖块,下面是我显示地雷的方法。

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的情况下修复它,这是一个要求。什么好主意吗?

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

问题是,当你"显示"时,你会显示所有的邻居。当显示邻居时,它会显示所有它的邻居,包括第一个,现在你有一个无限递归。

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

如果您不递归地尝试显示相同的标题,可能会有所帮助:

                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)测试-这将阻止堆栈溢出原因之一。除此之外,您还需要在递归之前将节点标记为"启用",否则它将继续来回反弹。

这不是一个真正有效的方法,你选择实现,但它应该与这个修复工作。

看起来你是从内部调用reveal。Reveal通过每个贴图。你对所有相邻的贴图调用它然后遍历每个贴图然后调用所有相邻的贴图。