中文字幕二区_国产精品免费在线观看_黄色网站观看_人人草人人澡_日本真实娇小xxxx

您的位置: 首頁(yè) > 技術(shù)文檔 > 多媒體制作 > A*尋路,二叉堆優(yōu)化及AS3實(shí)現(xiàn)
淺談flash web的結(jié)構(gòu) 回到列表 Apollo是危險(xiǎn)的嗎?
 A*尋路,二叉堆優(yōu)化及AS3實(shí)現(xiàn)

作者:eidiot 時(shí)間: 2007-04-23 文檔類型:原創(chuàng) 來(lái)自:藍(lán)色理想

第 1 頁(yè) A*尋路,二叉堆優(yōu)化及AS3實(shí)現(xiàn)
第 2 頁(yè) 牛刀小試 - A*尋路算法簡(jiǎn)介
第 3 頁(yè) 如虎添翼 - 使用二叉堆優(yōu)化
第 4 頁(yè) 鋒芒畢露 - AS3代碼和示例

地形數(shù)據(jù)不屬于A*尋路的范圍,這里定義一個(gè) IMapTileModel 接口,由其它(模型)類來(lái)實(shí)現(xiàn)地圖通路的判斷。其它比如尋路超時(shí)的判斷這里也不介紹,具體參考 AStar類及其測(cè)試代碼。這里只介紹三部分主要內(nèi)容:

* 數(shù)據(jù)存儲(chǔ)
    * 尋路過(guò)程
    * 列表排序

數(shù)據(jù)存儲(chǔ)
首先看看三個(gè)關(guān)鍵變量:

private var m_openList : Array; //開(kāi)放列表,存放節(jié)點(diǎn)ID
private var m_openCount : int; //當(dāng)前開(kāi)放列表中節(jié)點(diǎn)數(shù)量
private var m_openId : int; //節(jié)點(diǎn)加入開(kāi)放列表時(shí)分配的唯一ID(從0開(kāi)始)

開(kāi)放列表 m_openList 是個(gè)二叉堆(一維數(shù)組),F(xiàn)值最小的節(jié)點(diǎn)始終排在最前。為加快排序,開(kāi)放列表中只存放節(jié)點(diǎn)ID ,其它數(shù)據(jù)放在各自的一維數(shù)組中:

private var m_xList : Array; //節(jié)點(diǎn)x坐標(biāo)
private var m_yList : Array; //節(jié)點(diǎn)y坐標(biāo)
private var m_pathScoreList : Array; //節(jié)點(diǎn)路徑評(píng)分F值
private var m_movementCostList : Array; //(從起點(diǎn)移動(dòng)到)節(jié)點(diǎn)的移動(dòng)耗費(fèi)G值
private var m_fatherList : Array; //節(jié)點(diǎn)的父節(jié)點(diǎn)(ID)

這些數(shù)據(jù)列表都以節(jié)點(diǎn)ID為索引順序存儲(chǔ)。看看代碼如何工作:

//每次取出開(kāi)放列表最前面的ID
currId = this.m_openList[0];
//讀取當(dāng)前節(jié)點(diǎn)坐標(biāo)
currNoteX = this.m_xList[currId];
currNoteY = this.m_yList[currId];

還有一個(gè)很關(guān)鍵的變量:private var m_noteMap : Array;
//節(jié)點(diǎn)(數(shù)組)地圖,根據(jù)節(jié)點(diǎn)坐標(biāo)記錄節(jié)點(diǎn)開(kāi)啟關(guān)閉狀態(tài)和ID

使用 m_noteMap 可以方便的存取任何位置節(jié)點(diǎn)的開(kāi)啟關(guān)閉狀態(tài),并可取其ID進(jìn)而存取其它數(shù)據(jù)。m_noteMap 是個(gè)三維數(shù)組,第一維y坐標(biāo)(第幾行),第二維x坐標(biāo)(第幾列),第三維節(jié)點(diǎn)狀態(tài)和ID。判斷點(diǎn)(p_x, p_y)是否在開(kāi)啟列表中:

return this.m_noteMap[p_y][p_x][NOTE_OPEN];

尋路過(guò)程
AStar類 尋路的方法是 find() :

/**
* 開(kāi)始尋路
* @param p_startX        起點(diǎn)X坐標(biāo)
* @param p_startY        起點(diǎn)Y坐標(biāo)
* @param p_endX        終點(diǎn)X坐標(biāo)
* @param p_endY        終點(diǎn)Y坐標(biāo)
* @return                 找到的路徑(二維數(shù)組 : [p_startX, p_startY], ... , [p_endX, p_endY])
*/      
public function find(p_startX : int, p_startY : int, p_endX : int, p_endY : int) : Array{/* 尋路 */}

