C# 堆栈推送调用问题

本文关键字:调用 问题 堆栈 | 更新日期: 2024-11-05 01:35:56

我遇到了一个问题,我的 C# 堆栈将接受推送的值,但随后也用新值覆盖堆栈中以前存在的元素。

下面是供参考的构造函数块:

 public class MazNav                    //handles processing and navigation
{
    private Maze m;
    private static Stack<int[]> path;
    private int[] currCell;
    private int visCell;
    private Random rng;
    //constructor
    public MazNav(Maze mz)
    {
        m = mz;                                         //assigns this object to a maze
        path = new Stack<int[]>();                      //initialize the stack
        currCell = m.getStart();                        //starts the pathfinding at start cell
        visCell = 1;                                    //initializes the visited cells count
        path.Push(currCell);                            //adds this cell to the stack
        rng = new Random();                               //initializes the randomizer

问题出现在此方法末尾的 if 块中(对不起,它仍然很丑;我正在调试中,一旦我有工作:)

 public void buildMaze()
    {
        //variables to represent the current cell
        int[] currPos;              //coordinates
        int nextDir = 0;                 //direction towards next cell
        //variables to represent the next cell
        int[] nextPos;              //coordinates
        int backDir = 0;                //holds direction towards previous cell
        bool deadEnd = false;       //flags true when a backtrack is required
        bool outOfBounds = false;   //flags true when a move would leave the array
        while (visCell < m.getTotCells())       //while the number of visited cells is less than the total cells
        {
            if (path.Count > 0)     // if there is something in the stack
            {
                currPos = path.Peek();                          //check the current coordinates
                nextPos = currPos;                              //movement will happen one cell at a time; setting next cell coordinates the same as current allows easy adjustment
                nextDir = findNextUnv(currPos);                    //find the direction of the next cell to check
                deadEnd = false;
                outOfBounds = false;
                switch (nextDir)
                {
                    case 0: //North
                        if (nextPos[0] - 1 >= 0)
                        {
                            nextPos[0]--;
                            backDir = 2;
                        }
                        else
                        {
                            outOfBounds = true;
                        }
                        break;
                    case 1: //East
                        if (nextPos[1] + 1 < m.getCols())
                        {
                            nextPos[1]++;
                            backDir = 3;
                        }
                        else
                        {
                            outOfBounds = true;
                        }
                        break;
                    case 2: //South
                        if(nextPos[0] + 1 < m.getRows())
                        {
                            nextPos[0]++;
                            backDir = 0;
                        }
                        else
                        {
                            outOfBounds = true;
                        }
                        break;
                    case 3: //West
                        if (nextPos[1] - 1 >= 0)
                        {
                            nextPos[1]--;
                            backDir = 1;
                        }
                        else
                        {
                            outOfBounds = true;
                        }
                        break;
                    case 99: //dead end
                        try
                        {
                            deadEnd = true;
                            path.Pop();
                            currPos = path.Peek();
                            int diff;

                            if (currPos[0] == nextPos[0])
                            {
                                diff = currPos[1] - nextPos[1];
                                if (diff == -1)
                                {
                                    backDir = 3;
                                }
                                else if (diff == 1)
                                {
                                    backDir = 1;
                                }
                            }
                            else if (currPos[1] == nextPos[1])
                            {
                                diff = currPos[0] - nextPos[0];
                                if (diff == -1)
                                {
                                    backDir = 2;
                                }
                                else if (diff == 1)
                                {
                                    backDir = 0;
                                }
                            }
                            m.getCell(nextPos[0], nextPos[1]).setBck(backDir, true);
                        }
                        catch (Exception) { }
                        break;                           
                }
                    if (!deadEnd && !outOfBounds)
                        {
                            m.getCell(currPos[0], currPos[1]).setWal(nextDir, false);
                            m.getCell(nextPos[0], nextPos[1]).setWal(backDir, false);
                            path.Push(nextPos);
                            visCell++;
                        }
            }
        }
    }e

推送调用只执行一次,但是当我在调试器上观察它时,在该行运行后,计数增加了 1,但堆栈中的每个元素现在都相同。 以前有人遇到过这种行为吗? 我哪里出错了?

C# 堆栈推送调用问题

由于您对待nextPoscurPos的方式,您的代码中存在很多错误。

特别是这一行:

nextPos = currPos;

在这里,您将nextPos分配给与curPos相同的数组,因此如果您修改一个数组,另一个将随之修改。如果你将一个推送到堆栈上,然后修改任何一个,堆栈上的数组将随之修改。

我建议的解决方案是为您的位置使用不可变的数据类型,而不是数组(无论如何它都不是特别适合坐标):

internal struct Point
{
    internal int X { get; private set; }
    internal int Y { get; private set; }
    internal Point(int x, int y)
    {
        X = x;
        Y = y;
    }
    internal Point NewX(int deltaX)
    {
        return new Point(X + deltaX, Y);
    }
    internal Point NewY(int deltaY)
    {
        return new Point(X, Y + deltaY);
    }
}

这样,当您需要过渡到新点时,可以创建一个新点,而不是修改现有点:

if (nextPos.X - 1 >= 0)
{
    nextPos = nextPos.NewX(-1);
    backDir = 2;
}

这应该可以帮助您掌握您的值,并防止它们以各种方式相互覆盖。