洪水填充算法无限循环

时间:2013-12-18 19:05:58

标签: c# algorithm xna flood-fill

我正在尝试为我的游戏实施一个简单的洪水填充算法,以便在程序生成的洞穴中找到洞穴的大小;然而,我似乎缺少一些基本点,因此我使用的算法连续排队甚至检查点。 我的代码如下:

List<Point> sector = new List<Point>();
List<Point> checkd = new List<Point>();
List<Point> queue = new List<Point>();

queue.Add(new Point(startX, startY));

while (queue.Count > 0) {
    Point origin = queue[0];
    queue.RemoveAt(0);
    sector.Add(origin);
    checkd.Add(origin);

    for (int offsetX = -1; offsetX < 2; offsetX++) {
        for (int offsetY = -1; offsetY < 2; offsetY++) {
            if (offsetX == 0 && offsetY == 0 || offsetX == offsetY ||
                offsetX == -offsetY || -offsetX == offsetY)
                continue;

            Point target = new Point(offsetX, offsetY);

            if (target.X < 0 || target.Y < 0 ||
                target.X >= cells.Width || target.Y >= cells.Height ||
                !checkd.Contains (target))
                queue.Add(target);
        }
    }
}

1 个答案:

答案 0 :(得分:3)

这里有很多不妥之处。我尽可能地保留原始代码。

  1. 目标点计算:Point target = new Point (offsetX, offsetY);不计算位置。您可能想要使用Point target = new Point(origin.X + offsetX, origin.Y + offsetY);
  2. 检查越界坐标,如果该点已经在checkd,则无法在if (target.X < 0 || target.Y < 0 || target.X >= cells.Width || target.Y >= cells.Height || !checkd.Contains (target))中的一个if语句中完成,因为这也会在cells之外的队列中添加点1}} grid。
  3. 通过引用检查点是否在列表中。如果的引用已经在列表中,则使用List<Point>.Contains(Point p)仅返回true。从来没有这种情况,因为目标是使用Point target = new Point(...)创建的。
  4. 在添加目标点之前,您可能还想检查该点是否已经在队列中。

  5. 所以这是我的版本。它遍历所有点并最终将它们添加到checkd。

    List<Point> checkd = new List<Point>();
    List<Point> queue = new List<Point>();
    
    queue.Add(new Point(startX, startY));
    
    while (queue.Count > 0)
    {
        Point origin = queue[0];
        queue.RemoveAt(0);
        sector.Add(origin);
        checkd.Add(origin);
    
        for (int offsetX = -1; offsetX < 2; offsetX++)
        {
            for (int offsetY = -1; offsetY < 2; offsetY++)
            {
                // do not check origin or diagonal neighbours
                if (offsetX == 0 && offsetY == 0 || offsetX == offsetY || offsetX == -offsetY || -offsetX == offsetY) continue;
    
                Point target = new Point(origin.X + offsetX, origin.Y + offsetY);
    
                // skip out of bounds point
                if (target.X < 0 || target.Y < 0 || target.X >= cells.Width || target.Y >= cells.Height) continue;
    
                if (!Contains(checkd, target) && !Contains(queue, target))
                {
                    queue.Add(target);
                }
            }
        }
    }
    

    为了检查收容,我使用了以下方法:

    private bool Contains(List<Point> list, Point point)
    {
        return list.Any(p => p.X == point.X && p.Y == point.Y);
    } 
    

    尝试从头开始实施泛洪填充算法可能是一个很好的练习。对于一个严肃的项目,您应该考虑使用已经实现了此功能(可能还需要更多)的图形库。