注意這里返回?cái)?shù)據(jù)的形式:從起點(diǎn)到終點(diǎn)的節(jié)點(diǎn)數(shù)組,其中每個(gè)節(jié)點(diǎn)為一維數(shù)組[x, y]的形式。為了加快速度,類里沒(méi)有使用Object或是Point,節(jié)點(diǎn)坐標(biāo)全部以數(shù)組形式存儲(chǔ)。如節(jié)點(diǎn)note的x坐標(biāo)為note[0],y坐標(biāo)為note[1]。

下面開(kāi)始尋路,第一步將起點(diǎn)添加到開(kāi)啟列表:

this.openNote(p_startX, p_startY, 0, 0, 0);

openNote() 方法將節(jié)點(diǎn)加入開(kāi)放列表的同時(shí)分配一個(gè)唯一的ID、按此ID存儲(chǔ)數(shù)據(jù)、對(duì)開(kāi)啟列表排序。接下來(lái)是尋路過(guò)程:

while (this.m_openCount > 0)
{
    //每次取出開(kāi)放列表最前面的ID
    currId = this.m_openList[0];
    //將編碼為此ID的元素列入關(guān)閉列表
    this.closeNote(currId);
    //如果終點(diǎn)被放入關(guān)閉列表尋路結(jié)束,返回路徑
    if (currNoteX == p_endX && currNoteY == p_endY)
        return this.getPath(p_startX, p_startY, currId);
    //...每輪尋路過(guò)程
}
//開(kāi)放列表已空,找不到路徑
return null;

每輪的尋路:

//獲取周圍節(jié)點(diǎn),排除不可通過(guò)和已在關(guān)閉列表中的
aroundNotes = this.getArounds(currNoteX, currNoteY);
//對(duì)于周圍每個(gè)節(jié)點(diǎn)
for each (var note : Array in aroundNotes)
{
    //計(jì)算F和G值
    cost = this.m_movementCostList[currId] + (note[0] == currNoteX || note[1] == currNoteY) ? COST_STRAIGHT : COST_DIAGONAL;
    score = cost + (Math.abs(p_endX - note[0]) + Math.abs(p_endY - note[1])) * COST_STRAIGHT;
    if (this.isOpen(note[0], note[1])) //如果節(jié)點(diǎn)已在開(kāi)啟列表中
    {
        //測(cè)試節(jié)點(diǎn)的ID
    checkingId = this.m_noteMap[note[1]][note[0]][NOTE_ID];
    //如果新的G值比節(jié)點(diǎn)原來(lái)的G值小,修改F,G值,換父節(jié)點(diǎn)
    if(cost < this.m_movementCostList[checkingId])
    {
        this.m_movementCostList[checkingId] = cost;
        this.m_pathScoreList[checkingId] = score;
        this.m_fatherList[checkingId] = currId;
        //對(duì)開(kāi)啟列表重新排序
        this.aheadNote(this.getIndex(checkingId));
    }
    } else //如果節(jié)點(diǎn)不在開(kāi)放列表中
    {
    //將節(jié)點(diǎn)放入開(kāi)放列表
    this.openNote(note[0], note[1], score, cost, currId);
    }
}

從終點(diǎn)開(kāi)始依次沿父節(jié)點(diǎn)回到到起點(diǎn),返回找到的路徑:

/**
* 獲取路徑
* @param p_startX    起始點(diǎn)X坐標(biāo)
* @param p_startY    起始點(diǎn)Y坐標(biāo)
* @param p_id        終點(diǎn)的ID
* @return             路徑坐標(biāo)數(shù)組
*/      
private function getPath(p_startX : int, p_startY : int, p_id: int) : Array
{
    var arr : Array = [];
    var noteX : int = this.m_xList[p_id];
    var noteY : int = this.m_yList[p_id];
    while (noteX != p_startX || noteY != p_startY)
    {
    arr.unshift([noteX, noteY]);
    p_id = this.m_fatherList[p_id];
    noteX = this.m_xList[p_id];
    noteY = this.m_yList[p_id];
    }
    arr.unshift([p_startX, p_startY]);
    this.destroyLists();
    return arr;
}

列表排序
這部分看代碼和注釋就可以了,不多說(shuō):

