2017-03-12 41 views
1

我很难搞清楚如何正确设置我的数组。设置一个没有数据重复的多维数组

我有一个基本的瓷砖阵列设置为我的阵列grid[,]这工作正常。

现在我正在尝试为网格之间的边缘创建一个数组,以便放置墙。

所以我有这个:walls[,][,]其中每个[,]是一个网格位置,因此每个墙分隔2个网格位置。

这里的最终目标是,我想有两个网格点墙上阵列说AB,这样我可以再做:

Wall wallObject = walls[A.x,A.y][B.x,B.y];

希望是有道理的。我试图做这样的事情:

' 现在,因为每次1片可以有4个墙我试图建立我的墙阵列喜欢这一点,但不能工作了语法正确地做到这一点:

grids = new Tile[x,y]; 
walls = new Wall[grids.GetLength(0), grids.GetLength(1)][walls.GetLength(0) * 4, walls.GetLength(1) * 4]; // invalid rank specifier ERROR 

for(int i = 0; i < x; i++) { 
for(int j = 0; j < y; j++) { 

    grids[i, j] = new Tile(new Vector3(i, 0, j)); 
    foreach (Vector3 gridNeighbour in AdjacentTiles(new Vector3(i, 0, j))) //4 directions 
    { 
     if (!InGrid(gridNeighbour)) continue;  
     walls[i, j][(int)gridNeighbour.x, (int)gridNeighbour.z] = new Wall(grid[i,j],grid[(int)gridNeighbour.x,(int)gridNeighbour.z]); 
    } 

}} 

我在第二行得到一个错误,不确定写入它的正确方法。 我也相当肯定我的逻辑是错误的,因为这个数据设置,我认为会给我的墙壁的双倍数据,我会得到wall[gridA][gridB]wall[gridB][gridA],我想避免,但我不知道如何。

+0

我真的不认为你需要一个4维阵列,假设我理解你是对的。如果我不是,你能更好地解释为什么你需要一个4维数组? – Unlocked

+0

一个给定的墙分离了两块瓦'A'和'B',所以如果我想找到一个分隔两个特定瓦的墙,那么这个想法就是从像墙那样的阵列中抓住它[Ax,Ay] [Bx,By] 希望有道理。我推测我需要这种数组结构来完成它。 – Sir

回答

1

直接考虑你的问题,基本问题是你并不是真的想要创建一个4维数组。相反,您正尝试创建一个二维数组的二维数组。

如果你想做到这一点,你需要首先分配顶级二维数组,然后与其他二维数组元素填充它:

walls = new Wall[grids.GetLength(0), grids.GetLength(1)][,]; 

for (int i = 0; i < grids.GetLength(0); i++) 
for (int j = 0; j < grids.GetLength(1); j++) 
{ 
    walls[I, j] = new Wall[grids.GetLength(0) * 4, grids.GetLength(1) * 4]; 
} 

或者,你可以创建一个真正的四维阵列:

Wall[,,,] walls = new Wall[grids.GetLength(0), grids.GetLength(1), 
          grids.GetLength(0) * 4, grids.GetLength(1) * 4]; 

也就是说,这两种方法对我来说都显得非常浪费。这些数组中的绝大多数元素将不被使用。你只关心每个瓷砖四个墙,所以为什么不每个瓷砖只存储四个?例如:

Wall[,,] walls = new Wall[x, y, 4]; 

(而不是使用GetLength(),我只是重复使用xy变量,在你原来的代码出现来定义网格的尺寸)

然后写一个辅助方法即给定两个不同单元格的x/y位置,将返回所述墙的索引。下面是接近的一种方式:

private static readonly int[,] directions = 
{ 
    { 0, -1 }, 
    { 1, 0 }, 
    { 0, 1 }, 
    {-1, 0 } 
}; 

int GetWallIndex(int x0, int y0, int x1, int y1) 
{ 
    int dx = x0 - x1, dy = y0 -y1; 

    for (int i = 0; i < 4; i++) 
    { 
     if (directions[i, 0] == dx && directions[i, 1] == dy) 
     { 
      return i; 
     } 
    } 

    return -1; 
} 

GetWallIndex()上述方法将返回相应的指数为Wall对象有问题,或者-1如果你传递的是不实际相邻的区块的位置。然后,您可以在三维Wall[,,]数组中使用该索引来获取Wall对象。

这仍然具有无法复制Wall数据的低效率,即对于墙的任一侧上的每个单元一次。恕我直言,这是一个小小的让步,特别是如果Wall对象是一个引用类型(因此唯一重复的是引用本身)。但是,通过将数据存储在字典中并在查看时对瓦片坐标进行标准化,可以消除即使这种低效率也是如此。例如:

struct WallAddress 
{ 
    public int X0 { get; } 
    public int Y0 { get; } 
    public int X1 { get; } 
    public int Y1 { get; } 

    public WallAddress(int x0, int y0, int x1, int y1) 
    { 
     // Optional, not shown here: 
     // Validate addresses to make sure they represent adjacent tiles 

     if (x1 < x0 || (x1 == x0 && y1 < y0)) 
     { 
      int xT = x0, yT = y0; 

      x0 = x1; 
      x1 = xT; 
      y0 = y1; 
      y1 = yT; 
     } 

     X0 = x0; 
     Y0 = y0; 
     X1 = x1; 
     Y1 = y1; 
    } 
} 

Dictionary<WallAddress, Wall> walls = new Dictionary<WallAddress, Wall>(); 

然后你仅仅是为了对瓷砖的每个Wall对象创建WallAddress价值,在字典中填写。

1

不像在Java中,你可以这样做:

walls = new Wall[x][y][x2][y2]; 

C#不会让你初始化这样。有一种方法可以使Wall[,][,]工作,但是制作一个Wall[,,,]的4维数组要更容易。

然而甚至不会工作,因为如果你真的想这样做事有[reallybignumber]维数组(我不知道是做的最好的方式,但我们只是用它去),您需要一个Wall[,,,,]数组来存储x1,y1,x2,y2和墙的方向。虽然这会花费最轻微的速度(可能吗?我实际上并不知道C#中多维数组对性能的影响),但如果你只是去了,你会节省很多内存(并且很健全)用一个字典和结构像Peter Duniho的回答。