我正在创建一个简单的 XNA C# 自上而下的游戏。在游戏中,您将被一个像迷宫一样的地图周围的敌人跟踪。ATM 我已经设置好了,当游戏开始时,敌人会找到通往你的最短路径(它确实如此)。如果玩家移动了,则每秒都会找到一条新路径。
游戏总能找到一条通往你的路线,但似乎很难找到通往移动目标的最短路线,有时在你移动时会进入循环,当你停下来时,敌人会绕着地图绕半圈找到你,即使你只有几步之遥。它似乎不是启发式的,因为我删除了它(使其成为dijkstra),它似乎仍然存在同样的问题。我认为这是我忽略的简单事情,但我无法弄清楚是什么。
提前致谢
class PathFinder
{
private Cell[,] map = Game1.cellArray;
public List<Cell> calculate(int currX, int currY, int destX, int destY)
{
resetMap();
Debug.WriteLine("starting over");
List<Cell> path = new List<Cell>();
List<Cell> openList = new List<Cell>();
List<Cell> closedList = new List<Cell>();
Cell startPos = map[currY, currX];
Cell endPos = map[destY, destX];
startPos.closed = true;
closedList.Add(startPos);
Cell curPos = startPos;
while (!closedList.Contains(endPos))
{
//add adjacent nodes to list, discover their scores
foreach (Cell v in getAdj(curPos))
{
if (v.walkable == true && v.closed == false)
{
if (!openList.Contains(v))
{
v.parent = curPos;
v.H = getH(v, endPos);
v.G = v.parent.G + 10;
v.F = v.G + v.H;
openList.Add(v);
}
//if square already on list would benefit from current tile being parent, make it so
else if (curPos.G + 10 < v.G)
{
v.parent = curPos;
v.G = v.parent.G + 10;
v.F = v.G + v.H;
}
}
}
if (openList.Count <= 1) {/*Console.WriteLine("Returned NULL");*/ return null; }
curPos = openList[1];
curPos.closed = true;
closedList.Add(curPos);
openList[1] = openList[openList.Count - 1];
openList.RemoveAt(openList.Count - 1);
openList.OrderBy(o => o.F);
openList.Reverse();
}
//backtrack to discover path
Cell curNode = endPos;
path.Add(endPos);
while (curNode != startPos)
{
curNode = curNode.parent;
path.Add(curNode);
Debug.WriteLine("Path// X: " + curNode.xLocation + " Y: " + curNode.yLocation);
}
path.Reverse();
return path;
}
//finds heuristic of current square by checking distance to destination ignoring walls
private int getH(Cell curPos, Cell endPos)
{
int diffX = curPos.xLocation - endPos.xLocation;
int diffY = curPos.yLocation - endPos.yLocation;
if (diffX < 0)
{
diffX *= -1;
}
if (diffY < 0)
{
diffY *= -1;
}
return ((diffX + diffY) * 10);
}
//get list of adjacent Cells
private List<Cell> getAdj(Cell curPos)
{
List<Cell> adjList = new List<Cell>();
if (curPos.xLocation - 1 >= 0){
adjList.Add(map[curPos.yLocation, curPos.xLocation - 1]);
}
if (curPos.xLocation < 19)
{
adjList.Add(map[curPos.yLocation, curPos.xLocation + 1]);
}
if (curPos.yLocation - 1 >= 0)
{
adjList.Add(map[curPos.yLocation - 1, curPos.xLocation]);
}
if (curPos.yLocation < 19)
{
adjList.Add(map[curPos.yLocation + 1, curPos.xLocation]);
}
return adjList;
}
private void resetMap()
{
//reset Cells to default values
for (int r = 0; r < map.GetLength(1); r++)
{
for (int c = 0; c < map.GetLength(0); c++)
{
map[r, c].reset();
}
}
}
}