具有负索引的数组的实现

时间:2012-08-06 23:00:24

标签: c# arrays

我正在与一个向各个方向无限延伸的世界进行游戏。这意味着您可以处于X:50Y:50X:-50Y:-50的位置。但是......我不能用普通的C#List真正做到这一点......

我提出的所有想法似乎都太复杂/无效,无法工作......

6 个答案:

答案 0 :(得分:15)

实现无限网格的最简单方法是使用稀疏矩阵,其中包含x,y对作为键的字典以及要作为值存储的数据。如果网格稀疏,这种方法快速,易于实现,并且内存友好。

另一种方式是链接网格(类似于链表,但指向4个方向),或基于区块的方法来减少链接网格的开销(区块是NxN阵列的链接网格)。磁贴的实现非常复杂,但对于非常密集的网格,它是内存和性能之间的良好折衷。

但我个人最喜欢的方法是使用奇偶变换。所以奇数指数是正数,而偶数指数是负数。要从虚拟索引转换为物理索引,请使用公式p = abs(v * 2) - (v > 0 ? 1 : 0)并将物理转换为虚拟索引v = (p % 2 == 1 ? +1 : -1) * ((2*p + 3) / 4)。之所以出现这种关系,是因为在自然数和整数(0 <-> 0), (1 <-> 1), (2 <-> -1), (3 <-> 2), (4 <-> -2), (5 <-> 3), (6 <-> -3), ...之间存在一对一和关系(双射)。这种方法快速,简单,优雅,但如果你的网格非常稀疏,并且距离中心线很远,那么这种方法就不是很好。

答案 1 :(得分:1)

除非您有单元格的TON(是,TON of bits ...),否则您可以使用字典。将其与System.Drawing.Point组合作为关键,你会得到一件好事:

Dictionary<Point,YourGridObject> myMap = new Dictionary<Point,YourGridObject>();

编辑:除了字典之外,每个单元格都可以引用它的相邻单元格,这样你就可以使用字典直接进入“某处”,然后用相邻的单元格导航。我用这种方式在十六进制网格中实现A *寻路算法。

编辑2: 例如,如果您想要访问特定坐标,则可以简单地

var myTile = myMap[new Point(25, -25)];

然后,您想获得East磁贴,您可以

var eastTile = myTile.East;

您的网格对象也可以实现偏移方法,以便您可以通过

获取“West 2,North 5”磁贴
var otherTile = myTile.Offset(-2, 5);

答案 2 :(得分:0)

如何在两个不同方向上使用两个List进行扩展?

答案 3 :(得分:0)

我不确定这是否比您想要处理的更复杂,但您是否考虑使用极坐标而不是笛卡尔坐标?该坐标系中没有负数。我意识到起初的转变是困难的,但是一旦你绕过它,它就变成了第二天性。

答案 4 :(得分:0)

你可以使用Dictionary,它具有数组的所有功能,但显然是负数索引。

答案 5 :(得分:0)

计算机无法存储无限数组。 数组必须有一个边界,提醒您在数组初始化期间声明了特定大小的代码中的某处。 也许你在某个地方调整它的大小,但是仍然留下0到最大的数字范围

那么你应该做些什么,写一个允许在这样的地图中相对定位的函数。因此,您将当前地图[x,y]存储为位置。 你可以通过一个相对地增加/减少当前位置的功能来提升你的能力。 这样可以使您的代码更易于理解。

如果你没有处理游戏地图而不是数字范围,那么就说矢量 你可以创建一个n点列表,或者一个二维字典。

我在这里发帖,因为你的问题可能会导致人们编写错误的代码。

在地图周围有边框的情况下也可以为其他人添加(通常在游戏场景和图像处理中)。 您的数据来自[-1..width + 1],只需将其标注为[0,width + 2] 然后循环开始'for(int x = 1; x&lt; Width + 1; x ++)'