我想创建2D瓷砖图。示例:
Cell[,] cells;
for(int x = 0; x < columns; x++)
{
for(int y = 0; y < rows; y++)
{
cells[x, y] = new Cell();
}
}
第一个单元格将位于(0 | 0)。如果我想以该单元格为中心并在左侧和顶部创建新单元格该怎么办?这些单元格将具有负索引。
解决此问题的一种方法是确定一个方向的最大长度的值。每边有100张地图的地图会将地图的中心放置在(50 | 50)。
比方说,没有硬件限制,每边没有最大长度,创建具有(0 | 0)中心的2D地图的最佳方法是什么?与通过2D数组中的x和y坐标访问单元格相比,我无法想象出更好的方法。
答案 0 :(得分:4)
嗯,数组是逻辑结构,而不是物理结构。
这意味着我们将0,0
视为top left corner
的方式可能有助于可视化二维数组的内容(实际上,二维数组也有点像可视化帮助),这根本不准确-0,0
“单元格”不是一个角,索引也不是坐标,尽管当您像实际那样思考它们时,确实有助于理解它们。
话虽这么说,没有什么能阻止您创建自己的类,该类实现了可以同时使用正值和负值的索引器-实际上,根据Indexers (C# Programming Guide)-
索引器不必以整数值索引;由您决定如何定义特定的查找机制。
由于您甚至没有义务使用整数,因此您可以肯定地使用正值和负值作为索引器。
我正在测试一种使用列表列表进行存储并根据类索引器动态计算存储索引的想法,但是现在来不及了,我想我太累了,不能正确执行它。有点像其他答案的解决方案,但我试图这样做而没有使您在构造函数中设置最终大小。
答案 1 :(得分:2)
好吧,您不能在数组或列表中使用负索引,它们不是解决此类问题的正确结构。但是,您可以编写自己的类来处理此类问题。 / p>
只需将网格的大小传递到构造函数中,然后使用索引运算符基于调整后的索引返回一个值...像这样的东西...确实非常快地编写了它,所以可能在优化方面并不理想。
public class Grid<T> {
T[,] grid { get; }
int adjustment { get; }
int FindIndex(int provided) {
return provided + adjustment;
}
public Grid(int dimension) {
if (dimension <= 0)
throw new ArgumentException("Grid dimension cannot be <= 0");
if (dimension % 2 != 0)
throw new ArgumentException("Grid must be evenly divisible");
adjustment = dimension / 2;
grid = new T[dimension, dimension];
}
public T this[int key, int key2] {
get {
return grid[FindIndex(key), FindIndex(key2)];
}
set {
grid[FindIndex(key), FindIndex(key2)] = value;
}
}
}
我用这些来测试它:
var grid = new Grid<int>(100);
grid[-50, -50] = 5;
grid[0, 1] = 10;
您可以将其切换为:
var grid = new Grid<Cell>(100);
这仅适用于尺寸相等的网格...如果需要单独的尺寸,则需要调整构造函数和FindIndex方法。
我认为无限大小的网格将很危险。如果将尺寸增加到右侧,则必须重新定位中心。这意味着,由于网格不再正确居中,您认为将为0,0的位置现在将移动。
此外,这种结构的性能将是一场噩梦,因为您不能依赖于无限数组(因为它本质上不是)。因此,您要么必须连续复制数组(如列表的工作方式),要么使用链表。如果使用链表,则必须进行大量迭代才能获得所需的任何值。