【问题标题】:Value of array is always the same as the value from another array [duplicate]数组的值始终与另一个数组的值相同[重复]
【发布时间】:2022-01-06 07:19:51
【问题描述】:

我正在尝试制作一个使控制台中的前景更新尽可能少的蛇游戏,因此我在一个类中有两个网格。第一个是当前网格,第二个用于检查当前网格中是否发生了变化。 因此,第二个网格应该始终具有上次游戏时间的当前网格的值,但问题是,如果我更改当前网格,第二个网格也会更改,即使这两个变量都有彼此无关。

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。

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

【问题讨论】:

  • 问题是oldState.SetCells(Grid.Cells);。你只是在复制参考。因此,您很快就会得到两个包含相同单元格数组的表格。

标签: c# arrays multidimensional-array console-application .net-5


【解决方案1】:
Cell[,] newField = Grid.Cells;

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

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

【讨论】:

  • 谢谢^^ 之前没有注意到数组被引用了。
  • 一开始我学习了一个 Cell 类,因为我以为我要添加更多属性,但后来它变得非常简单。但对我来说,当它是一堂课时会更清楚。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-24
  • 2022-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多