【问题标题】:Array with negative indexes具有负索引的数组
【发布时间】:2013-03-21 18:06:12
【问题描述】:

我有一个数组,用于存储我正在开发的游戏的地图数据。

MyMapType[,,] map; 

我使用固定数组而不是 Collection 的原因是因为固定数组的工作速度非常快。

现在我的问题是,我想在游戏中支持负 z 水平。所以我希望能够访问负索引。

如果这不可行,我想到了另外一对解决方案。

我正在考虑将地平面设置为任意数字(例如 10)作为可能的解决方案,任何小于 10 的都可以被视为负数。但是如果不使用,这不会让数组变大 10 倍吗?

我考虑的另一个解决方案是“滚动我自己的”,您有一个二维数组字典,列表中的 Z 级别作为索引。但这还有很多工作要做,我不确定它是否慢。

所以总结一下 - 创建支持负索引的数组的任何方式?如果没有 - 是否有一种简洁的方法可以“模拟”此类行为而不会牺牲太多 CPU 时间或 RAM - 请注意这些游戏地图最终可能会很大并且需要不断访问。

【问题讨论】:

  • 向数组添加 10 个额外元素不会使其变大一个数量级(除非数组只有 ~1 个元素开始)。
  • @MattBall - 它是一个多维数组,10x10x1 不是 10x10x10 大小的 1/10 吗?
  • 如果你追求速度,多维数组是个坏主意。它们比一维数组慢得多。如果您正在构建的地图数据大部分是空白空间或有很多冗余,那么不可变四叉树可能是比数组更好的数据结构;访问速度较慢,但​​您可以在相对较少的内存中表示任意大的区域。而且它们很容易支持负指数。]
  • @Haedrian:它们是一维数组,通过简单的数学运算可以找到正确的记录。但是数学是通过辅助方法完成的,这会导致开销。如果您对其进行分析,您会发现与其他变量访问相比,.NET 中的多维数组访问非常慢。

标签: c# arrays multidimensional-array


【解决方案1】:

用一个类替换你的数组:

class MyArray {
    private MyMapType[] myArray = new myMapType[size]
    MyMapType this[index] {
       get{return myArray[index + offset];}
    }

}

您可以在构造函数中设置大小和偏移量,甚至可以随意更改。

在此示例的基础上还有另一个版本:

class MyArray {
    private MyMapType[] positives = new myMapType[size]
    private MyMapType[] negatives = new myMapType[size-1]
    MyMapType this[index] {
       get{return index >= 0 ? positives[index] : negateves[1-index];}
    }

}

这并没有改变您需要为它们设置大小的事实。老实说,我更喜欢第一个

【讨论】:

  • 这个解决方案会让他定义偏移量。
  • 问题是我需要一个多维数组。所以我需要重写一堆代码来获得 xth,yth,zth 值。嗯。
  • @aguyngueran 是的,但他无论如何都想这样做,这无论如何都是不可避免的。定义偏移量与定义大小没有什么不同,如果你想要数组,你就无法摆脱它
  • @Haedrian 考虑到 Eric Lippert 的评论,考虑类的一维数组
  • 嗯,我喜欢你的第二个,它适用于多维数组而不会增加太多开销(如果我发现它太慢,我会考虑像 Eric Lippert 建议的四叉树,但是就我的目的而言,我认为它会足够快)
【解决方案2】:

如果你想要“负”索引,C# 8 现在支持它。

var words = new string[]
{
                // index from start    index from end
    "The",      // 0                   ^9
    "quick",    // 1                   ^8
    "brown",    // 2                   ^7
    "fox",      // 3                   ^6
    "jumped",   // 4                   ^5
    "over",     // 5                   ^4
    "the",      // 6                   ^3
    "lazy",     // 7                   ^2
    "dog"       // 8                   ^1
};              // 9 (or words.Length) ^0

所以调用否定的会是这样的

words[^1]

看到这个link

所以在你的情况下,中间元素可能是零 Z

【讨论】:

  • 要指出调用words[^1] 将等同于调用words[8] 直言不等于调用words[-1]
【解决方案3】:

您能否尝试将 MyMapTime[,] 列表存储在两个列表中:

  • 1 表示 z 值大于或等于 0
  • 和第二个负 z 值。

表的索引将是 z 的值。 这样做可以让您快速访问特定 z 水平的 xy 值。 当然,问题是:你的 z 值是多少?有稀疏的还是密集的。 即使对于稀疏值,您最终也会得到一个数组,其中包含 [,] 的空值。

【讨论】:

    【解决方案4】:

    使用 Dictionary 类,因为您可以为键或值分配您想要的任何值。虽然我不确定这对于您上面显示的 3 维数组如何工作,但我可以展示如果这是一个 1 维数组,这将如何工作,并且您可以推断如何最好地利用它:

    MyMapType[] map;
    
    //map is filled with w/e data
    
    Dictionary<int, MyMapType> x = new Dictionary<int, MyMapType>();
    
    x[-1] = //(map data for whatever value is for the negative value);
    x[0] = map[0]
    //(etc...)
    

    【讨论】:

    • 我也有同样的想法。但我也只需要一个双向的 1-dim 数组。也应该可以使用 3D 数组:Dictionary&lt;int, Dictionary&lt;int, Dictionary&lt;int, MyMapType&gt;&gt;&gt;
    【解决方案5】:

    我想在这里指出,字典允许负索引 2D 字典也可以解决此类问题,只需考虑数据结构以及是否可以使用字典

    请注意,字典和列表用于不同的场景。 它们的速度取决于它们使用的功能

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-18
      • 1970-01-01
      • 2018-09-22
      • 2014-01-21
      • 2011-04-29
      • 2020-02-03
      • 1970-01-01
      相关资源
      最近更新 更多