C#-A*算法给出了错误的结果
我正在尝试用C#制作4向A星寻路算法,但无法使其正常工作。在Main方法中,我有一个示例5x5 int数组映射来设置哪些字段可以访问,哪些字段不能访问(0-清除字段,1-障碍)。例如,我将起点设置为(1,3),目标点设置为(4,4),所以我希望路径能够避开墙并继续前进,等等,但事实并非如此。我甚至让我的算法显示每一位家长及其继任者(邻居)。在我的例子中,它显示(2,4)作为一个节点,尽管被标记为字段中的障碍物(Map),它是如何发生的?GetSuccessivers方法中有一条明确的语句,只包含标记为0的语句,但它仍然包含(2,4)点。我不确定GetSuccessivers或FindPath(主算法)是否有问题 示例地图:C#-A*算法给出了错误的结果,c#,algorithm,a-star,C#,Algorithm,A Star,我正在尝试用C#制作4向A星寻路算法,但无法使其正常工作。在Main方法中,我有一个示例5x5 int数组映射来设置哪些字段可以访问,哪些字段不能访问(0-清除字段,1-障碍)。例如,我将起点设置为(1,3),目标点设置为(4,4),所以我希望路径能够避开墙并继续前进,等等,但事实并非如此。我甚至让我的算法显示每一位家长及其继任者(邻居)。在我的例子中,它显示(2,4)作为一个节点,尽管被标记为字段中的障碍物(Map),它是如何发生的?GetSuccessivers方法中有一条明确的语句,只包含
int[,] fields = new int[5, 5] //MAP, 1 - OBSTACLE
{
{ 0, 0, 0, 0, 0 },
{ 0, 1, 1, 1, 0 },
{ 0, 1, 1, 1, 0 },
{ 0, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 0 }
};
举例:
Node start = new Node(1, 3); //START LOCATION ON MAP
Node target = new Node(4, 4); //TARGET LOCATION ON MAP
生成的路径(从目标到开始):
完整代码(FindPath和GetSuccessivers是主要的方法,但我仍然可能在其他方法中出错):
使用系统;
使用System.Collections.Generic;
使用System.Linq;
名称空间FoxLib
{
公共类节点
{
公共节点(整数x,整数y)
{
这个.x=x;
这个。y=y;
}
公共int x,y;//在地图上的位置
公共节点父节点;//以后需要检索路径
公共int G、H、F;
//G-从开始节点到该节点的成本
//H-从该节点到目标的成本(启发式)
//F-G+H;节点成本
}
公共类寻路
{
公共静态void FindPath(int startX、int startY、int targetX、int targetY、int[,]字段)//主算法
{
bool pathFound=false;//路径可用吗?
Node start=新节点(startX,startY);//开始节点
节点目标=新节点(targetX,targetY);//目标节点
start.parent=开始;
start.G=0;
start.H=Math.Abs(target.x-start.x)+Math.Abs(target.y-start.y);
start.F=start.G+start.H;
节点当前=新节点(0,0);
List openList=new List();//等待检查的节点
List closedList=new List();//已选中节点
openList.Add(开始);
while(openList.Count>0)//只要还有节点要发现,就执行此操作
{
current=MinFNode(openList);//查找F成本最低的节点(较低=较好的路径)
openList.Remove(当前);//从队列中删除当前节点
if((current.x==target.x)&&&(current.y==target.y))//找到目标
{
Console.WriteLine(“找到路径”);
pathFound=true;
//通过检查父项显示路径(从目标到开始)
Console.WriteLine(“[FULL PATH]”);
做
{
Console.WriteLine(current.x+“,”+current.y);
current=current.parent;
}而((current.x!=start.x)&&(current.y!=start.y));
控制台写入线(start.x+“,”+start.y);
打破
}
列表继任者=GET继任者(current.x,current.y,fields);//获取继任者
foreach(后续节点中的节点)
{
node.parent=current;//将当前节点设置为父节点,以便稍后检索路径
node.G=current.G+10;//10—从当前到其后续节点的距离,从当前到开始的当前.G距离
node.H=Math.Abs(target.x-node.x)+Math.Abs(target.y-node.y);//到目标的启发式距离
node.F=node.G+node.H;//节点最终成本
Console.WriteLine(current.x+“,“+current.y+”父级|后继者:“+node.x+”,“+node.y);//测试显示以检查生成的后继者当前节点
if(closedList.FirstOrDefault(l=>l.x==node.x&&l.y==node.y)!=null)//如果已关闭列表中已存在后续项
{
Node temp=closedList.FirstOrDefault(l=>l.x==Node.x&&l.y==Node.y);
if(node.Fl.x==node.x&&l.y==node.y)!=null)//如果后续项已存在于打开的列表中
{
Node temp=openList.FirstOrDefault(l=>l.x==Node.x&&l.y==Node.y);
if(node.F4, 4
3, 4
2, 4
1, 3
using System;
using System.Collections.Generic;
using System.Linq;
namespace FoxLib
{
public class Node
{
public Node(int x, int y)
{
this.x = x;
this.y = y;
}
public int x, y; //POSITION ON MAP
public Node parent; //NEEDED TO RETRIEVE PATH LATER
public int G, H, F;
//G - COST FROM START NODE TO THIS NODE
//H - COST FROM THIS NODE TO TARGET (HEURISTIC)
//F - G + H; NODE COST
}
public class Pathfinding
{
public static void FindPath(int startX, int startY, int targetX, int targetY, int[,] fields) //MAIN ALGORITHM
{
bool pathFound=false; //IS PATH AVAILABLE?
Node start = new Node(startX, startY); //STARTING NODE
Node target = new Node(targetX, targetY); //TARGET NODE
start.parent = start;
start.G = 0;
start.H = Math.Abs(target.x - start.x) + Math.Abs(target.y - start.y);
start.F = start.G + start.H;
Node current = new Node(0, 0);
List<Node> openList = new List<Node>(); //NODES WAITING TO BE CHECKED
List<Node> closedList = new List<Node>(); //ALREADY CHECKED NODES
openList.Add(start);
while(openList.Count>0) //DO AS LONG AS THERE ARE STILL NODES TO DISCOVER
{
current = MinFNode(openList); //FIND NODE WITH LOWEST F COST (LOWER=BETTER PATH)
openList.Remove(current); //REMOVE CURRENT NODE FROM QUEUE
if ((current.x==target.x)&&(current.y==target.y)) //TARGET FOUND
{
Console.WriteLine("PATH FOUND");
pathFound = true;
//DISPLAY PATH (FROM TARGET TO START) BY CHECKING PARENTS
Console.WriteLine("[FULL PATH]");
do
{
Console.WriteLine(current.x + ", " + current.y);
current = current.parent;
} while ((current.x != start.x) && (current.y != start.y));
Console.WriteLine(start.x + ", " + start.y);
break;
}
List<Node> successors = GetSuccessors(current.x, current.y, fields); //GET SUCCESSORS
foreach (Node node in successors)
{
node.parent = current; //SET CURRENT NODE AS PARENT TO RETRIEVE PATH LATER
node.G = current.G + 10; //10 - DISTANCE FROM CURRENT TO ITS SUCCESSOR, current.G DISTANCE FROM CURRENT TO START
node.H = Math.Abs(target.x - node.x) + Math.Abs(target.y - node.y); //HEURISTIC DISTANCE TO TARGET
node.F = node.G + node.H; //NODE FINAL COST
Console.WriteLine(current.x + ", " + current.y + " PARENT | SUCCESSOR: " + node.x + ", " + node.y); //TEST DISPLAY TO CHECK SUCCESSORS CURRENT NODE PRODUCED
if (closedList.FirstOrDefault(l => l.x == node.x && l.y == node.y) != null) //IF SUCCESSOR ALREADY EXISTS ON CLOSED LIST
{
Node temp = closedList.FirstOrDefault(l => l.x == node.x && l.y == node.y);
if (node.F < temp.F) //IF NEW PATH TO THIS NODE IS BETTER? (LOWER F = SHORTER PATH)
{
closedList.Remove(temp); //REMOVE OLD NODE
temp.parent = node.parent;
temp.F = node.F;
closedList.Add(temp); //ADD UPDATED NODE
}
}
else
if(openList.FirstOrDefault(l => l.x == node.x && l.y == node.y) != null) //IF SUCCESSOR ALREADY EXISTS ON OPEN LIST
{
Node temp = openList.FirstOrDefault(l => l.x == node.x && l.y == node.y);
if (node.F < temp.F) //IF NEW PATH TO THIS NODE IS BETTER? (LOWER F = SHORTER PATH)
{
openList.Remove(temp); //REMOVE OLD NODE
temp.parent = node.parent;
temp.F = node.F;
openList.Add(temp); //ADD UPDATED NODE
}
}
else
{
openList.Add(node); //ADD SUCCESSOR TO OPEN LIST
}
}
closedList.Add(current); //MARK CURRENT NODE AS CHECKED (NO NEED TO CHECK IT UNTIL BETTER PATH TO THIS NODE IS FOUND)
}
if(!pathFound)
{
Console.WriteLine("PATH NOT FOUND");
}
}
//FIND NODE WITH LOWEST F COST
public static Node MinFNode(List<Node> nodes)
{
Node result = nodes[0];
foreach(Node node in nodes)
{
if (node.F < result.F)
result = node;
}
return result;
}
//GET SUCCESSORS OF CURRENT NODE (ONLY THE ONES WITH "0" VALUE)
public static List<Node> GetSuccessors(int x, int y, int[,] fields)
{
List<Node> Successors = new List<Node>();
if ((x - 1 >= 0) && (fields[x - 1, y]==0))
Successors.Add(new Node(x - 1, y)); //LEFT
if ((x + 1 < fields.GetLength(0)) && (fields[x + 1, y]==0))
Successors.Add(new Node(x + 1, y)); //RIGHT
if ((y - 1 >= 0) && (fields[x, y - 1]==0))
Successors.Add(new Node(x, y - 1)); //UP
if ((y + 1 < fields.GetLength(1)) && (fields[x, y + 1]==0))
Successors.Add(new Node(x, y + 1)); //DOWN
return Successors; //RETURN LIST OF AVAILABLE SUCCESSORS
}
static void Main()
{
int[,] fields = new int[5, 5] //MAP, 1 - OBSTACLE
{
{ 0, 0, 0, 0, 0 },
{ 0, 1, 1, 1, 0 },
{ 0, 1, 1, 1, 0 },
{ 0, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 0 }
};
Node start = new Node(1, 3); //START LOCATION ON MAP
Node target = new Node(4, 4); //TARGET LOCATION ON MAP
FindPath(start.x,start.y,target.x,target.y,fields); //MAIN ALGORITHM
Console.WriteLine("END");
Console.ReadLine();
}
}
}