在符合多个条件的2D地图上查找位置

时间:2010-03-02 14:17:37

标签: c# .net mono

作为我的个人项目,我开发了一个用户可以随时加入的游戏。 我有一个平铺的世界地图,它是从一个简单的Bitmap创建的,它在整个地图上的随机位置都有资源,除了海洋。

当一个玩家加入我想在一个地方创建他的起始位置时,该地方至少有4个区域中的4个资源的区域(有一个仍然决定直径的圆圈,我认为大约3-4个区块)但是没有海洋瓷砖(Tile.Type!=“ocean”)并且不与属于另一个玩家的字段冲突(Tile.Owner == null)。

地图大小可以变化,目前它是600x450并且它实现为一个简单的数组:Tile [] [],Tile.Resource为null或者将Tile.Resource.Type作为资源名称的字符串(因为它是可配置的)通过明文文件来适应我想要放入的任何风景,所以没有可能的内置枚举。)

我目前有一个简单遍历每个可能位置的循环,检查范围内的每个字段并计算每个资源字段的数量,如果其中一个字段没有,或者如果其中一个属于某个播放器,则丢弃它是一片海洋。

我希望如果它找到一个随机位置但不是必需的,那么单声道兼容性是必需的。

在C#中实现算法的最佳方法是什么?

修改

玩家的区域 )所以预先计算的位置可能不起作用。

6 个答案:

答案 0 :(得分:2)

为什么不循环遍历所有资源,而不是遍历所有位置?您的资源可能更少。然后选择一组符合您的聚类标准的资源。

答案 1 :(得分:1)

假设创建地图后,您不必经常创建新地图。

只需在每个Tile中添加以下内容,并在生成地图后计算一次:

-int NrOceanTiles
-int NrResourceA
-int ...

现在,当你想要一块瓷砖时,你可以更快地完成它:

IEnumerable<Tiles> goodTiles = tiles.Where(tile => tile.NrResourceA >= 1 && tile.NrResourceB >= 2);
Tile goodTile = goodTiles.ElementAt(randomI);

答案 2 :(得分:1)

如果游戏不是为大量玩家设计的,那么大多数游戏都会在地图上实现“起点”。你会亲自挑选它们并以某种方式记录地图中的位置,这可能类似于你实现地图资源的方式(也就是说,在那个地方,有一个你可以拿起的物品,但是在瓷砖地图上面)。

由于资源随机产生,你可能不会在起始点上产生资源(可能是可见的或不可见),或者根本不会在有资源的起始点产生一个玩家(或者看一下9个单元格的盒子找到一个紧密的备用位置。)

当然,您可能希望保留一组可能的起始位置,并在创建和使用资源时更新它。

答案 3 :(得分:1)

预定义数据仍然是最好的前进方式。

在修改地图大小时,添加/丢失资源不会经常发生,只需在数据表发生时更新即可。也许你可以每天进行一次地图/资源更改,并在每日数据库更新中完成所有工作。

通过这种方式,找到有效位置的速度远远快于您搜索周围所有平铺的任何算法。

答案 4 :(得分:1)

您可能会考虑模拟退火......实施起来并不复杂。你有一套具有一定重量的标准,并在一定的“温度”下随机“摇动”位置(温度越高,位置随机移动的半径越大,从之前的位置开始),然后当它“冷却“你根据总重量衡量位置的价值并减去负面的东西,比如产卵太靠近死亡的地方,或者在其他玩家旁边等等......如果价值不在一定范围内,你降低温度,但再次“摇动”位置,冷却,检查重量和总体值,重复直到获得可接受的解决方案。

模拟退火用于地图制作,以最大清晰度标记城市和特征,同时保持在范围内并最小化重叠。由于它是一种启发式方法,因此无法保证会有最佳解决方案,因此您可以“降低温度”并最终选择最佳结果。

答案 5 :(得分:0)

似乎最好的办法是在地图生成时计算开放位置。让您的起始位置计算功能可选择采用网格位置和大小或矩形角。

列出免费地点和占用地点。玩家占领领土?将范围内的资源移动到“已占用”列表。球员被无情地压碎了?将范围内的资源移动到空闲列表。资源消除了?删除在“打开/占用”列表中使用它的所有位置。资源添加?使用效果半径重新计算以确定影响区域。当您的地图区域扩展时,只需在网格+效果半径的新部分上运行初始计算并添加新位置。

然后你必须设置事件并在有人加入时选择随机的免费值。