Как преобразовать этот блок в цикл for

#c#

#c#

Вопрос:

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

Ошибка при его использовании= «Коллекция была изменена; операция перечисления может не выполняться»

Комментарии:

1. Вы ожидали, что будет больше одной точки, чтобы соответствовать координатам для еды?

2. Нет, мне нужна только одна точка. Проблема в том, что когда я преобразую его в цикл for, p.X и p.Y становятся необъявленными

3. Змея. Body — это экземпляр объекта из другого класса

Ответ №1:

Я предполагаю, что вы хотите найти Змею.Тело сбора Очков содержит Еду.Укажите, измените свои свойства, а затем остановите цикл. (В противном случае у вас могут возникнуть серьезные проблемы с правильным обходом вашей коллекции и увеличением ее размера)

Итак, предположим, что Тело представляет собой массив точек

 for(int x = 0; x < Snake.Body.Length; x  )
{
    Point p = Snake.Body[x];
    if (p.X == Food.Point.X amp;amp; p.Y == Food.Point.Y)
    {
          Points  ;
          Food = new FoodSpawn();
          Snake.Grow(Points   4); 
          break;
    }
}
  

Если Змея.Тело — это List<Point> тогда нам нужно изменить цикл for на

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

Или с помощью LINQ

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

Комментарии:

1. Почему вы используете Count метод Linq вместо Any ? (Не то чтобы это действительно имело значение здесь для игры со змеями, хотя …) Или вы намеревались использовать цикл for с cnt или иным образом использовать cnt для вычисления роста змеи?

2. Вы правы. Any было бы лучше, потому что это остановило бы поиск перед Count

Ответ №2:

Самым простым способом было бы

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

Ответ №3:

Проблема в вашем случае заключается в том, что вы пытаетесь работать с общим количеством точек в теле змеи,

 foreach (Point p in Snake.Body) 
  

но в конце этого цикла (или в середине) точки меняются. Они увеличиваются или уменьшаются. Как только они это делают, они вызывают эту ошибку в перечислении. В вашем коде этот пункт

 Points  ;
  

Это увеличивает количество баллов и, таким образом, вызывает ошибку. И после этой строки кода,

 Snake.Grow(Points   4); 
  

Это заставляет Snake объект расти до заданных значений. Это то самое место, где ошибка. На самом деле это не ошибка, но вместо этого это место, которое при вызове ошибки запускается в следующем цикле.

Итак, что вы можете сделать, так это создать простую int переменную to и затем работать с ней.

Комментарии:

1. Я предполагаю, Snake.Grow добавляет один в коллекцию, которую он перечисляет.

2. @TimSchmelter, точно. Я думаю, у него есть метод Grow как void Grow (Snake snake) { snake.Points } увеличение роста, спасибо и за совет. 🙂

Ответ №4:

Во-первых, как уже упоминалось, вы пытаетесь изменить свою коллекцию (заставляя свою змею расти) во время перечисления, что недопустимо, потому что это оставляет перечислитель не знающим, с чего продолжить, или (что еще хуже) пропускающим что-то, что было бы добавлено ранее на итерации.

Лучшим способом подхода к этому конкретному случаю может быть выполнение проверки, а затем выполнение вашей логики роста после этой проверки или выполнение логики, основанной на .Любая функция Linq

 if(Snake.Body.Any(p => p.X == Food.Point.X amp;amp; p.Y == Food.Point.Y))
{
    Points  ;
    Food = new FoodSpawn();
    Snake.Grow(Points   4); 
}
  

или, если вы хотите, чтобы подача происходила несколько раз в одном цикле (доступно несколько продуктов), используйте .Где функция

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

Это предотвратит модификацию до перечисления