具有负索引的数组的实现
本文关键字:数组 实现 索引 | 更新日期: 2024-11-08 01:57:36
我正在制作一个游戏,其世界向各个方向无限延伸。这意味着你可以处于位置X:50
、Y:50
或X:-50
、Y:-50
。但。。。我真的不能用普通的 C# 列表做到这一点......
我想出的所有想法似乎都太复杂/效率低下而无法工作......
实现无限网格的最简单方法是使用稀疏矩阵,其中包含一个字典,其中 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), ...
。这种方法快速、简单且优雅,但当您的网格非常稀疏且项目离中心线非常远时,内存方面不是很好。
除非你有一吨(是的,一吨位...),否则你可以使用字典。将其与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;
网格对象还可以实现偏移方法,以便通过以下方式获取"西 2,北 5"磁贴
var otherTile = myTile.Offset(-2, 5);
在下面使用两个列表进行两个不同方向的扩展怎么样?
我不确定这是否比您想要处理的更复杂,但是您是否考虑过使用极坐标而不是笛卡尔坐标? 该坐标系中没有负数。 我意识到这种转移一开始很困难,但一旦你把头缠绕在它周围,它就会成为第二天性。
您可以使用字典,它具有数组的所有功能,但显然具有负索引。
计算机不能存储无限的数组。数组必须有边界,提醒您在代码中的某个地方在数组初始化期间声明了特定大小。也许您在某处调整了它的大小,但这仍然留下了一个从 0..到. 的数字范围。.max。
所以你应该做的是,写一个允许在这样的地图中相对定位的函数。因此,您将当前地图[x,y]存储为位置。并且您可以通过拥有一个相对地从当前位置添加/减法的函数来上升。这也使您的代码更易于理解。
如果你不处理游戏地图而是处理数字范围,让我们说向量您可以创建 n 个点的列表或 2D 字典。
我在这里发布它,因为您的问题可能会导致人们编写错误的代码。
还为地图周围有边框的其他人添加(典型的游戏场景和图像处理。您的数据从 [-1..width+1] 开始,只需将其尺寸为 [0,width+2]然后循环从"for (int x = 1; x <Width+1;>