简体   繁体   中英

Remove object from List<> on condition

I am creating an ant simulation program where ants travel around and collect food and bring it to the nest. When a certain number of ants have collected from the food I want the food source to disappear. I have a separate class for antObject, foodObject and nestObject.

I have a 'int foodleft = 25' variable in my stationaryFood class. The foodobjects are placed onto the screen when the user clicks, and are immediately added to a list object 'foodList'. A draw method draws all the objects in the list. I cannot figure out how to make the specific food object disappear when its 'foodLeft' variable hits 0!

Here is my draw method in my stationaryFood class -

  public void Draw(SpriteBatch spriteBatch, List<stationaryFood> foodlist)
    {
        foreach (stationaryFood food in foodlist)
        {
            spriteBatch.Draw(foodImage, foodBoundingRectangle, foodColor);                                                              //draw each food object in foodList
        }
    }

And here is my attempted solution to the problem in my main 'game1' class in the update method

  if (foodList.Count > 0)
        {
            foreach (stationaryFood f in foodList)
            {
                if (f.FoodLeft == 0)
                {
                    foodList.Remove(f);


                }
            }
        }

However this does not work! I get an 'unhandled invalid operation error'.

In my draw method in my main game1 class I have this

        foreach (stationaryFood f in foodList)
        {
            f.Draw(spriteBatch, foodList);
        }

Can anybody see where I am going wrong?

You're modifying the collection as you're iterating through it, hence why you're getting an exception. In your case, instead of this:

foreach (stationaryFood f in foodList)
{
    if (f.FoodLeft == 0)
    {
        foodList.Remove(f);
    }
}

Do this instead (assuming it's available in XNA):

foodList.RemoveAll(x => x.FoodLeft == 0)

If it isn't, you can look at the answer in this question for an alternative.

George Howarth's answer will work perfectly fine.

If you are uncomfortable with lambda expressions you could try reverse iteration :

foreach (stationaryFood f in foodList.Reverse<stationaryFood>())
{
    if (f.FoodLeft == 0)
    {
        foodList.Remove(f);
    }
}

Reverse iteration allows us to loop through a collection and remove items at the same time.

Preamble:

Game programming is a good way to get started with C#, but I would advise to read more into the basic constructs like for , foreach and the language conventions.

The first five modules in the Microsoft Virtual Academcy Programming in C# Jump Start will greatly increase your understanding of the language.

Answer:

I could not see a reason to use foodlist in the stationaryFood class. This will draw overlapped textures which is pointless.

public void Draw(SpriteBatch spriteBatch)
{
    spriteBatch.Draw(foodImage, foodBoundingRectangle, foodColor);
}

You can make a method which will remove items from the list.

private void RemoveFood(List<stationaryFood> foodlist)
{
    var foodToRemove = new List<stationaryFood>();

    foreach(var f in foodlist)
    {
        if(f.FoodLeft == 0)
        {
            foodToRemove.Add(f);
        }
    }

    foreach(var f in foodToRemove)
    {
        foodlist.Remove(f);
    }
}

Later on when you learn about lambdas it can be simplified to:

private void RemoveFood(List<stationaryFood> foodlist)
{
    foodlist.RemoveAll(food => food.FoodList == 0);
}

You can add this in the Update method.

if (foodList.Count > 0)
{
    RemoveFood(fooList);
}

And change the logic in the Draw method.

if (foodlist.Count > 0)
{
    foreach(var f in foodlist)
    {
        f.Draw(spriteBatch);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM