A星尋路的lua實現

來源:互聯網
上載者:User

A星尋路的lua實現

在項目中遇到了自動尋路的需求,於是決定開始學習一下A星,對於A星我也沒有深究,只能說是勉強搞定了需求,在這和大家分享一下,相互進步,

A星有個公式 f(x) = g(x) + h(x) ,搞清楚這個公式就好辦了,f(x)就是當前位置到下一個位置的總價值,g(x)表示實際價,這是說這一部分代價是確定的,h(x)表示估價值,就是說我從下一個位置到到終點的代價是未知的,所以叫估價值,中所示,黑色格子表示當前位置,綠色格子表示下一步可能到達的位置,即上、下、左、右這幾個方向,紅色格子表示終點,褐色表示障礙物,現在要從黑色格子到達紅色格子,那麼黑色格子的下一步肯定是綠色格子當中的一個,黑色格子到綠色格子之間是相挨著的,所以我們可以很明確的知道它的實際代價為1(移動一步的代價)即g(x),綠色格子到紅色格子之間隔著很長的距離,中間還有障礙物,所以這個代價是未知的,即h(x),所以總的代價就為f(x) = g(x) + h(x),我們看到周圍有4個綠色的格子,到底走那一步比較好呢,所以我們要把這4個格子的f(x)值都求出來,然後進行排序,選擇f(x)值最小的,即總代價最少的那個格子,以此方法繼續下去,直到到達終點 或者 地圖上沒有綠色格子了


下面來看一下這個工具類,g(x)和h(x)要選的比較合適,一般就是採用的曼哈頓演算法,即兩點在x方向和y方向的距離之和,

-- Filename: PathUtil.lua-- Author: bzx-- Date: 2014-07-01-- Purpose: 尋路module("PathUtil", package.seeall)local _map_data         -- 地圖資料local _open_list        -- 開放節點local _open_map         -- 開放節點,為了提高效能而加local _close_map        -- 關閉節點local _deleget          -- 代理local _dest_point       -- 目標點local _start_point      -- 起點local _path             -- 路徑-- 尋找路徑--[[deleget = {    g = function(point1, point2)        -- add your code        -- 返回點point1到點point2的實際代價    end    h = function(point1, point2)        -- add your code        -- 返回點point1到點point2的估算代價    end    getValue = function(j, i)        -- 返回地圖中第i行,第j列的資料 1為障礙物,0為非障礙物    end    width -- 地圖寬度    height -- 地圖高度}--]]function findPath(deleget, start_point, dest_point)    _deleget = deleget    _dest_point = dest_point    _start_point = start_point    init()    while not table.isEmpty(_open_list) do        local cur_point = _open_list[1]        table.remove(_open_list, 1)        _open_map[cur_point.key] = nil        if isEqual(cur_point, dest_point) then            return makePath(cur_point)        else            _close_map[cur_point.key] = cur_point            local next_points = getNextPoints(cur_point)            for i = 1, #next_points do                local next_point = next_points[i]                if _open_map[next_point.key] == nil and _close_map[next_point.key] == nil and isObstacle(next_point) == false then                    _open_map[next_point.key] = next_point                    table.insert(_open_list, next_point)                end            end            table.sort(_open_list, compareF)        end    end    return nilendfunction init()    _open_list = {}    _open_map = {}    _close_map = {}    _path = {}    _map_data = {}    for i = 1, _deleget.height do        _map_data[i] = {}        for j = 1, _deleget.width do            local value = _deleget.getValue(j, i)            _map_data[i][j] = value        end    end    _open_map[getKey(_start_point)] = _start_point    table.insert(_open_list, _start_point)endfunction createPoint(x, y)    local point = {        ["x"] = x,        ["y"] = y,        ["last"] = nil,        ["g_value"] = 0,        ["h_value"] = 0,        ["f_value"] = 0    }    point["key"] = getKey(point)    return pointend-- 得到下一個可以移動的點-- @param point 當前所在點function getNextPoints(point)    local next_points = {}    for i = 1, #_deleget.directions do        local offset = _deleget.directions[i]        local next_point = createPoint(point.x + offset[1], point.y + offset[2])        next_point["last"] = point        if next_point.x >= 1 and next_point.x <= _deleget.width and next_point.y >= 1 and next_point.y <= _deleget.height then            next_point["g_value"] = _deleget.g(point, next_point)            next_point["h_value"] = _deleget.h(point, _dest_point)--math.abs(next_points.x - _dest_point.x) + math.abs(next_points.y - _dest_point.y)            next_point["f_value"] = next_point.g_value + next_point.h_value            table.insert(next_points, next_point)        end    end    return next_pointsend-- 得到路徑-- @param end_point 目標點function makePath(end_point)    _path = {}    local point = end_point    while point.last ~= nil do        table.insert(_path, createPoint(point.x, point.y))        point = point.last    end    local start_point = point    table.insert(_path, start_point)    return _pathend-- 兩個點的代價比較子function compareF(point1, point2)    return point1.f_value < point2.f_valueend-- 是否是障礙物function isObstacle(point)    local value = _map_data[point.y][point.x]    if value == 1 then        return true    end    return falseend-- 兩個點是否是同一個點function isEqual(point1, point2)    return point1.key == point2.keyend-- 根據點得到點的keyfunction getKey(point)    local key =  string.format("%d,%d", point.x, point.y)    return keyend

下面是工具類PathUtil的用法

   local deleget = {}        deleget.g = function(point1, point2)            return math.abs(point1.x - point2.x) + math.abs(point1.y - point2.y)        end        deleget.h = deleget.g        deleget.getValue = function(j, i)            local index = FindTreasureUtil.getIndex(j, i)            local map_info = _map_info.map[index]            if map_info.display == 0 and map_info.eid ~= 1 then                return 0            end            return 1        end        deleget.directions = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}} -- 左,上,下,右        deleget.width = _cols        deleget.height = _rows                local dest_row, dest_col = FindTreasureUtil.getMapPosition(tag)        local dest_point = PathUtil.createPoint(dest_col, dest_row)        local start_row, start_col = FindTreasureUtil.getMapPosition(_player_index)        local start_point = PathUtil.createPoint(start_col, start_row)        _path = PathUtil.findPath(deleget, start_point, dest_point)

_path就是我們找到的路徑,起點為最後一個元素,終點為第一個元素,由於項目中的地圖比較簡單,因此我也沒有過於深究,關於A星的介紹網上的資料還有很多,我這一般就顯得太簡略了,初次接觸自動尋路,希望大神們多多指教

另附廣告一條:出售美容品的微店  如需詳細瞭解可加我姐姐QQ:937893128    各路大神 給你的老婆,女朋友,小三,小四,小五......還有你的眾多基友買點吧




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.