1

由于某种原因,我修改的代码似乎无法正常运行。调试时没有异常错误,但它的功能与原始代码(列表)中的不同 - 也就是说它似乎没有更新。我已将其定位到我认为导致问题的代码区域:

我的原始代码(使用列表)有效:

    private List<Gem> gems = new List<Gem>();
    private List<Enemy> enemies = new List<Enemy>();

    private void UpdateGems(GameTime gameTime)
    {
        for (int i = 0; i < gems.Count; ++i)
        {
            Gem gem = gems[i];

            gem.Update(gameTime);

            if (gem.BoundingCircle.Intersects(Player.BoundingRectangle))
            {
                gems.RemoveAt(i--);
                OnGemCollected(gem, Player);
            }
        }
    }

这是我修改后的代码,将 List 替换为 Stack,但无法正常工作:

    private Stack<Gem> gems = new Stack<Gem>();
    private Stack<Enemy> enemies = new Stack<Enemy>();

    private void UpdateGems(GameTime gameTime)
    {
        for (int i = 0; i < gems.Count; ++i)
        {
            Gem gem = gems.Peek();


            gem.Update(gameTime);


            if (gem.BoundingCircle.Equals(Player.BoundingRectangle))
            {
                gems.Pop();

                OnGemCollected(gem, Player);
            }
        }
    }

有任何想法吗?

4

4 回答 4

1

我不知道你到底需要什么,但循环看起来有点奇怪:如果你pop()在第一轮没有从堆栈中取出任何东西,peek()将始终返回相同的元素。 堆栈数据结构没有索引,它只允许弹出/查看最后推送的元素。带有列表的代码的行为当然不同,因为您实际上是在检查列表中的所有元素。

于 2013-05-18T06:28:50.733 回答
1

根据定义,当您从堆栈中弹出某些内容时,您会删除最后添加的项目。因此,您颠倒了Gem从集合中检查和删除对象的顺序 - 当您执行PeekandPopBoundingCircle.Equals()签入Stack<Gem>版本时,您不会像在版本中那样检查集合中的第一个项目List<Gem>

List 可以在任一方向上迭代,只需以适当的方式调整您的索引器。堆栈是 LIFO (后进先出),因此您只能访问最后添加的项目。

于 2013-05-18T06:30:55.307 回答
0

我认为当调用峰值方法时,它可能会在堆栈集合的顶部保留对该项目的引用。因此,当您调用 pop 方法时。它会工作不正常。

于 2013-05-18T06:55:15.217 回答
0

我已复制您的示例并将其放入控制台应用程序,如下所示

class Program
    {
        private static Stack<Gem> gems = new Stack<Gem>();
        private Stack<Enemy> enemies = new Stack<Enemy>();
        static void Main(string[] args)
        {
            gems.Push(new Gem
                {
                   BoundingCircle = new BoundingCircle
                       {
                           Name = "abc"
                       }
                });

            gems.Push(new Gem
            {
                BoundingCircle = new BoundingCircle
                {
                    Name = "def"
                }
            });

            UpdateGems(new GameTime());
        }

        private static void UpdateGems(GameTime gameTime)
        {
            for (int i = 0; i < gems.Count; ++i)
            {
                Gem gem = gems.Peek();


                gem.Update(gameTime);


                if (gem.BoundingCircle.Equals(Player.BoundingRectangle))
                {
                    gems.Pop();

                    OnGemCollected(gem, null);
                }
            }
        }

        private static void OnGemCollected(Gem gem, Player player)
        {

        }
    }

    public class Gem
    {
        public void Update(GameTime gameTime)
        {

        }

        public BoundingCircle BoundingCircle { get; set; }
    }

    public class Enemy
    {

    }

    public class GameTime
    {

    }

    public class BoundingCircle : Bounding
    {
        public override bool Equals(object obj)
        {
            var temp = (Bounding) obj;
            return Name.Equals(temp.Name, StringComparison.InvariantCulture);
        }
    }

    public class Player
    {
        static Player()
        {
            BoundingRectangle = new BoundingRectangle
                {
                    Name = "def"
                };
        }

        public static BoundingRectangle BoundingRectangle { get; set; }
    }

    public class BoundingRectangle : Bounding
    {

    }

    public abstract class Bounding
    {
        public string Name { get; set; }
    }

它工作得很好。请注意,您的 Equals 函数必须被 BoundingCircle 类覆盖。

于 2013-05-18T07:52:51.473 回答