C# 创建三维数组

C# 创建三维数组,c#,syntax,multidimensional-array,C#,Syntax,Multidimensional Array,我是C#的新手,我想创建一个多维数组,如下所示: int[,,] table = { { {1,1,1,0}, {1,0,0,0}, ... }, { {0,1,1,0}, {1,0,1,0}, ... }, ... }; table.Set(0, 0, new int[] { 0, 0, 1, 1 }); 但在8x4单元中 我想储存迷宫细胞 {

我是C#的新手,我想创建一个多维数组,如下所示:

int[,,] table = {
                  { {1,1,1,0}, {1,0,0,0}, ... },
                  { {0,1,1,0}, {1,0,1,0}, ... },
                  ...
                };
table.Set(0, 0, new int[] { 0, 0, 1, 1 });

但在8x4单元中

我想储存迷宫细胞

{
    {1,1,1,0}, {1,0,0,0}, {1,1,1,1}, {1,0,0,0}, {1,1,0,1}, {1,1,0,1}, {0,1,0,0}, {1,0,0,1},
    ...
    {0,1,1,0}, {1,0,1,0}, {0,0,1,1}, {1,0,1,0}, {1,0,0,1}, {0,1,0,1}, {1,1,1,0}, {1,1,0,1},
}

3D数组的数组初始值设定项如下所示:

int[,,] table = {
                  { {1,1,1,0}, {1,0,0,0}, ... },
                  { {0,1,1,0}, {1,0,1,0}, ... },
                  ...
                };
table.Set(0, 0, new int[] { 0, 0, 1, 1 });
第一行是对的。第二行不行。最接近的方法是使用二维数组:

int[,][] table = new int[8,8][];
table[0,0] = new int[] {0, 0, 1, 1};
int[,][] table = {
                  { new[] { 1, 1, 1, 0 }, new[] { 1, 0, 0, 0 } },
                  { new[] { 0, 1, 1, 0 }, new[] { 1, 0, 1, 0 } }
                };
就像@tigrou和@Pierre-Luc-Pineault所建议的那样,将每个单元封装在一个对象中而不是一个普通数组中会更干净

考虑将数据存储在外部文件中并读取,而不是对256个数字进行硬编码。

我知道它并没有明确回答这个问题,但我认为,使用3D阵列是在自食其果。C#是一种面向对象的语言,所以如果你认为它是面向对象的,那么它真的很有帮助

与其使用表示3d迷宫单元的多维数组(如果它确实是您想要的3d迷宫),为什么不创建一个名为Cell的类的
列表
,每个类包含它们的位置和您需要的其他内容,例如:

public class Cell
{ 
    public Cell (int x, int y, int z)
    {
        X = x;
        Y = y;
        Z = z;
    }

    public int X { get; set; }
    public int Y { get; set; }
    public int Z { get; set; }
    public bool IsExplored { get; set; }
}
然后你可以有一个简单的
列表
,你可以在上面迭代。 您还可以删除x、y、z并创建一个
位置

对于墙,可以创建
Enum
并使用位操作,或者存储
Enum
的列表。既然你是初学者,我建议你列出枚举。您必须将此枚举添加到代码中,并将此属性添加到
单元格
类中:

public Enum WallPosition
{
    Top,
    Left,
    Bottom,
    Right
}


public List<WallPosition> walls { get; set;} //This goes into the Cell class
需要以不同的方式渲染每个已探索的单元吗

