如何将此块转换为for循环

本文关键字:for 循环 转换 | 更新日期: 2023-09-27 18:11:05

foreach (Point p in Snake.Body)
if (p.X == Food.Point.X && p.Y == Food.Point.Y)
{
    Points++;
    Food = new FoodSpawn();
    Snake.Grow(Points + 4); 
}

当我使用它的错误是= "Collection was modified;枚举操作不能执行"

如何将此块转换为for循环

"

我假设你想找到蛇。身体收集点包含食物。点,更改属性,然后停止循环。(否则在正确遍历集合和增加其大小时可能会出现严重问题)

那么,假设Body是Point 的数组
for(int x = 0; x < Snake.Body.Length; x++)
{
    Point p = Snake.Body[x];
    if (p.X == Food.Point.X && p.Y == Food.Point.Y)
    {
          Points++;
          Food = new FoodSpawn();
          Snake.Grow(Points + 4); 
          break;
    }
}

如果蛇。Body是List<Point>那么我们需要将for循环改为

for(int x = 0; x < Snake.Body.Count(); x++)

或者使用LINQ

int cnt = Snake.Body.Count(x => x.X == Food.Point.X && p.Y == Food.Point.Y);
if(cnt != 0)
{
     Points++;
     Food = new FoodSpawn();
     Snake.Grow(Points + 4); 
}

最简单的方法是

foreach (Point p in Snake.Body.ToArray())

你的问题是,你试图在蛇的身体点的总数上工作,

foreach (Point p in Snake.Body) 

,但在循环结束时(或在循环中间),点改变。它们增加或减少。一旦它们这样做了,就会在枚举中导致这个错误。在您的代码中,这个点

Points++;

它正在增加点,从而触发错误。在这行代码之后,

Snake.Grow(Points + 4); 

它正在使Snake对象生长到所提供的点。这就是错误所在。实际上不是错误,而是在下一个循环中调用错误触发的地方。

所以,你能做的就是创建一个简单的int变量,然后对它进行处理。

首先,如前所述,您试图在枚举期间更改集合(使蛇生长)—这是不允许的,因为这会使枚举器不知道从哪里继续,或者(更糟的是)丢失本应在迭代早期添加的内容。

处理这种特殊情况的更好方法可能是执行检查,然后在检查之后执行增长逻辑,或者执行基于Linq

的。any函数的逻辑。
if(Snake.Body.Any(p => p.X == Food.Point.X && p.Y == Food.Point.Y))
{
    Points++;
    Food = new FoodSpawn();
    Snake.Grow(Points + 4); 
}

或者,如果您希望feed在同一循环中出现多次(有多种食物可用),请使用.Where函数

foreach(var p in Snake.Body
    .Where(p => p.X == Food.Point.X && p.Y == Food.Point.Y)
    .ToArray()) // This caches the result and avoids those pesky errors
{ ... }

这将防止修改,直到枚举