/** 將(新加入開(kāi)放別表或修改了路徑評(píng)分的)節(jié)點(diǎn)向前移動(dòng) */
private function aheadNote(p_index : int) : void
{
    var father : int;
    var change : int;
    //如果節(jié)點(diǎn)不在列表最前
    while(p_index > 1)
    {
    //父節(jié)點(diǎn)的位置
    father = Math.floor(p_index / 2);
    //如果該節(jié)點(diǎn)的F值小于父節(jié)點(diǎn)的F值則和父節(jié)點(diǎn)交換
    if (this.getScore(p_index) < this.getScore(father))
    {
        change = this.m_openList[p_index - 1];
        this.m_openList[p_index - 1] = this.m_openList[father - 1];
        this.m_openList[father - 1] = change;
        p_index = father;
    } else
    {
        break;
    }
    }
}
/** 將(取出開(kāi)啟列表中路徑評(píng)分最低的節(jié)點(diǎn)后從隊(duì)尾移到最前的)節(jié)點(diǎn)向后移動(dòng) */
private function backNote() : void
{
    //尾部的節(jié)點(diǎn)被移到最前面
    var checkIndex : int = 1;
    var tmp : int;
    var change : int;
    while(true)
    {
    tmp = checkIndex;
    //如果有子節(jié)點(diǎn)
    if (2 * tmp <= this.m_openCount)
    {
        //如果子節(jié)點(diǎn)的F值更小
        if(this.getScore(checkIndex) > this.getScore(2 * tmp))
        {
        //記節(jié)點(diǎn)的新位置為子節(jié)點(diǎn)位置
        checkIndex = 2 * tmp;
        }
        //如果有兩個(gè)子節(jié)點(diǎn)
        if (2 * tmp + 1 <= this.m_openCount)
        {
        //如果第二個(gè)子節(jié)點(diǎn)F值更小
        if(this.getScore(checkIndex) > this.getScore(2 * tmp + 1))
        {
            //更新節(jié)點(diǎn)新位置為第二個(gè)子節(jié)點(diǎn)位置
            checkIndex = 2 * tmp + 1;
        }
        }
    }
    //如果節(jié)點(diǎn)位置沒(méi)有更新結(jié)束排序
    if (tmp == checkIndex)
    {
        break;
    }
    //反之和新位置交換,繼續(xù)和新位置的子節(jié)點(diǎn)比較F值
    else
    {
        change = this.m_openList[tmp - 1];
        this.m_openList[tmp - 1] = this.m_openList[checkIndex - 1];
        this.m_openList[checkIndex - 1] = change;
    }
    }
}

其中 getScore() 方法:

/**
* 獲取某節(jié)點(diǎn)的路徑評(píng)分F值
* @param p_index    節(jié)點(diǎn)在開(kāi)啟列表中的索引(從1開(kāi)始)
*/      
private function getScore(p_index : int) : int
{
    //開(kāi)啟列表索引從1開(kāi)始,ID從0開(kāi)始,數(shù)組索引從0開(kāi)始
    return this.m_pathScoreList[this.m_openList[p_index - 1]];
}

經(jīng)典論壇討論:
http://bbs.blueidea.com/thread-2738527-1-1.html

本文鏈接:http://m.95time.cn/tech/multimedia/2007/4665.asp 

出處:藍(lán)色理想
責(zé)任編輯:elesa

上一頁(yè) 如虎添翼 - 使用二叉堆優(yōu)化 下一頁(yè)

◎進(jìn)入論壇Flash專欄版塊參加討論

