A星算法JavaScript版本

A星算法

介紹

javascript實現A星尋路算法javascript

  1. 在遊戲中常有須要主角/敵人去移動到某個物品或者追尋敵人的時候,這個時候,可使用尋路算法
  2. 爲了實現canvas遊戲,須要尋路算法,因而便本身用JS實現了一下

原理思路

簡化搜索區域:java

  1. 爲了減小資源消耗,首先須要咱們將地圖分割爲區塊,以下圖

    圖片描述

    2.創建起點和終點座標,用於尋路git

維護open和close列表算法

  1. 咱們新建兩個列表,一個open表,它記錄了全部被考慮的尋路點;一個close表,它記錄了全部再也不被考慮的點
  2. 咱們要作的是接下來對兩個表的維護

搜索路徑canvas

  1. 如何尋路呢,首先咱們引入3個量數組

    1. G值,也就是當前點到起始點所需的代價
    2. H值,不考慮全部障礙等要素,該點到終點非斜線方式的估算量,也就是x+y的值
    3. F值,也就是該點的G+H的值
    4. 如圖所示,左上角爲F,右上角爲H,左下爲G:
      圖片描述
  2. 接下來是尋路具體實現函數

    1. 首先最小F值的點加入open,點暫記爲curr點
    2. 將curr點移除open,加入close
    3. 對於curr相鄰點,都有如下步驟spa

      1. 在close或者是障礙,無論它
      2. 不在open中,則計算它的各項值,加入open
      3. 在open中,則計算咱們當前這條路徑到達這個點是否有更小F值,是則更新它的F值
    4. 檢測到當前路徑點和終點一致時候則結束尋路;若是open中爲空,則表明沒有合適的尋路方案,尋路失敗
  3. JS實現的具體方案code

    1. 首先創建一個Sopt的類,它裏面包含如下信息blog

      1. 屬性:x,y,f,g,h,isWall,neighbors,parents,
      2. 方法addNeighbors,用於添加周圍8個格子能夠添加的點
    2. 初始化地圖全部點,運行addNeighbors方法,將neighbors數組初始化
    3. 創建尋路流程

      1. 初始化地點、終點,將起點加入openlist
      2. 創建一個遞歸函數用於尋找路徑
    4. 尋路遞歸函數

      1. 首先判斷openlist是否長度爲0,是則尋路失敗
      2. 創建一個curr表明當前點初始爲null,和currIndex序列號初始爲0

        let currIndex = 0;
                let curr = null;
                
                for(let i = 0; i < openList.length; i++) {
                    if(openList[i].f < openList[currIndex].f) {
                        currIndex = i;
                    }
                }
        
                curr = openList[currIndex];
        
                if(curr === endSopt) {
                    drawPath(curr);
                    return true;
                }
        
                removeFromArray(openList, curr);
                closedList.push(curr);

        3.遍歷curr的neighbors,將合適點的parent設爲curr

        for(let i = 0; i < curr.neighbors.length; i++) {
                    
                    let neighbor = curr.neighbors[i];
                    if(!closedList.includes(neighbor) && !neighbor.wall) {
        
                        let tmpF =  curr.g + getG(curr, neighbor) + getH(neighbor);
        
                        let newPath = false; // 是不是更好的路線
        
                        if(openList.includes(neighbor)) {
                            if(tmpF <= neighbor.f) {
                                neighbor.f = tmpF;
                                newPath = true;
                            }
                        } else {
                            neighbor.g = curr.g + getG(curr, neighbor);
                            neighbor.h = getH(neighbor);
                            neighbor.f = neighbor.g + neighbor.h;
                            newPath = true;
                            openList.push(neighbor);
                        }
        
                        if(newPath) {
                            neighbor.parent = curr;
                        }
                    }
                }
        
        4.遞歸這個函數,當點和終點一致時,返回這個點,而後遞歸它的parent屬性,則能找到路線

最後附上案例地址:a星算法

相關文章
相關標籤/搜索