foreach (Cell cell in yourCellList.Where(c => c.IsExplored) { //Do stuff }
等等

无需使用复杂的
进行三维循环,我认为一个简单的
foreach
比一个

for (int i = 0; i < 8; i++)
    for (int j = 0; j < 8; j++)
        for (int k = 0; k < 4; k++)
for(int i=0;i<8;i++)
对于(int j=0;j<8;j++)
对于(int k=0;k<4;k++)
每次需要访问表时

唯一难看的部分是填充您的列表(通过创建新的
单元格
实例),但它仍然比一堵巨大的
{{{{0,1,0,1},{1,1,0}[…]墙更具可读性。

我还建议你读一本书

  • 对于多维数组,您可以一次设置所有数组(基本上使用您显示的语法):

    也可以逐个设置项目:

    int[,,] table = new int[8,8,4];
    table[0,0,0] = 0;
    
    两者之间没有任何区别。您最好编写一个扩展方法,该方法的工作方式如下:

    int[,,] table = {
                      { {1,1,1,0}, {1,0,0,0}, ... },
                      { {0,1,1,0}, {1,0,1,0}, ... },
                      ...
                    };
    
    table.Set(0, 0, new int[] { 0, 0, 1, 1 });
    
  • 或者,您可以使用二维阵列:

    int[,][] table = new int[8,8][];
    table[0,0] = new int[] {0, 0, 1, 1};
    
    int[,][] table = {
                      { new[] { 1, 1, 1, 0 }, new[] { 1, 0, 0, 0 } },
                      { new[] { 0, 1, 1, 0 }, new[] { 1, 0, 1, 0 } }
                    };
    
    或者您可以使用您建议的语法:

    int[,][] table = new int[8,8][];
    table[0,0] = new[] { 0, 0, 1, 1 };
    
    这种方法的一个缺点是,它不会强制内部数组的长度都相同

  • 正如注释中所建议的,另一个选项是使用自定义类型,如
    Cell
    ,并拥有一个2D数组。这样做可以更清楚地说明数组的实际含义,
    表[0,0]。左侧的
    肯定比
    表[0,0,1]
    更具可读性

  • 如果墙可以存在或不存在,则不应使用
    int
    0
    1
    ,应使用
    bool
    false
    true
    。如果希望有更多状态,则可能需要使用
    enum

  • 您的结构包含大量重复,因为单元格的底部与其下方单元格的顶部相同(除非您希望有单向墙)。这意味着该结构可能会进入不一致的状态,这通常很难调试(“墙不在那里?但我只是看了看,它就在那里。”)

    避免这种情况的一种方法是存储墙,而不是存储单元。存储墙不是8×8个单元,而是8×9个水平墙和9×8个垂直墙。然后,您可以使用方法将其提取出来,以便轻松查找特定单元的墙


  • 我们使用的是C#,而不是C,为什么不使用一些OO原则呢?只需创建一个名为Cell的类列表,其中包含3个属性。调试时3D数组非常混乱。人们喜欢将事情复杂化,这让我感到惊讶。您的第二个代码片段无法编译。3D数组不是2D数组,但您试图将其视为一个数组。“C#是一种面向对象的语言,因此如果你认为它是面向对象的,那么它真的很有帮助。”C#是一种多范式语言,因此你应该使用最适合任务的语言。我不确定是否可以使用包含4个简单值的类型来调用“OO”。你可以用C或Haskell轻松地实现这一点,但它们都不是面向对象的。此外,你的设计速度非常慢,访问特定单元格的速度是O(n),而不是O(1)如果您使用多维数组。如果您希望能够轻松地使用
    foreach
    ,您可以为此创建助手方法,而不牺牲性能。@svick速度非常慢?这是一个8x8x4网格;256个单元格。您可以强制执行整个数独网格(9*9*9可能性;729可能性)在5到15毫秒内,采用适当的设计…我真的不认为您必须在访问单个单元格的几微秒内牺牲可读性和可维护性。我不知道使用多维数组如何牺牲可维护性的可读性。正如我所说,如果您想使用
    foreach
    ,您可以为我编写一个简单的帮助程序方法。这不是数独,它将永远保持9×9(我完全不知道729是从哪里来的,但这与这里无关)。迷宫现在是8×8,但将来可能会变得更大。@svick我做了一些基准测试,在我的计算机上,达到300毫秒的执行时间(平均眨眼时间)在获取列表的最后一个元素时,您至少需要15000个元素。我认为他可以使用256个单元格。但是,您是对的,在他的列表上调用60000次之后,执行时间将比眨眼稍长一点,这是难以置信的慢。