我正在编写一个在7x7瓷砖上设置的游戏脚本,玩家总是在中间(图24(。零作为视觉添加,实际上是一个数组,而不是7x7 2D数组。
[00,01,02,03,04,05,06]
[07,08,09,10,11,12,13]
[14,15,16,17,18,19,20]
[21,22,23,24,25,26,27]
[28,29,30,31,32,33,34]
[35,36,37,38,39,40,41]
[42,43,44,45,46,47,48]
游戏是服务器驱动的,因此玩家使用相对坐标。这意味着,如果玩家移动,瓷砖[0]会改变。这是玩家的简短版本将始终从瓷砖24(即中心瓷砖(移动。网格很难编码,但是如果我公开发布它,我将稍微更改代码。没问题。
该功能应采用目的地并找到从图24到该正方形的好路径,但实际上它返回了"未定义"。
如果我输入24我希望游戏输出这样的数组
[18,12,6]
这是代码:
z = 0;
function pathTo(goal){
var createPath = function (goal){
var createNode = function(i){
this.id = i;
this.g = Infinity;
this.f = Infinity;
this.parent = null;
this.open = null;
};
this.nodes = Array(49);
for(i=0;i<this.nodes.length;i++){
this.nodes[i] = new createNode(i);
}
this.start = this.nodes[24];
this.start.g = 0;
this.currentNodeId = 24;
this.goal = this.nodes[goal];
this.bestPath = null;
};//end createPath
var getBestNeighbor = function(nodeId){
z++
if(z>50){throw z}debugger;
console.log(nodeId);
var getG = function(parentG){
//here you can check the map for water, sand, and ruins penalties
/*
default = 1
path = .9
water = 3
*/
return (parentG + 1);
};
var closeNode = function (node){
node.open = false;
};//end closeNode
var getF = function(startId,endId,g){
if(g>9){
throw g;
}
var startX = startId % 7;
var startY = (startId - startX) / 7;
var endX = endId % 7;
var endY = (endId - endX) / 7;
var h = Math.sqrt( Math.pow((startX - endX) , 2 ) + Math.pow(( startY - endY ), 2 ) );
console.log("Start.id:"+startId+"H:"+h+" Start.id.g:"+g);
return (h + g);
};//end getF
var tracePath = function(tracedNode){
path.bestPath = [];
while(tracedNode != path.start){
path.bestPath.unshift(tracedNode.id);
tracedNode = tracedNode.parent;
}
return path.bestPath;
};//end tracePath
var getNeighborNodeId = function(x,y,currentId){return currentId + (y*7) + x;};//end getNeighborNodeId
if(path.bestPath === null){
var neighborNode = {};
var bestNode = {f: Infinity};
if(nodeId == path.goal.id){//may need to pass path
return tracePath(path.nodes[nodeId]);
}else{
for(x=-1;x<=1;x++){
for(y=-1;y<=1;y++){
var nnId = getNeighborNodeId(x,y,nodeId);
if(nnId==24){debugger}
if( ( (x!=0) && (y!=0) ) ||( (nnId>=0) && (nnId<=48))){
var neighborNode = path.nodes[nnId];
if(neighborNode.open === null){ neighborNode.open = true; }
if(neighborNode.open === true ){//don't check closed neighbors
if(typeof neighborNode === "object"){
neighborNode.parent = path.nodes[nodeId]
debugger;
neighborNode.g = getG(neighborNode.parent.g);
neighborNode.f = getF(neighborNode.id , path.goal.id , neighborNode.g);
if( neighborNode.f < bestNode.f){
bestNode = neighborNode;
}//endif
}//endif
}//endif Note: if the node isn't null or true, it's false.
}
}//endfor
}//endfor - Note: Here we should have the best neighbor
if(bestNode.f == Infinity){
closeNode(path.nodes[nodeId]);//need escape for no possible path
return;
}else{
//bestNode.parent = path.nodes[nodeId];
path.currentNodeId = bestNode.id;
getBestNeighbor(bestNode.id);
}//endelse
}//endelse
}//endif
};//end getBestNeighbor
var path = new createPath(goal);
while(path.bestPath === null){
getBestNeighbor(path.currentNodeId);
}//end while
return path.bestPath;
}//end pathTo
console.log(pathTo(41)); //testing with 6
和jsfiddle链接:https://jsfiddle.net/jb4xtf3h/
这是我第一次到处都拍打全球,所以它可能有一个我不熟悉的范围问题。
我的问题很可能是在GetNeighborid功能中;我认为我没有任何声明一个好节点的父母。
问题在于它在三次而不是NE上进行三次。这可能意味着我在getBestneighbor函数中有一个错误
我也认为我无法正确逃脱递归功能。
出于某种原因,当我投入41时,它真的很困惑。这要么与我设置的G和H相关,后者在A*中经常使用以记录在此路径上行进的距离和剩余的估计距离。特别是g数是错误的,因为由于某种原因,它正在采取不好的步骤。
这是工作代码。我没有实施墙壁或其他任何东西,但我确实显示了您在哪里做。您需要做的就是关闭所有在开始路径之前墙壁的节点,如果您希望AI知道"知道",则可以分配运动处罚。避免水或沙子。
我实际上不能固定一个问题,但是一个主要问题是说明的方式:
if( ( (x!=0) && (y!=0) ) ||( (nnId>=0) && (nnId<=48))){
已更改为:
if( ( !(x==0 && y==0) && ( nnId>=0 && nnId<=48))){
这一行的目的是防止搜索您站在x,y =(0,0(上的瓷砖,并确保要查看的邻居在网格上(7x7 Grid具有49个正方形编号0-48(
我想说的是"如果x&amp;y都不为零。显然,这实际上与一个或语句相同,因此,如果两个正方形是0,则它跳过了它,并且需要空间有问题,因为有多个指示无法正常工作。
我希望如果某人需要一个不错的简单路径脚本,我真的很努力地使代码可读,而我不是世界上最强大的编码器,而是一个在100行中使用的脚本*,我认为这是公平的。容易遵循。如果您正在阅读本文,并且您不熟悉*路径,那么您可能需要知道的是
h是您的启发式价值,这是对剩余距离形成瓷砖的估计。在此代码中,它在路径对象path.nodes[array#].h
g是您到目前为止移动到该方形path.nodes[array#].g
的距离。
f只是为总值添加了H G。Wikipedia上的伪代码帮助我写了它。
var z = 0;
function pathTo(goal){
var createPath = function (goal){
var createNode = function(i){
this.id = i;
this.g = Infinity;
this.f = Infinity;
this.parent = null;
this.open = null;
};
this.nodes = Array(49);
for(i=0;i<this.nodes.length;i++){
this.nodes[i] = new createNode(i);
}
this.start = this.nodes[24];
this.start.g = 0;
this.currentNodeId = 24;
this.goal = this.nodes[goal];
this.bestPath = null;
};//end createPath
var path = new createPath(goal);
var getBestNeighbor = function(nodeId){
var getG = function(parentG){
//here you can check the map for water, sand, and ruins penalties
/*
default = 1
path = .9
water = 3
*/
return (parentG + 1);
};
var closeNode = function (node){
node.open = false;
};//end closeNode
var getF = function(startId,endId,g){
var startX = startId % 7;
var startY = (startId - startX) / 7;
var endX = endId % 7;
var endY = (endId - endX) / 7;
var h = Math.sqrt( Math.pow((startX - endX) , 2 ) + Math.pow(( startY - endY ), 2 ) );
return (h + g);
};//end getF
var tracePath = function(tracedNode){
path.bestPath = [];
while(tracedNode != path.start){
path.bestPath.unshift(tracedNode.id);
tracedNode = tracedNode.parent;
}
return path.bestPath;
};//end tracePath
var getNeighborNodeId = function(x,y,currentId){return currentId + (y*7) + x;};//end getNeighborNodeId
debugger;
z++
if(z>50){throw z}
if(path.bestPath === null){
var neighborNode = {};
var bestNode = {f: Infinity};
if(nodeId == path.goal.id){//may need to pass path
return tracePath(path.nodes[nodeId]);
}else{
for(y=-1;y<=1;y++){
for(x=-1;x<=1;x++){
var nnId = getNeighborNodeId(x,y,nodeId);
if( ( !(x==0 && y==0) && ( nnId>=0 && nnId<=48))){
var neighborNode = path.nodes[nnId];
if(path.nodes[nodeId].parent!=neighborNode){
if(neighborNode.open === null){ neighborNode.open = true; }
if(neighborNode.open === true ){//don't check closed neighbors
if(typeof neighborNode === "object"){
neighborNode.parent = path.nodes[nodeId]
neighborNode.g = getG(neighborNode.parent.g);
neighborNode.f = getF(neighborNode.id , path.goal.id , neighborNode.g);
if( neighborNode.f < bestNode.f){
bestNode = neighborNode;
}//endif
}//endif
}
}//endif Note: if the node isn't null or true, it's false.
}
}//endfor
}//endfor - Note: Here we should have the best neighbor
if(bestNode.f >= 50){
closeNode(path.nodes[nodeId]);//need escape for no possible path
return;
}else{
path.currentNodeId = bestNode.id;
getBestNeighbor(bestNode.id);
}//endelse
}//endelse
}//endif
};//end getBestNeighbor
while(path.bestPath === null){
getBestNeighbor(path.currentNodeId);
}//end while
return path.bestPath;
}//end pathTo
myPath = pathTo(41); //testing with 6
console.log("path2:"+myPath);