2012-08-06 38 views
7

我正在制作一个游戏,游戏的方向无限延伸。这意味着您可以在位置X:50,Y:50X:-50,Y:-50。但是...我真的不能做到这一点与普通的C#列表...负指数阵列的实现

我拿出所有的想法似乎过于复杂/低效的工作...

+0

通常它与模数运算符 – 2012-08-06 23:01:38

+0

护理实现为详细一点更 – Entity 2012-08-06 23:14:09

+0

没关系我的意见上面,我正在考虑其他的东西,请看下面的答案,而不是 – 2012-08-07 00:54:59

回答

14

最简单的实现无限网格的方法是使用一个带有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), ...。这种方法是快速,简单和优雅的,但是当你的网格非常稀疏并且距离中心线很远时,记忆并不是很好。

+0

我认为偶数的方法对我所做的工作很好。感谢:) – Entity 2012-08-08 10:47:12

1

除非你有单元格的TON(是,TON位......),你可以使用字典。再加上一个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; 

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

var otherTile = myTile.Offset(-2, 5); 
获得'West 2,North 5'
+0

因此,让我们说我想找到位置'25','-25' ......我会使用'.Where(...)'函数吗? – Entity 2012-08-07 13:08:47

+0

而不是添加对相邻单元格的引用,而是可以更容易地存储对Point对象的引用,您可以通过在Point的坐标中添加/减去来查找相邻元素。根据程序结构的不同,这些非规范化可能会非常有用或不必要地复杂化。 – 2012-08-07 13:27:40

+0

@TheAdamGaskins我在我的答案中添加了一些元素,但这只是建议。我不知道你的瓷砖到底想做什么,但实现它的最佳方式实际上取决于你将如何使用它。 – Tipx 2012-08-07 17:08:28

0

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

0

我不确定这是否比您想要处理的更复杂,但您是否考虑过使用极坐标而不是笛卡尔?该坐标系中没有负数。我意识到开始的时候这个盖子很困难,但是一旦你将它包裹起来,它就成为第二天性。

0

你可以使用字典,它具有数组的所有功能,除了明显的负数索引。

0

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

所以你应该做的,写一个功能,允许在这样的地图相对定位。因此,您将当前的地图[x,y]存储为一个位置。 通过具有相对于您当前位置添加/减少的功能,您可以上升。 这可以让您的代码更易于理解。

如果你不处理游戏地图,但数字范围,可以说矢量 你可以创建一个n点或2d字典的列表。

我在这里发布,导致您的问题可能导致人们写错码。

还为其他人在地图周围存在边界的情况下添加(在游戏场景中为典型情况,并且图像处理为 ,其中数据从[-1..width + 1]开始,只是将其尺寸标为[0 ,宽度+ 2] 然后循环槽它开始“为(INT X = 1; X <宽度+ 1; X ++)”?