0
votes

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?

3
I've edited your title. See Should questions include “tags” in their titles? where the consensus is "no, they should not". - rene

3 Answers

3
votes

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.

0
votes

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.

0
votes

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