【问题标题】:Is there a faster for me to look to a specific index without using an array?在不使用数组的情况下,我是否可以更快地查看特定索引?
【发布时间】:2019-01-19 17:05:42
【问题描述】:

我正在创建一种 2D 地图,其中的坐标附有 tile 类, tile 类将在其中包含其坐标,以及稍后将访问的其他一些值,但我希望该映射没有大小限制。问题是,我想在该地图中查看一些 tile 内部的值,例如:我在 coord(25,30) 并且我想知道每个相邻的 tile 类中的布尔值tile.

  • 如果我使用数组,我可能有最快的方法来检查 tile 的坐标,例如2 个索引的数组。我可以将每个索引分别设为 x 和 y 坐标,因此我只会在看到 tile 上的值时检查该坐标。 但地图会有大小限制

  • 如果我使用列表地图将没有大小限制,但我无法直接检查坐标,所以我需要通过每个创建的 tile foreach 循环,并检查该图块内的坐标是否与我要查找的坐标相同。

  • 我目前的解决方案是有一个只有坐标的第二个列表,并在我创建图块时分配它,因此坐标列表中的索引与图块列表中的索引相同。因此,当我需要检查某个图块时,我会执行 CoordinateList.Contains(coordinate),如果这是真的,那么我将该坐标的索引作为代码应该在 tile 列表中查找的索引。

我想要一种更快的方法来检查图块,没有大小限制。

到目前为止,使用tile 列表,我每次检查整个地图的时间大约为 3200 毫秒(列表中大约有 2000 个tiles)。

使用mapCoord 列表,我得到了大约 1500 毫秒(大约 2000 个图块和坐标)。

使用数组,我得到了非常快的响应(从未测量过),但肯定不到我的第二次……因为我从来不用检查整个数组,而是检查某个索引。

更容易理解我的问题的示例:

注意1:它不会填满整个数组。

注意2:它并不总是矩形的。

int size = 50;
Tile[,] mapArray = new Tile[size,size];
List<Tile> mapList = new List<Tile>();
List<Vector2Int> mapCoord = new List<Vector2Int>();
void CreateMap()
{
    for(int x = size/2; size <= size/2; x++)
    {
        for(int y = size/2; size <= size/2; y++)
        {
        if(x > 2 && y > 3)
            {
            mapArray[x,y] = new Tile(new Vector2Int(x,y), false, 32);
            mapList.add(new Tile(new Vector2Int(x,y), false, 32));
            mapCoord.add(new Vector2Int(x,y));
            }
        }
    }
}

所以如果我要检查数组中的tile,我只会检查数组中的坐标,因为tile 坐标与数组索引相同,但它会有大小限制。

如果我要检查列表中的图块,我需要像这样执行foreach 循环。对性能和优化非常不利。

Tile desiredTile = null;
for each(Tile tile in mapTiles)
{
    if(tile.Coord == DesiredCoord)
        desiredTile = tile;
}

到目前为止,最好的方法是检查mapCoord 列表,如下所示:

if(mapCoord.Contains(desiredCoord))
{
    desiredTile = mapList[mapCoord.IndexOf(DesiredCoord)];
}

【问题讨论】:

  • size &lt;= size/2曾经会变成true吗?检查你的循环条件。
  • 查找“稀疏数组”作为一种方法。一种可能的实现是字典,其中键实际上是两个整数(x 和 y)的元组。如果游戏以标准边界开始(比如起点的 +/- 100),您可以混合和匹配 200x200 数组和除此之外的字典。您还可以通过将多个矩形区域作为一个数组来获得创意。
  • @spender 它是一种类型,它的意思是 x = -size/2 不是正数,y 也一样
  • @Flydog57 字典真的为我做了,从 1500 毫秒到几乎 10 毫秒,你的想法真的很好,谢谢...

标签: c# arrays list unity3d optimization


【解决方案1】:

查找“稀疏数组”作为一种方法。一种可能的实现是字典,其中键实际上是两个整数(x 和 y)的元组。如果游戏以标准边界开始(比如起点的 +/- 100),您可以混合和匹配 200x200 数组和除此之外的字典。您还可以通过将多个矩形区域作为一个数组来获得创意。

如果您的总地址空间适合一个短整数 (+/- 32k),那么您可以执行以下操作:

[StructLayout(LayoutKind.Explicit)]
struct IntXY
{
    [FieldOffset(0)] Int16 X;
    [FieldOffset(2)] Int16 Y;
    [FieldOffset(0)] UInt32 AsAnUnsignedInteger;

    public override int GetHashCode()
    {
        return AsAnUnsignedInteger.GetHashCode();
    }
}

并将其用作 Dictionary 中的键(使用 LayoutKind.Explicit 使其实际上与 C/C++ union 相同 - X 和 Y 短裤占用与无符号整数相同的 32 位组合)。它可能比Tuple&lt;int, int&gt; 便宜(尽管您可能想测试我的猜测)。

【讨论】:

    猜你喜欢
    • 2016-06-26
    • 1970-01-01
    • 2020-12-09
    • 2013-10-23
    • 1970-01-01
    • 2013-01-02
    • 2014-03-31
    • 1970-01-01
    • 2017-04-07
    相关资源
    最近更新 更多