我正在尝试用Java制作小型塔防守游戏。我有一个由Point2D.Double
数组组成的网格,名为:
FieldArr并[h] [V]
h
表示水平字段,v
表示垂直垂直字段
这就像这样的网格
+ + + + + + +
S + X + + + +
+ + + X + + +
+ X + + + + F
+ + X + + + +
S表示开始,F表示完成,X表示塔
现在我想计算最短的路线,但我没有任何线索如何开始这个
塔楼有以下vars用于定位: HorizontalNr和VerticalNr。
对于我做的油漆:
public void paint(Graphics2D g2) {
int Xpos = HorizontalNr * playfield.getSquarewidth() + playfield.GetinitialXPos();
int Ypos = VerticalNr * playfield.getSquarewidth() + playfield.GetinitialYPos();
g2.fillRect(Xpos, Ypos, 50, 50);
}
任何人都有任何提示,关于如何制作我的敌人类,所以我不会遇到算法的任何问题? 和/或有关于如何计算最短路径的提示?
已经谢谢了 grt kiwi
答案 0 :(得分:4)
shortest path problem已经进行了很多研究,很多文献都存在这个问题。最好只使用现有算法,而不是自己发明算法。
例如,一个简单而有效的算法是Dijkstra's algorithm。来自维基百科:
- 让我们开始的节点称为初始节点。设节点Y的距离是从初始节点到Y的距离.Dijkstra算法将分配一些初始距离值,并尝试逐步改进它们。 为每个节点分配一个暂定距离值:为我们的初始节点设置为零,为所有其他节点设置为无穷大。
- 标记未访问的所有节点。将初始节点设置为当前节点。创建一组称为未访问集的未访问节点,其中包含除初始节点之外的所有节点。
- 对于当前节点,考虑所有未访问的邻居并计算其暂定距离。例如,如果当前节点A标记为临时距离6,并且将其与邻居B连接的边缘具有长度2,则到B(通过A)的距离将是6 + 2 = 8。如果该距离小于先前记录的B的临时距离,则覆盖该距离。即使邻居已被检查过,但此时并未将其标记为已访问,并且它仍保留在未访问的集合中。
- 当我们考虑当前节点的所有邻居时,将当前节点标记为已访问并将其从未访问的集合中删除。永远不会再次检查受访节点;现在记录的距离是最终的,最小的。
- 如果目标节点已被标记为已访问(在规划两个特定节点之间的路由时)或未访问集合中节点之间的最小暂定距离是无穷大(计划完整遍历时),则停止。算法已经完成。
- 将标记有最小暂定距离的未访问节点设置为下一个“当前节点”,然后返回步骤3.
醇>
答案 1 :(得分:2)
如果你想要避开塔楼,那么你要从头到尾寻找欧几里德路径,这可以用最短的路径来解决ala djkstra。
答案 2 :(得分:1)
正如马克所说,这是最短路径问题,可以轻松有效地解决。
请注意,由于您的问题未加权,因此您可以在此处使用BFS,这非常容易实现,并且还可以保证找到未加权图的排序路径。
BFS的伪代码:
findShortestPath(source,target):
queue<- new queue
visited <- {}
Map<point,point> parents <- empty map
queue.push(source)
while (queue.empty() == false):
current <- queue.takeFirst()
if (current.equals(target)):
extract the path from source to destination using the map parents(*)
return
visited.add(current)
for each p such that p and current are neighbors: //insert neighbors to queue
if p is not in visited:
if (p is not an obstacle):
queue.push(p)
parents.put(p,current) //current is the parent of p
(*)从地图中提取路径很简单:只需按照current <- parent.get(current)
进行操作,直到获得null
,这样就可以提取您将使用的确切路径。
请注意,更快的解决方案[在大多数情况下]将A* manhattan distance heuristic,但实施起来要复杂得多。