Модификация списка WPF во время итерации? - PullRequest
0 голосов
/ 01 апреля 2020

enter image description here

Я пытаюсь сделать очень простую игру, где желтый шар отскакивает назад и четвертым. Если он сталкивается с одним из движущихся синих квадратов, он должен исчезнуть, а в другом месте должен появиться новый (всегда 3 в окне). Когда мой код достигает этой части, все 3 квадрата исчезают (затем появляются, как и предполагалось, это не проблема), и я просто не могу понять, почему. Было бы огромной помощью, если бы кто-то мог использовать мои методы, отвечающие за проблему Заранее спасибо.

Итак, мой метод timer_Tick, отвечающий за каждый кадр:

 void timer_Tick(object sender, EventArgs e)
        {
            logic.MoveBall();
            if (model.Enemy.Count<3)
            {
                logic.AddEnemy();
            }

            int iii = 0;
            foreach (MyShape enemy in model.Enemy)  //the whole thing from here is me trying to solve list modification during iteration
            {
                if (logic.MoveEnemy(enemy) == -1)
                {
                    logic.MoveEnemy(enemy);
                }
                else iii = logic.MoveEnemy(enemy);
            }
            if (iii > -1)
            {
                for (int j = model.Enemy.Count - 1; j >= 0; j--)
                {
                    if (j == model.Enemy.Count - iii)
                    {
                        model.Enemy.RemoveAt(j);
                    }
                }
            }
        }

MoveEnemy: я пытаюсь решить, есть ли сговор, и если да, то попробуйте удалить данный объект формы (синий квадрат). Поскольку весь этот метод находится в foreach, я просто сохраняю съемный элемент и пересылаю его в timer_Tick

public int MoveEnemy(MyShape shape) 
{
    int i = 0;
    int ii = -1;
    if ((shape.Area.IntersectsWith(model.Ball.Area)))
    {
        i = 0;
        foreach (var e in model.Enemy)
        {
            i++;
            if (shape == e)
            {
                ii = i;
            }

        }

    }

    shape.ChangeX(shape.Dx);
    shape.ChangeY(shape.Dy);
    bool coll = false;

    foreach (var e in model.Enemy)
    {
        if ((e.Area.IntersectsWith(shape.Area)) && (shape != e))
        {
            coll = true;
        }
    }

    if (shape.Area.Left < 0 || shape.Area.Right > Config.Width-40 || coll)
    {             
        shape.Dx = -shape.Dx;              

    }

    if (shape.Area.Top < 0)
    {
        shape.Dy = -shape.Dy;
    }
    if (shape.Area.Bottom > Config.Height/2)
    {
        shape.Dy = -shape.Dy;              
    }

    RefreshScreen?.Invoke(this, EventArgs.Empty);
    return ii;

}

И, наконец, AddEnemy:

public void AddEnemy()
        {
            rnd = new Random();
            int r = rnd.Next(-300, 300);
            model.Enemy.Add(new MyShape(Config.Width / 2+r, 0, 40, 40));
            RefreshScreen?.Invoke(this, EventArgs.Empty);
        }

1 Ответ

1 голос
/ 01 апреля 2020

List<T> (или IList и Enumerable) предоставляет несколько полезных методов для сжатия кода:

int itemIndex = list.IndexOf(item); // Gets the index of the item if found, otherwise returns -1
list.Remove(item); // Remove item if contained in collection
list.RemoveAll(item => item > 5); // Removes all items that satisfy a condition (replaces explicit iteration)
bool hasAnyMatch = list.Any(item => item > 5); // Returns true as soon as the first item satisfies the condition (replaces explicit iteration)

Упрощенная версия, которая должна устранить недостаток:

void timer_Tick(object sender, EventArgs e)
{
  if (model.Enemy.Count < 3)
  {
    logic.AddEnemy();
  }

  logic.MoveBall();
  model.Enemy.ForeEach(logic.MoveEnemy);    
  model.Enemy.RemoveAll(logic.IsCollidingWithBall);
}

public void AddEnemy()
{
  rnd = new Random();
  int r = rnd.Next(-300, 300);

  model.Enemy.Add(new MyShape(Config.Width / 2 + r, 0, 40, 40));

  RefreshScreen?.Invoke(this, EventArgs.Empty);
}

public bool IsCollidingWithBall(MyShape shape) 
{
  return shape.Area.IntersectsWith(model.Ball.Area);
}

public int MoveEnemy(MyShape shape) 
{
  shape.ChangeX(shape.Dx);
  shape.ChangeY(shape.Dy);

  bool hasCollision = model.Enemy.Any(enemy => enemy.Area.IntersectsWith(shape.Area)  
    && enemy != shape);

  if (hasCollision  || shape.Area.Left < 0 || shape.Area.Right > Config.Width - 40)
  {             
    shape.Dx = -shape.Dx;              
  }

  if (shape.Area.Top < 0)
  {
    shape.Dy = -shape.Dy;
  }

  if (shape.Area.Bottom > Config.Height / 2)
  {
    shape.Dy = -shape.Dy;              
  }

  RefreshScreen?.Invoke(this, EventArgs.Empty);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...