创建三维数组

时间:2013-06-16 16:12:05

标签: c# syntax multidimensional-array

我是C#的新手,我想创建一个像这样的多维数组:

http://kids.parks.ca.gov/pages/22784/images/maze.gif

但是在8x8x4细胞中。

我想存储迷宫细胞。

{
    {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},
}
int[,,] table = new int[8,8,4]; // is this right?

table[0,0] = {0, 0, 1, 1}; // I want to fill it this way.

3 个答案:

答案 0 :(得分:5)

我知道它并没有明确地回答这个问题,但在我看来,你是通过使用3D阵列来拍摄自己的。 C#是一种OO语言,所以如果你想到OO,它确实很有用。

为什么不创建一个名为Cell的类List,而不是使用表示单元格的多维数组3d Maze(如果它真的是一个3d迷宫),每个类都包含它们的位置和其他东西你需要,比如:

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; }
}

然后你可以拥有一个可以迭代的简单List<Cell>。 您还可以删除x,y,z并创建Position类。

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

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


public List<WallPosition> walls { get; set;} //This goes into the Cell class

这样,每次操作都会容易得多。例如,如果您需要探索第3列中的每个单元格,则可以执行

foreach (Cell cell in yourCellList.Where(c => c.Y == 3))
{
    cell.IsExplored = true;
}

需要以不同的方式呈现每个被探索的细胞吗?

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

等等。

您的3个维度不需要复杂的for循环,而我认为简单的foreach

更具可读性
for (int i = 0; i < 8; i++)
    for (int j = 0; j < 8; j++)
        for (int k = 0; k < 4; k++)

每次你需要访问你的桌子时。

唯一难看的部分就是填写你的列表(通过创建新的Cell个实例),但它仍然比{ { { 0, 1, 0, 1 }, {1, 1, 1, 0} [...]

的大墙更具可读性

我还建议您阅读introduction to OO principles

答案 1 :(得分:1)

  1. 使用多维数组,您可以一次性设置它们(基本上使用您显示的语法):

    int[,,] table = {
                      { { 1, 1, 1, 0 }, { 1, 0, 0, 0 } },
                      { { 0, 1, 1, 0 }, { 1, 0, 1, 0 } }
                    };
    

    或者您可以逐个设置项目:

    int[,,] table = new int[8,8,4];
    table[0,0,0] = 0;
    

    之间没有任何东西。你能做的最好的事情是编写一个类似于这样的扩展方法:

    table.Set(0, 0, new int[] { 0, 0, 1, 1 });
    
  2. 作为替代方案,您可以使用2D数组阵列:

    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 };
    

    这种方法的一个缺点是它不会强制内部数组的长度相同。

  3. 正如评论中所建议的那样,另一个选项是使用自定义类型,如Cell,并有一个二维数组。这样做可以更清楚地了解数组的实际含义,table[0,0].Left肯定比table[0,0,1]更具可读性。

  4. 如果墙可以在那里,你不应该使用int01,你应该使用bool值{{1 }和false。如果您想拥有更多州,true可能是合适的。

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

    避免这种情况的一种方法是存储墙而不是细胞。而不是8×8单元,你将有8×9水平墙和9×8垂直墙。然后,您可以使用方法将其抽象出去,这样您就可以轻松查找特定单元格的墙壁。

答案 2 :(得分:0)

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

int[,,] table = {
                  { {1,1,1,0}, {1,0,0,0}, ... },
                  { {0,1,1,0}, {1,0,1,0}, ... },
                  ...
                };

第一行是对的。第二行不起作用。最接近的是使用2D数组阵列:

int[,][] table = new int[8,8][];
table[0,0] = new int[] {0, 0, 1, 1};

像@tigrou和@Pierre-Luc Pineault建议的那样,将每个单元格封装在一个对象而不是普通数组中会更加清晰。

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