【问题标题】:Remove object from List<> on condition在条件下从 List<> 中删除对象
【发布时间】:2014-04-14 12:55:27
【问题描述】:

我正在创建一个蚂蚁模拟程序,蚂蚁在其中四处走动并收集食物并将其带到巢穴。当从食物中收集到一定数量的蚂蚁时,我希望食物来源消失。我有一个单独的 antObject、foodObject 和 nestObject 类。

我的固定食品类中有一个“int foodleft = 25”变量。当用户单击时,食物对象被放置到屏幕上,并立即添加到列表对象“foodList”中。 draw 方法绘制列表中的所有对象。我无法弄清楚如何使特定的食物对象在其“foodLeft”变量达到 0 时消失!

这是我在固定食品类中的绘制方法 -

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

这是我在更新方法中的主“game1”类中尝试解决的问题

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


                }
            }
        }

但是这不起作用!我收到“未处理的无效操作错误”。

在我的主要 game1 类的 draw 方法中,我有这个

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

谁能看出我哪里出错了?

【问题讨论】:

标签: c# xna


【解决方案1】:

您在迭代集合时正在修改集合,因此会出现异常。在你的情况下,而不是这个:

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

改为这样做(假设它在 XNA 中可用):

foodList.RemoveAll(x =&gt; x.FoodLeft == 0)

如果不是,您可以查看this 问题中的答案以寻找替代方案。

【讨论】:

  • 对不起,我实际上对编程很陌生,还没有学会这个。 X 代表什么?上面的“if”语句是否仍然存在?感谢您的回复
  • 另外这不会给我一个很好的错误!但食物并没有消失!据我所知,它只在游戏开始时在 draw 方法中绘制一次,然后即使它从列表中删除它也不会消失,因为列表没有再次绘制:(
  • 如果是这种情况,那么您必须重新绘制列表。您对屏幕上的对象所做的任何更改都需要调用 Draw 方法以反映更改!
  • RemoveAll 方法中的语法是Lambda Expression。在答案中,对列表中x 是“当前项目”的每个项目执行 lambda。如果您愿意,可以将 x 替换为 f,如果它对您更易读的话。
  • 感谢您的解释!我试过这个 foreach(stationaryFood f in foodList) { foodList.RemoveAll(x => x.FoodLeft == 0); f.Draw(spriteBatch, foodList);但是我得到另一个错误,必须在绘制之前调用“开始”方法
【解决方案2】:

George Howarth 的回答会非常好。

如果您对 lambda 表达式不满意,您可以尝试反向迭代

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

反向迭代允许我们循环遍历一个集合并同时删除项目。

【讨论】:

  • Reverse 方法将复制列表,因此您不会修改同一个集合。我建议不要使用这种方法,因为它会导致性能损失,这对于减少游戏编程很重要。
【解决方案3】:

序言:

游戏编程是开始使用 C# 的好方法,但我建议您深入了解 forforeach 等基本结构和语言约定。

Microsoft Virtual Academcy Programming in C# Jump Start 中的前五个模块将大大提高您对该语言的理解。

答案:

我看不出在stationaryFood 类中使用foodlist 的理由。这将绘制重叠的纹理,这是毫无意义的。

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

您可以创建一个从列表中删除项目的方法。

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

稍后当您了解 lambdas 时,它可以简化为:

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

您可以在Update 方法中添加它。

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

并更改Draw方法中的逻辑。

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

【讨论】:

    猜你喜欢
    • 2021-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-19
    • 1970-01-01
    • 1970-01-01
    • 2012-10-30
    • 2019-04-22
    相关资源
    最近更新 更多