js+ajax實(shí)現(xiàn)的A*游戲路徑算法整理第2/2頁(yè)
更新時(shí)間:2007年05月28日 00:00:00 作者:
在51js上找到了hjjboy朋友的js實(shí)現(xiàn)方法,我給增加了注釋?zhuān)员闳蘸笳矸庋b。
復(fù)制代碼 代碼如下:
<html><head><title>use A* to find path...</title></head>
<body style="margin:0px">
<script>
/*
written by hjjboy
email:tianmashuangyi@163.com
qq:156809986
*/
var closelist=new Array(),openlist=new Array();//closelist保存最終結(jié)果。openlist保存臨時(shí)生成的點(diǎn);
var gw=10,gh=10,gwh=14;//參數(shù) gh是水平附加參數(shù) gwh是四角的附加參數(shù)。
var p_start=new Array(2),p_end=new Array(2);//p_start為起點(diǎn),p_end為終點(diǎn)
var s_path,n_path="";//s_path為當(dāng)前點(diǎn) n_path為障礙物數(shù)組樣式的字符串.
var num,bg,flag=0;
var w=30,h=20;
function GetRound(pos){//返回原點(diǎn)周?chē)?個(gè)點(diǎn)
var a=new Array();
a[0]=(pos[0]+1)+","+(pos[1]-1);
a[1]=(pos[0]+1)+","+pos[1];
a[2]=(pos[0]+1)+","+(pos[1]+1);
a[3]=pos[0]+","+(pos[1]+1);
a[4]=(pos[0]-1)+","+(pos[1]+1);
a[5]=(pos[0]-1)+","+pos[1];
a[6]=(pos[0]-1)+","+(pos[1]-1);
a[7]=pos[0]+","+(pos[1]-1);
return a;
}
function GetF(arr){ //參數(shù)為原點(diǎn)周?chē)?個(gè)點(diǎn)
var t,G,H,F;//F,綜合的距離值,H,距離值 G,水平\角落附加計(jì)算
for(var i=0;i<arr.length;i++){
t=arr[i].split(",");
t[0]=parseInt(t[0]);
t[1]=parseInt(t[1]);
if(IsOutScreen([t[0],t[1]])||IsPass(arr[i])||InClose([t[0],t[1]])||IsStart([t[0],t[1]])||!IsInTurn([t[0],t[1]]))
continue;//如果上面條件有一滿(mǎn)足,則跳過(guò)本次循環(huán),進(jìn)行下一次。
if((t[0]-s_path[3][0])*(t[1]-s_path[3][1])!=0)//判斷該點(diǎn)是否處于起點(diǎn)的垂直或橫向位置上
G=s_path[1]+gwh;//如果不在G=14;
else
G=s_path[1]+gw;//如果在G=10;
if(InOpen([t[0],t[1]])){//如果當(dāng)前點(diǎn)已存在openlist數(shù)組中
if(G<openlist[num][1]){
maptt.rows[openlist[num][4][1]].cells[openlist[num][4][0]].style.backgroundColor="blue";//調(diào)試
openlist[num][0]=(G+openlist[num][2]);
openlist[num][1]=G;
openlist[num][4]=s_path[3];
}
else{G=openlist[num][1];}
}
else{
H=(Math.abs(p_end[0]-t[0])+Math.abs(p_end[1]-t[1]))*gw;
F=G+H;
arr[i]=new Array();
arr[i][0]=F;
arr[i][1]=G;
arr[i][2]=H;
arr[i][3]=[t[0],t[1]];
arr[i][4]=s_path[3];
openlist[openlist.length]=arr[i];//將F等信息保存到openlist
}
if(maptt.rows[t[1]].cells[t[0]].style.backgroundColor!="#cccccc"&&maptt.rows[t[1]].cells[t[0]].style.backgroundColor!="#0000ff"&&maptt.rows[t[1]].cells[t[0]].style.backgroundColor!="#ff0000"&&maptt.rows[t[1]].cells[t[0]].style.backgroundColor!="#00ff00")
{
maptt.rows[t[1]].cells[t[0]].style.backgroundColor="#FF00FF";
if(F!=undefined)
maptt.rows[t[1]].cells[t[0]].innerHTML="<font color='black'>"+F+"</font>";
}
}
}
function IsStart(arr){ //判斷該點(diǎn)是不是起點(diǎn)
if(arr[0]==p_start[0]&&arr[1]==p_start[1])
return true;
return false;
}
function IsInTurn(arr){ //判斷是否是拐角
if(arr[0]>s_path[3][0]){
if(arr[1]>s_path[3][1]){
if(IsPass((arr[0]-1)+","+arr[1])||IsPass(arr[0]+","+(arr[1]-1)))
return false;
}
else if(arr[1]<s_path[3][1]){
if(IsPass((arr[0]-1)+","+arr[1])||IsPass(arr[0]+","+(arr[1]+1)))
return false;
}
}
else if(arr[0]<s_path[3][0]){
if(arr[1]>s_path[3][1]){
if(IsPass((arr[0]+1)+","+arr[1])||IsPass(arr[0]+","+(arr[1]-1)))
return false;
}
else if(arr[1]<s_path[3][1]){
if(IsPass((arr[0]+1)+","+arr[1])||IsPass(arr[0]+","+(arr[1]+1)))
return false;
}
}
return true;
}
function IsOutScreen(arr){ //是否超出場(chǎng)景范圍
if(arr[0]<0||arr[1]<0||arr[0]>(w-1)||arr[1]>(h-1))
return true;
return false;
}
function InOpen(arr){//獲得傳入在openlist數(shù)組的位置,如不存在返回false,存在為true,位置索引保存全局變量num中。
var bool=false;
for(var i=0;i<openlist.length;i++){
if(arr[0]==openlist[i][3][0]&&arr[1]==openlist[i][3][1]){
bool=true;num=i;break;}
}
return bool;
}
function InClose(arr){
var bool=false;
for(var i=0;i<closelist.length;i++){
if((arr[0]==closelist[i][3][0])&&(arr[1]==closelist[i][3][1])){
bool=true;break;}
}
return bool;
}
function IsPass(pos){ //pos這個(gè)點(diǎn)是否和障礙點(diǎn)重合
if((";"+n_path+";").indexOf(";"+pos+";")!=-1)
return true;
return false;
}
function Sort(arr){//整理數(shù)組,找出最小的F,放在最后的位置。
var temp;
for(var i=0;i<arr.length;i++){
if(arr.length==1)break;
if(arr[i][0]<=arr[i+1][0]){
temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
}
if((i+1)==(arr.length-1))
break;
}
}
function main(){//主函數(shù)
alert('');
GetF(//把原點(diǎn)周?chē)?點(diǎn)傳入GetF進(jìn)行處理。算A*核心函數(shù)了 :),進(jìn)行求F,更新openlist數(shù)組
GetRound(s_path[3]) //求原點(diǎn)周?chē)?點(diǎn)
);
debugdiv.innerHTML+="A:"+openlist.join('|')+"<br />";//調(diào)試
Sort(openlist);//整理數(shù)組,找出最小的F,放在最后的位置。
debugdiv.innerHTML+="B:"+openlist.join('|')+"<br />";//調(diào)試
s_path=openlist[openlist.length-1];//設(shè)置當(dāng)前原點(diǎn)為F最小的點(diǎn)
closelist[closelist.length]=s_path;//講當(dāng)前原點(diǎn)增加進(jìn)closelist數(shù)組中
openlist[openlist.length-1]=null;//從openlist中清除F最小的點(diǎn)
debugdiv.innerHTML+="C:"+openlist.join('|')+"<br />";//調(diào)試
if(openlist.length==0){alert("Can't Find the way");return;}//如果openlist數(shù)組中沒(méi)有數(shù)據(jù)了,則找不到路徑
openlist.length=openlist.length-1;//上次刪除把數(shù)據(jù)刪了,位置還保留了,這里刪除
if((s_path[3][0]==p_end[0])&&(s_path[3][1]==p_end[1])){//如果到到終點(diǎn)了,描繪路徑
getPath();
}
else{//否則循環(huán)執(zhí)行,標(biāo)準(zhǔn)原點(diǎn)
maptt.rows[s_path[3][1]].cells[s_path[3][0]].style.backgroundColor="green";setTimeout("main()",100);
}
}
function getPath(){//描繪路徑
var str="";
var t=closelist[closelist.length-1][4];
while(1){
str+=t.join(",")+";";
maptt.rows[t[1]].cells[t[0]].style.backgroundColor="#ffff00";
for(var i=0;i<closelist.length;i++){
if(closelist[i][3][0]==t[0]&&closelist[i][3][1]==t[1])
t=closelist[i][4];
}
if(t[0]==p_start[0]&&t[1]==p_start[1])
break;
}
alert(str);
}
function setPos(){//初始原點(diǎn)為起點(diǎn)
var h=(Math.abs(p_end[0]-p_start[0])+Math.abs(p_end[1]-p_start[1]))*gw;
s_path=[h,0,h,p_start,p_start];
}
function set(id,arr){//設(shè)置點(diǎn)的類(lèi)型
switch(id){
case 1:
p_start=arr;
maptt.rows[arr[1]].cells[arr[0]].style.backgroundColor="#ff0000";break;
case 2:
p_end=arr;maptt.rows[arr[1]].cells[arr[0]].style.backgroundColor="#0000ff";break;
case 3:
n_path+=arr.join(",")+";";maptt.rows[arr[1]].cells[arr[0]].style.backgroundColor="#cccccc";break;
default:
break;
}
}
function setflag(id){flag=id;}
</script>
<table id="maptt" cellspacing="1" cellpadding="0" border="0" bgcolor="#000000">
<script>
for(var i=0;i<h;i++){
document.write("<tr>");
for(var j=0;j<w;j++){
document.write('<td onclick="set(flag,['+j+','+i+']);" bgcolor="#ffffff" width="20" height="20"></td>');
}
document.write("</tr>");
}
</script>
</table>
<a href="javascript:setflag(1);">StarPoint</a><br>
<a href='javascript:setflag(2);'>EndPoint</a><br>
<a href='javascript:setflag(3);'>Wall</a><br>
<input type="button" onclick="setPos();main();this.disabled=true;" value="find">
<div id="debugdiv"></div>
</body>
</html>
在發(fā)一個(gè).net版本的實(shí)現(xiàn) 進(jìn)入
相關(guān)文章
如何在js中動(dòng)態(tài)修改元素的class屬性
在JavaScript中動(dòng)態(tài)修改CSS樣式是一種常見(jiàn)的操作,它允許開(kāi)發(fā)者根據(jù)不同的條件或者用戶(hù)的交互來(lái)改變網(wǎng)頁(yè)的外觀,這篇文章主要介紹了如何在js中動(dòng)態(tài)修改元素的class屬性的相關(guān)資料,需要的朋友可以參考下2025-04-04使用原生js實(shí)現(xiàn)頁(yè)面蒙灰(mask)效果示例代碼
像js的框架Extjs的mask()和unmask()功能提供了蒙灰效果,當(dāng)然jquery也提供了這種蒙灰方法,下面有個(gè)示例,大家可以參考下2014-06-06js利用canvas制作一個(gè)實(shí)時(shí)時(shí)鐘
Canvas是HTML5中強(qiáng)大的繪圖工具,它讓我們能夠在網(wǎng)頁(yè)上創(chuàng)建各種精美的圖形和動(dòng)畫(huà)效果,本文將向您展示如何使用Canvas制作一個(gè)實(shí)時(shí)時(shí)鐘,感興趣的可以了解下2023-08-08JavaScript動(dòng)態(tài)設(shè)置div的樣式的方法
這篇文章主要介紹了JavaScript動(dòng)態(tài)設(shè)置div的樣式的方法的相關(guān)資料,需要的朋友可以參考下2015-12-12基于JS快速實(shí)現(xiàn)導(dǎo)航下拉菜單動(dòng)畫(huà)效果附源碼下載
這是一個(gè)帶變形動(dòng)畫(huà)特效的下拉導(dǎo)航菜單特效。該導(dǎo)航菜單在菜單項(xiàng)之間切換時(shí),下拉菜單會(huì)快速的根據(jù)菜單內(nèi)容的大小來(lái)動(dòng)態(tài)變形,顯示合適的下拉菜單大小,效果非常棒,對(duì)導(dǎo)航下拉菜單效果感興趣的朋友一起通過(guò)本文學(xué)習(xí)吧2016-10-10用javascript實(shí)現(xiàn)li 列表數(shù)據(jù)隔行變換背景顏色
客戶(hù)端效果,效率自然不錯(cuò)。以前的做法是偶數(shù)行時(shí)給li加一個(gè)class,方法當(dāng)然不可取,如果后臺(tái)讀取再加class就很麻煩了,看看這個(gè)效果2007-08-08使用layui的router來(lái)進(jìn)行傳參的實(shí)現(xiàn)方法
今天小編就為大家分享一篇使用layui的router來(lái)進(jìn)行傳參的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09