A*寻路算法(JavaScript实现)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
div{
position: absolute;
width: 50px;
height: 50px;
margin: 1px 1px;
background-color: gray;
border: 1px dashed #cccccc;
}
body{
position: relative;
font-family: "微软雅黑"; }
header,
section
{
position: relative;
margin: 0 auto;
width: 998px;
} </style>
</head>
<body>
<header>
<h1>A*寻路demo演示</h1>
<table>
<tr>
<td>输入地图列数(最大15列):</td>
<td><input id="rowInput" type="text"/></td>
</tr>
<tr>
<td>请输入地图行数(最大15行):</td>
<td><input id="colInput" type="text"></td>
</tr>
<tr>
<td></td>
<td><input id="createMapBtn" type="button" value="点击生成地图"/></td>
</tr>
<tr>
<td id="prompt">test...</td>
<td><input id="findPoint" type="button" value="开始寻路" style="display: none"/></td>
</tr> </table> </header> <section id="main"></section> <script>
function Point(){
this.x=0;
this.y=0;
this.G=0;//G值 开始点 到当前点的移动量
this.H=0;//H值 当前点移动目的地的移动量估算值
this.father=null;
};
Point.prototype={
Console:function(){
console.log("x:"+this.x+" and y:"+this.y);
},
Init:function(x,y,father){
this.x=x;
this.y=y;
this.father=father;
}
};
function AStar(){
//地图存放二维数组
this.map=[];
//行数
this.rowCount=0;
//列数
this.colCount=0;
//出发点
this.startPoint=new Point();
//终点
this.endPoint=new Point();
//存放Opint类的open数组
this.openList=[];
//存在Opint类的close数组
this.closeList=[];
};
AStar.prototype={
//是否为障碍物
IsBar:function(x,y){
if(this.map[x][y]==3){
console.log("bar...");
return true;
}
else{
console.log("no bar...")
return false;
}
},
//当前坐标是否在OpenList
IsInOpenList:function(x,y){
for(var i=0;i<this.openList.length;i++){
if(this.openList[i].x==x&&this.openList[i].y==y){
return true;
} }
return false;
},
//当前坐标是否在CloseList
IsInCloseList:function(x,y){
for(var i=0;i<this.closeList.length;i++){
if(this.closeList[i].x==x&&this.closeList[i].y==y){
return true;
} }
return false;
},
//计算G值;(p是Point类)
GetG:function(p){
if(p.father==null){
return 0;
}
return p.father.G+1;
},
//计算H值
GetH:function(p,pb){
return Math.abs(p.x-pb.x)+Math.abs(p.y-pb.y);
},
//添加当前点的上下左右相邻的方格到Open列表中
AddNeiToOpenList:function(curPoint){
for(var x=curPoint.x-1;x<=curPoint.x+1;x++){
for(var y=curPoint.y-1;y<=curPoint.y+1;y++){
//排除自身以及超出下标的点
if((x>=0&&x<this.colCount&&y>=0&&y<this.rowCount)&&!(curPoint.x==x&&curPoint.y==y)){
//排除斜对角
if(Math.abs(x-curPoint.x)+Math.abs(y-curPoint.y)==1){
//不是障碍物且不在关闭列表中
if(this.IsBar(x,y)==false&&this.IsInCloseList(x,y)==false){
//不存在Open列表
if(this.IsInOpenList(x,y)==false){
var point=new Point();
point.x=x;
point.y=y;
point.father=curPoint;
point.G=this.GetG(point);
point.H=this.GetH(point,this.endPoint);
this.openList.push(point);
}
}
}
}
}
}
},
//在openlist集合中获取G+H为最小的Point点
GetMinFFromOpenList:function(){
var minPoint=null;
var index=0;
for(var i=0;i<this.openList.length;i++){
if(minPoint==null||minPoint.G+minPoint.H>=this.openList[i].G+this.openList[i].H){
minPoint=this.openList[i];
index=i;
}
}
return{
minPoint:minPoint,
index:index
}
}, GetPointFromOpenList:function(x,y){
for(var i=0;i<this.openList.length;i++){
if(this.openList[i].x==x&&this.openList[i].y==y){
return this.openList[i];
}
}
return null; },
//开始寻找节点
FindPoint:function(){
console.log(this);
this.openList.push(this.startPoint);
while(this.IsInOpenList(this.endPoint.x,this.endPoint.y)==false||this.openList.length==0){
var curPoint=this.GetMinFFromOpenList().minPoint;
console.log("curPoint:"+curPoint);
var index=this.GetMinFFromOpenList().index;
if(curPoint==null){
console.log("没有路");
return;
}
this.openList.splice(index,1);
this.closeList.push(curPoint);
this.AddNeiToOpenList(curPoint);
}
var p=this.GetPointFromOpenList(this.endPoint.x,this.endPoint.y);
console.log(p+".....");
while(p.father!=null){
p= p.father;
console.log("father..");
this.map[p.x][p.y]=4;
}
//把终结点也设置成4
this.map[this.endPoint.x][this.endPoint.y]=4;
},
PrintMap:function(){ } };
//地图类 map数组保存数字标识 :0 默认 1 开始点 2 结束点 3 障碍物
function Map(id){
this.map=[];
this.container=document.getElementById(id);
this.colCount=0;
this.rowCount=0;
}
Map.prototype={
init:function(colCount,rowCount){
this.colCount=colCount;
this.rowCount=rowCount;
for(var colIndex=0;colIndex<this.colCount;colIndex++){
this.map.push([]);
for(var rowIndex=0;rowIndex<this.rowCount;rowIndex++){
this.map[colIndex].push(0);
}
}
},
drawMap:function(callback){
for(var colIndex=0;colIndex<this.map.length;colIndex++){
for(var rowIndex=0;rowIndex<this.map[colIndex].length;rowIndex++){
var div=document.createElement("div");
div.style.top=colIndex*50+5+"px";
div.style.left=rowIndex*50+5+"px";
div.setAttribute("colIndex",colIndex);
div.setAttribute("rowIndex",rowIndex);
div.onclick=callback;
this.container.appendChild(div);
} } },
drawPoints:function(){
var divs=this.container.children;
console.log(divs.length);
console.log(this.map);
var timer=1000;
for(var i=0;i<divs.length;i++){
var colIndex=divs[i].getAttribute("colIndex");
var rowIndex=divs[i].getAttribute("rowIndex");
if(this.map[colIndex][rowIndex]==4){
divs[i].style.backgroundColor="red";
}
}
},
getPoint:function(colIndex,rowIndex){
return this.map[colIndex][rowIndex];
},
setStartPoint:function(colIndex,rowIndex){
this.map[colIndex][rowIndex]=1;
},
setEndPoint:function(colIndex,rowIndex){
this.map[colIndex][rowIndex]=2;
},
setBarPoint:function(colIndex,rowIndex){
this.map[colIndex][rowIndex]=3;
},
clearMap:function(){
this.map.splice(0,this.map.length);
this.container.innerHTML="";
} } var rowInput=document.querySelector("#rowInput");
var colInput=document.querySelector("#colInput");
var createMapBtn=document.querySelector("#createMapBtn");
var prompt=document.querySelector("#prompt");
var findPoint=document.querySelector("#findPoint");
var curMap=new Map("main");
var state=0;//状态标识 0选择开始节点标识 1选择结束节点标识 2选择障碍物标识
var aStar=new AStar();//寻路类 createMapBtn.onclick=function(){ curMap.clearMap();
curMap.init(colInput.value,rowInput.value);
aStar.map=curMap.map;
aStar.colCount=colInput.value;
aStar.rowCount=rowInput.value;
curMap.drawMap(function(){
var colIndex=this.getAttribute("colIndex");
var rowIndex=this.getAttribute("rowIndex");
if(curMap.getPoint(colIndex,rowIndex)!=0){
return;
}
if(state==0){
this.style.backgroundColor="blue";
curMap.setStartPoint(colIndex,rowIndex);
aStar.startPoint.x=colIndex;
aStar.startPoint.y=rowIndex;
state=1;
prompt.innerHTML="请点击格子,设置终点"; }else if(state==1){
this.style.backgroundColor="yellow";
curMap.setEndPoint(colIndex,rowIndex);
aStar.endPoint.x=colIndex;
aStar.endPoint.y=rowIndex;
prompt.innerHTML="请点击格子,设置障碍物";
console.log(findPoint);
findPoint.style.display="block";
state=2;
}else if(state==2){
curMap.setBarPoint(colIndex,rowIndex);
this.style.backgroundColor="black";
}
});
prompt.innerHTML="请点击格子,设置起始点";
}
findPoint.onclick=function(){
console.log(aStar.map);
aStar.FindPoint();
curMap.drawPoints();
} </script> </body>
</html>
A*寻路算法(JavaScript实现)的更多相关文章
- javascript的Astar版 寻路算法
去年做一个模仿保卫萝卜的塔防游戏的时候,自己写的,游戏框架用的是coco2d-html5 实现原理可以参考 http://www.cnblogs.com/technology/archive/2011 ...
- 读《数据结构与算法 Javascript描述》 | 平淡无奇
“平淡无奇”,一句话总结. 当初买这本书的原因,在意的是有没有什么令人惊喜的东西,特别是针对Javascript代码的奇思妙想,所以就买下了这本书. 在买的几本书里面,最先看的也是这一本,但看起目录就 ...
- 不再依赖A*,利用C++编写全新寻路算法
一,说在前面的话 大概在半年前,看见一到信息竞赛题:在任意方格阵中设置障碍物,确定起始点后,求这两点之间路径.当时觉得蛮有意思的,但是没有时间去做,今天花了两个小时来实现它.据说有一个更高级的寻路算法 ...
- PHP树生成迷宫及A*自己主动寻路算法
PHP树生成迷宫及A*自己主动寻路算法 迷宫算法是採用树的深度遍历原理.这样生成的迷宫相当的细,并且死胡同数量相对较少! 随意两点之间都存在唯一的一条通路. 至于A*寻路算法是最大众化的一全自己主动寻 ...
- A星寻路算法介绍
你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...
- A*寻路算法探究
A*寻路算法探究 A*算法常用在游戏的寻路,是一种静态网路中求解最短路径的搜索方法,也是解决很多搜索问题的算法.相对于Dijkstra,BFS这些算法在复杂的搜索更有效率.本文在U3D中进行代码的测试 ...
- A*寻路算法
对于初学者而言,A*寻路已经是个比较复杂的算法了,为了便于理解,本文降低了A*算法的难度,规定只能横竖(四方向)寻路,而无法直接走对角线,使得整个算法更好理解. 简而言之,A*寻路就是计算从起点经过该 ...
- 数据结构与算法JavaScript (一) 栈
序 数据结构与算法JavaScript这本书算是讲解得比较浅显的,优点就是用javascript语言把常用的数据结构给描述了下,书中很多例子来源于常见的一些面试题目,算是与时俱进,业余看了下就顺便记录 ...
- 算法:Astar寻路算法改进,双向A*寻路算法
早前写了一篇关于A*算法的文章:<算法:Astar寻路算法改进> 最近在写个js的UI框架,顺便实现了一个js版本的A*算法,与之前不同的是,该A*算法是个双向A*. 双向A*有什么好处呢 ...
随机推荐
- PostgreSQL笔记
本文针对目前最新版9.5.1,若非说明,文中所说文档即指官方文档.本人刚接触PostgreSQL不久,文中不免错漏,请大家指正:随着了解深入,本文[可能]会不定期更新补足. JSON PostgreS ...
- MacOS changed System Integrity Protection status
禁止 System Integrity Protection 按住 command + R 重启系统 进入单用户模式 启动bash工具: 输入: csrutil disable 输入:reboot 启 ...
- 14.S5PV210串行通信编程实战
1.整个程序流程分析(1)整个串口通信相关程序包含2部分:uart_init负责初始化串口,uart_putc负责发送一个字节2.串口控制器初始化关键步骤(1)初始化串口的Tx和Rx引脚所对应的GPI ...
- .NET (三)委托第三讲:内置委托Action
.NET 为我们提供了无返回值的内置委托 Action,代码如下: // 摘要: // 封装一个方法,该方法只有一个参数并且不返回值. // // 参数: // obj: // 此委托封装的方法的参数 ...
- RPC hessian简单案例
RPC(Remote procedure call) 远程服务调用. dubbox就是RPC框架,hessian是简单的RPC实现. 首先需要有接口及其实现类: 接口. public interfac ...
- HEX文件格式和其校验算法
这次我将在原来的基础上(http://www.cnblogs.com/libra13179/p/5787084.html)继续讲解HEX文件的格式 打开app_valid_setting_apply. ...
- 一个C#语法高亮插件
语法高亮对程序员阅读代码来说有着不小的帮助,虽然VisualStudio本身支持C#语法高亮,但也只是对关键字.类名.字符串等少数元素加了标记,而我们代码中主题:变量.函数.属性.事件等都没有进行高亮 ...
- 【转】jqGrid 各种参数 详解
[原文]http://www.cnblogs.com/younggun/archive/2012/08/27/2657922.htmljqGrid 各种参数 详解 JQGrid JQGrid是一个 ...
- [转]在WPF中区别TextBlock和Label
TextBlock和Label都是用来显示少量数据的.好多文章对Label存在的描述都是它允许使用"快速获取"."快速获取"就是允许你用Alt加上其它的按键快速 ...
- c#绘制表格
//绘制表格 //定义绘制表格的参数 Pen _Pen = new Pen(Brushes.Black); // VBConversions Note: Initial value cannot be ...