[英]Flood fill algorithm looping ad infinitum
I'm trying to implement a simple flood fill algorithm to my game in order to find the size of a cavern in a procedurally generated cave; 我正在尝试为我的游戏实现一个简单的洪水填充算法,以便在程序生成的洞穴中找到洞穴的大小; however, I appear to be missing some fundamental point and as such the algorithm I'm using continuously queues even checked points. 然而,我似乎缺少一些基本点,因此我使用的算法连续排队甚至检查点。 My code is as follows: 我的代码如下:
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);
}
}
}
There are many things wrong here. 这里有很多不妥之处。 I tried to preserve your original code as much as possible. 我尽可能地保留原始代码。
Point target = new Point (offsetX, offsetY);
目标点计算: Point target = new Point (offsetX, offsetY);
does not compute the position. 不计算位置。 You probably want to use Point target = new Point(origin.X + offsetX, origin.Y + offsetY);
你可能想使用Point target = new Point(origin.X + offsetX, origin.Y + offsetY);
checkd
cannot be done in one if-statement as in if (target.X < 0 || target.Y < 0 || target.X >= cells.Width || target.Y >= cells.Height || !checkd.Contains (target))
since that would also add points to the queue which are outside the cells
grid. 检查越界坐标并且如果该点已经处于checkd
则无法在一个if语句中完成,如if (target.X < 0 || target.Y < 0 || target.X >= cells.Width || target.Y >= cells.Height || !checkd.Contains (target))
因为这也会在队列中添加cells
格网格之外的点。 List<Point>.Contains(Point p)
only returns true if the reference to the point is already in the list. 如果对点的引用已经在列表中,则使用List<Point>.Contains(Point p)
仅返回true。 This is never the case since target is created as with Point target = new Point(...)
. 从来没有这种情况,因为目标是使用Point target = new Point(...)
。 So here is my version. 所以这是我的版本。 It travels through all points and eventually adds them to checkd. 它遍历所有点并最终将它们添加到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);
}
}
}
}
To check for containment I used the method: 为了检查收容,我使用了以下方法:
private bool Contains(List<Point> list, Point point)
{
return list.Any(p => p.X == point.X && p.Y == point.Y);
}
Trying to implement a flood-fill algorithm from scratch may be a good exercise. 尝试从头开始实施泛洪填充算法可能是一个很好的练习。 For a serious project you should consider using a graphics library which has this functionality (and probably more you will need) already implemented. 对于一个严肃的项目,你应该考虑使用一个图形库,它已经实现了这个功能(可能你需要的更多)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.