3

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


(来源:parks.ca.gov

但是在 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.
4

3 回答 3

6

我知道它没有明确回答这个问题,但在我看来,你使用 3D 数组是在自取其辱。C# 是一种 OO 语言,所以如果您认为 OO,它真的很有帮助。

与其为您的 3d 迷宫(如果它真的是您想要的 3d 迷宫)使用表示单元的多维数组,不如创建一个List名为 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; }
}

然后你可以有一个简单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 }

等等。

不需要复杂for的 3 维循环,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} [...]

我还建议您阅读面向对象原则的介绍

于 2013-06-16T17:00:20.197 回答
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. 作为替代方案,您可以使用二维数组:

    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并具有这些类型的 2D 数组。这样做可以更清楚地说明数组的实际含义,table[0,0].Left当然比table[0,0,1].

  4. 如果墙可以存在或不存在,则不应使用int0and 1,而应使用boolfalseand true。如果您想拥有更多状态,则enum可能是合适的。

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

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

于 2013-06-16T17:11:21.113 回答
0

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

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

第一行是对的。第二行不行。最接近的是使用二维数组:

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

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

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

于 2013-06-16T16:24:18.593 回答