相關(guān)文章 更多相關(guān)鏈接
淺談flash web的結(jié)構(gòu)
雅致Flash打包工具1.0
用Flash制作的站長(zhǎng)工具箱
Apollo是危險(xiǎn)的嗎?
Apollo 開(kāi)發(fā)技巧
作者文章
Conjee_Album 1.0 發(fā)布
AS3學(xué)習(xí)筆記
關(guān)鍵字搜索 常規(guī)搜索 推薦文檔
熱門搜索:CSS Fireworks 設(shè)計(jì)比賽 網(wǎng)頁(yè)制作 web標(biāo)準(zhǔn) 用戶體驗(yàn) UE photoshop Dreamweaver Studio8 Flash 手繪 CG
站點(diǎn)最新 站點(diǎn)最新列表
周大!熬•自然”設(shè)計(jì)大賽開(kāi)啟
國(guó)際體驗(yàn)設(shè)計(jì)大會(huì)7月將在京舉行
中國(guó)國(guó)防科技信息中心標(biāo)志征集
云計(jì)算如何讓安全問(wèn)題可控
云計(jì)算是多數(shù)企業(yè)唯一擁抱互聯(lián)網(wǎng)的機(jī)會(huì)
阿里行云
云手機(jī)年終巨獻(xiàn),送禮標(biāo)配299起
阿里巴巴CTO王堅(jiān)的"云和互聯(lián)網(wǎng)觀"
1499元買真八核 云OS雙蛋大促
首屆COCO桌面手機(jī)主題設(shè)計(jì)大賽
欄目最新 欄目最新列表
淺談JavaScript編程語(yǔ)言的編碼規(guī)范
如何在illustrator中繪制臺(tái)歷
Ps簡(jiǎn)單繪制一個(gè)可愛(ài)的鉛筆圖標(biāo)
數(shù)據(jù)同步算法研究
用ps作簡(jiǎn)單的作品展示頁(yè)面
CSS定位機(jī)制之一:普通流
25個(gè)最佳最閃亮的Eclipse開(kāi)發(fā)項(xiàng)目
Illustrator中制作針線縫制文字效果
Photoshop制作印刷凹凸字體
VS2010中創(chuàng)建自定義SQL Rule
>> 分頁(yè) 首頁(yè) 前頁(yè) 后頁(yè) 尾頁(yè) 頁(yè)次:4/4頁(yè) 1個(gè)記錄/頁(yè) 轉(zhuǎn)到 頁(yè) 共4個(gè)記錄

藍(lán)色理想版權(quán)申明:除部分特別聲明不要轉(zhuǎn)載,或者授權(quán)我站獨(dú)家播發(fā)的文章外,大家可以自由轉(zhuǎn)載我站點(diǎn)的原創(chuàng)文章,但原作者和來(lái)自我站的鏈接必須保留(非我站原創(chuàng)的,按照原來(lái)自一節(jié),自行鏈接)。文章版權(quán)歸我站和作者共有。

轉(zhuǎn)載要求:轉(zhuǎn)載之圖片、文件,鏈接請(qǐng)不要盜鏈到本站,且不準(zhǔn)打上各自站點(diǎn)的水印,亦不能抹去我站點(diǎn)水印。

特別注意:本站所提供的攝影照片,插畫,設(shè)計(jì)作品,如需使用,請(qǐng)與原作者聯(lián)系,版權(quán)歸原作者所有,文章若有侵犯作者版權(quán),請(qǐng)與我們聯(lián)系,我們將立即刪除修改。

您的評(píng)論
用戶名:  口令:
說(shuō)明:輸入正確的用戶名和密碼才能參與評(píng)論。如果您不是本站會(huì)員,你可以注冊(cè) 為本站會(huì)員。
注意:文章中的鏈接、內(nèi)容等需要修改的錯(cuò)誤,請(qǐng)用報(bào)告錯(cuò)誤,以利文檔及時(shí)修改。
不評(píng)分 1 2 3 4 5
注意:請(qǐng)不要在評(píng)論中含與內(nèi)容無(wú)關(guān)的廣告鏈接,違者封ID
請(qǐng)您注意:
·不良評(píng)論請(qǐng)用報(bào)告管理員,以利管理員及時(shí)刪除。
·尊重網(wǎng)上道德,遵守中華人民共和國(guó)的各項(xiàng)有關(guān)法律法規(guī)
·承擔(dān)一切因您的行為而直接或間接導(dǎo)致的民事或刑事法律責(zé)任
·本站評(píng)論管理人員有權(quán)保留或刪除其管轄評(píng)論中的任意內(nèi)容
·您在本站發(fā)表的作品,本站有權(quán)在網(wǎng)站內(nèi)轉(zhuǎn)載或引用
·參與本評(píng)論即表明您已經(jīng)閱讀并接受上述條款
推薦文檔 | 打印文檔 | 評(píng)論文檔 | 報(bào)告錯(cuò)誤  
專業(yè)書(shū)推薦 更多內(nèi)容
網(wǎng)站可用性測(cè)試及優(yōu)化指南
《寫給大家看的色彩書(shū)1》
《跟我去香港》
眾妙之門—網(wǎng)站UI 設(shè)計(jì)之道
《Flex 4.0 RIA開(kāi)發(fā)寶典》
《贏在設(shè)計(jì)》
犀利開(kāi)發(fā)—jQuery內(nèi)核詳解與實(shí)踐
作品集 更多內(nèi)容

雜⑦雜⑧ Gold NORMANA V2