如何提高扫雷算法的性能?

4
我正在制作扫雷克隆游戏。我写了一个算法,当单击周围没有地雷的方块时,它会递归地显示所有周围也没有地雷的邻居,然后是它们的邻居... 这个结果只需要一次点击。 它的功能正常,但速度太慢了。原始扫雷游戏可以立即显示这些方块,但在我的情况下,它们之间有一点延迟。
我编写了以下代码:
private void RevealNeighbor(int x, int y) {
    foreach(var neighbor in _neighbors) {
        try {
            Tile tile = _tiles[x + neighbor[0], y + neighbor[1]];
            if(tile.TileType == TileType.Empty && tile.Hidden) {
                tile.Reveal();
                if(tile.Number == 0) {
                    RevealNeighbor(x + neighbor[0], y + neighbor[1]);
                }
            }
        }
        catch(IndexOutOfRangeException) {
        }
    }
}

_neighbors是一个数组的数组,其中包含8个邻居位置的偏移量:

private readonly int[][] _neighbors = new[] {
                                          new[] {-1, -1},
                                          new[] {0, -1},
                                          new[] {1, -1},
                                          new[] {1, 0},
                                          new[] {1, 1},
                                          new[] {0, 1},
                                          new[] {-1, 1},
                                          new[] {-1, 0}
                                      };

如何让它变得更快?

2
tile.Reveal(); 会触发渲染吗? - Karthik T
5
延迟应该是在绘制更新而不是计算更新。使用分析器来避免猜测。 - Hans Passant
一个Tile是一个System.Windows.Forms.Button。Reveal()方法只是禁用按钮并将文本设置为数字(如果数字大于0)。 - Paul
那将会触发一次绘制。 - BoltClock
2个回答

3

使用 SuspendLayout 方法,只有在需要绘制时再进行绘制:

*false 是设计师的默认值,请查明其含义

this.SuspendLayout();
... logic      
this.ResumeLayout(false);

同时,避免滥用异常机制,这样做不仅效率低下,而且是一种不好的实践。

相反,使用“围墙”(在矩阵末尾添加额外的瓷砖来表示…嗯…一个围墙)。


1
我猜RevealNeighbor实际上是重新绘制了棋盘。相反,你应该计算出将要被揭示的内容,然后再重新绘制棋盘。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接