C# 堆栈推送调用问题

C# stack push call issue

我遇到了一个问题,我的 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,但堆栈中的每个元素现在都相同。有没有人遇到过这种行为?我哪里错了?

由于您对待 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;
}

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