我很难弄清楚如何正确设置我的阵列。
我有一个基本的图块阵列设置到我的数组grid[,]
这很好。
现在我正在尝试为网格之间的边缘制作一个数组,这样我就可以放下墙了。
所以我有这个:walls[,][,]
其中每个[,]
是一个网格位置,因此每个墙分隔2个网格位置。
这里的最终目标是我想要一个带有两个网格点的墙阵列,如A
和B
,这样我就可以这样做:
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]
我想避免但我不会#39 ;我知道如何。
答案 0 :(得分: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()
,我只是重复使用原始代码中的x
和y
变量来定义网格的尺寸。)
然后编写一个辅助方法,给定两个不同单元格的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>();
然后,您只需为每个WallAddress
对象创建一对图块的Wall
值,然后填写字典。
答案 1 :(得分:1)
与Java不同,您可以执行以下操作:
walls = new Wall[x][y][x2][y2];
C#不会让你这样初始化。有一种方法可以使Wall[,][,]
起作用,但是制作Wall[,,,]
的4维数组要容易得多。
然而,这甚至都行不通,因为如果你真的想用[reallybignumber]维度数组做这样的事情(我不确定这是最好的方法,但让我们去吧) ,你需要一个Wall[,,,,]
数组来存储x1,y1,x2,y2和墙面方向。
虽然这会花费最多的速度(可能?我实际上并不知道C#中多维数组的性能影响),如果你只是去,你会节省很多内存(和理智)像Peter Duniho的回答一样的字典和结构。