数组的值始终与另一个数组的值相同

Value of array is always the same as the value from another array

我正在尝试制作一款贪吃蛇游戏,尽可能减少控制台中的前景更新,因此我将两个网格合二为一 class。第一个是当前网格,第二个用于检查当前网格中是否发生了某些变化。 因此,第二个网格应该始终具有上一个游戏刻度的当前网格的值,但问题是,如果我更改当前网格,第二个网格也会更改,即使两个变量互不相关

public class Canvas
{
    public Size Bounds { get; set; }
    public Position Location { get; set; }
    public Table Grid { get; set; } // That is grid one
    public Position? Apple { get; set; }

    private Table oldState; // And that is the second one

    public Canvas(Position location, Size bounds)
    {
        Bounds = bounds;
        Location = location;
        Grid = new(location, bounds);
        oldState = new(location, bounds);
    }

    public Task DrawField(bool borders = false, bool ignoreIf = false)
    {
        if (borders) DrawBorders();
        if (Grid.Cells == oldState.Cells && !ignoreIf) return Task.CompletedTask;
        for (int y = 0; y < Bounds.Height - 1; y += 2)
        {
            for (int x = 0; x < Bounds.Width; x++)
            {
                // Here is the problem: Both grids are the same
                if (Grid.Cells[x, y].Type != oldState.Cells[x, y].Type || Grid.Cells[x, y + 1].Type != oldState.Cells[x, y + 1].Type || ignoreIf)
                {
                    Console.BackgroundColor = Grid.Cells[x, y].GetColor() ?? (IsEven(x) ? ConsoleColor.Green : ConsoleColor.DarkGreen);
                    Console.ForegroundColor = Grid.Cells[x, y + 1].GetColor() ?? (IsEven(x) ? ConsoleColor.DarkGreen : ConsoleColor.Green);
                    Console.SetCursorPosition(Location.Left + x, Location.Top + y / 2);
                    Console.Write("▄");
                }
            }
        }
        oldState.SetCells(Grid.Cells);
        return Task.CompletedTask;
    }

    public Task ClearField()
    {
        Grid.ClearField();
        oldState.ClearField();
        return Task.CompletedTask;
    }

    public Task SetNewApple()
    {
        List<Position> availableFields = new();
        for (int y = 0; y < Bounds.Height; y++)
        {
            for (int x = 0; x < Bounds.Width; x++)
            {
                if (Grid.Cells[x, y].Type is Cell.CellTypes.Empty) availableFields.Add(new(x, y));
            }
        }

        if (availableFields.Count == 0) return Task.CompletedTask; // GAME WIN

        Random r = new(DateTime.Now.Millisecond);
        if (Apple != null) Grid.Cells[Apple.Value.Left, Apple.Value.Top] = new(Cell.CellTypes.Empty);
        Apple = availableFields[r.Next(0, availableFields.Count)];

        Cell[,] newField = Grid.Cells;
        newField[Apple.Value.Left, Apple.Value.Top] = new(Cell.CellTypes.Apple);

        Grid.SetCells(newField); // This is where the apple is added for the snake game and that ONLY for grid 1, but this is where the second grid gets the apple added as well.

        return Task.CompletedTask;
    }
}

public class Table
{
    public Cell[,] Cells { get; private set; }
    public Position Location { get; set; }
    public Size Bounds { get { return new(Cells.GetLength(0), Cells.GetLength(1)); } }

    public Table(Position pos, Size size)
    {
        Cells = new Cell[size.Width, size.Height];
        Location = pos;
        ClearField();
    }

    public Task SetCells(Cell[,] cells)
    {
        Cells = cells;
        return Task.CompletedTask;
    }

    public Task ClearField()
    {
        for (int y = 0; y < Cells.GetLength(1); y++)
        {
            for (int x = 0; x < Cells.GetLength(0); x++)
            {
                Cells[x, y] = new(Cell.CellTypes.Empty);
            }
        }
        return Task.CompletedTask;
    }
}

public class Cell
{
    public CellTypes Type { get; set; }

    public Cell()
    {
        Type = CellTypes.Empty;
    }
    public Cell(CellTypes type) => Type = type;

    public ConsoleColor? GetColor() => (Type is CellTypes.Snake) ? ConsoleColor.White : (Type is CellTypes.Apple) ? ConsoleColor.Red : null;

    public enum CellTypes { Empty, Snake, Apple }
}

Position 结构有两个整数:Top 和 Left。

如果您需要有关代码和我的问题的更多信息,请随时询问,谢谢。

Cell[,] newField = Grid.Cells;

结构按值传递,并在赋值时复制。但是任何东西的数组(struct 或 class)都不是结构,而是通过引用传递的。即使 Cell 是一个结构,您也不会得到数组的副本,而事实并非如此。在上面的行 newFieldGrid.Cells 引用相同的单元格数组之后。

要复制一个数组,您实际上必须将该数组的所有元素复制到另一个相同维度的数组中。手动。在你的情况下,我认为你可以摆脱“浅拷贝”。 Cell 是一个 class,但在这里可以让两个数组引用相同的单元格。不过有一件事,为什么不直接使用 CellType 而不是 CellConsoleColor 可能只是单独 class 中的 extension method,而不是 属性,并且 Cell class 将变得不必要。