如何将此块转换为for循环

时间:2014-07-02 15:10:34

标签: c#

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); 
}

我使用它时的错误是=“收集被修改;枚举操作可能无法执行”

4 个答案:

答案 0 :(得分:2)

我假设您想要查找Point的Snake.Body集合是否包含Food.Point,更改您的属性然后停止循环。 (否则,在正确遍历集合并增加其大小时可能会出现严重问题)

所以,假设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;
    }
}

如果Snake.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); 
}

答案 1 :(得分:1)

你的案例中的问题是你正试图处理蛇体内的总点数,

foreach (Point p in Snake.Body) 

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

Points++;

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

Snake.Grow(Points + 4); 

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

因此,您可以做的是创建一个简单的int变量,然后对其进行处理。

答案 2 :(得分:1)

最简单的方法是

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

答案 3 :(得分:1)

首先,如上所述,您在枚举期间尝试改变您的收藏(让您的蛇成长) - 这是不允许的,因为它让调查员不知道从哪里继续或(更糟)丢失某些东西这将在迭代的早期添加。

更好地处理这种特殊情况的方法可能是执行检查,然后在检查后执行增长逻辑,或者执行基于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
{ ... }

这将阻止修改直到枚举