抱歉,标题不太丰富,我想不出更好的办法了。当我说有效时,我指的是不占用CPU的代码。
问题:
想象一下由块状构成的3D宇宙飞船,就像我的世界中的一艘船。我想在自制船类中存储此造船中每个块的位置。
为此,我在Ship类中使用了private List<ShipBlock> shipBlocks;
。这里的ShipBlock是一个自制类,它以向量Vec3(int x, int y, int z)
的形式保存位置,以及与该问题无关的其他信息。
但是现在我想在船上进行测试。船舶是否在某个testPosition(x,y,z)上包含一个ShipBlock,如果是,则为此返回ShipBlock。但是,我还没有找到有效执行此操作的方法。遍历整个List并根据测试位置测试每个位置非常昂贵,我希望它能很快。
因此,我决定制作一个Map<Vec3, ShipBlock> shipBlocksMap
来存储信息。钥匙将是ShipBlock的位置。我可以简单地执行shipBlocksMap.get(testPosition)
,如果船在该位置有一个ShipBlock,它将返回正确的ShipBlock。如果不是,它将返回null。
直到我搬船并且所有ShipBlock都获得了新职位之前,这似乎正是我想要的。我在这里了解到,如果您作为键提供的对象发生更改,则地图中的键不会更改。因此,如果我现在要使用shipBlocksMap.get(testPosition)
并在移动的船上使用一个位置,则由于键的位置仍然是旧位置,它将返回null。 (很抱歉,如果我感到困惑,我不确定如何更好地解释它)
题:
我在这里要问的问题是:假设船舶是否可以包含成千上万个ShipBlock,那么测试它是否包含具有特定位置的ShipBlock的最有效方法是什么?而且我应该以什么方式存储船上的ShipBlocks,以便这种检查有效地进行?
码:
如果有人想在这里看到它,那就是Ship和ShipBlock类的代码。
public class ShipBlock
{
public Vec3 position;
public String shipBlockType;
public ShipBlock(Vec3 position, String shipBlockType)
{
this.position= position;
this.shipBlockType = shipBlockType;
}
}
public class Ship
{
private Map<Vec3, ShipBlock> shipBlocksMap;
public Ship(Map<Vec3, ShipBlock> shipBlocksMap)
{
this.shipBlocksMap = shipBlocksMap;
}
public ShipBlock containsShipBlock(Vec3 position)
{
return shipBlocksMap.get(position);
}
}
最佳答案
我认为最重要的设计更改是保存块相对于船的位置。
这样,您无需在飞船移动时更改块的键,并且可以轻松地使用Map<Vec3, ShipBlock> shipBlocksMap
进行恒定时间测试,此时键就是相对位置。
您可以通过计算(概念上)relative_block_pos = absolute_block_pos - ship_pos
来获得相对位置。
这意味着您需要存储船的位置。
作为一种选择,您可以简单地选择船的第一个块作为船的位置,因此,第一个块始终具有坐标(0, 0, 0)
。
这样,将所有块的坐标更改减少到最小(但在大多数情况下不需要这样做)。