zoukankan      html  css  js  c++  java
  • 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 nil
    end
    
    function 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)
    end
    
    function 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 point
    end
    
    -- 得到下一个能够移动的点
    -- @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_points
    end
    
    -- 得到路径
    -- @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 _path
    end
    
    -- 两个点的代价比較器
    function compareF(point1, point2)
        return point1.f_value < point2.f_value
    end
    
    -- 是否是障碍物
    function isObstacle(point)
        local value = _map_data[point.y][point.x]
        if value == 1 then
            return true
        end
        return false
    end
    
    -- 两个点是否是同一个点
    function isEqual(point1, point2)
        return point1.key == point2.key
    end
    
    -- 依据点得到点的key
    function getKey(point)
        local key =  string.format("%d,%d", point.x, point.y)
        return key
    end

    以下是工具类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    各路大神 给你的老婆。女朋友,小三,小四,小五......还有你的众多基友买点吧




    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    Python下opencv库的安装过程与一些问题汇总
    Pandas数据结构(二)——Pandas DataFrame
    Pandas数据结构(一)——Pandas Series
    Python:日期和时间的处理模块及相关函数
    Python常用的正则表达式处理函数
    Python的标准库介绍与常用的第三方库
    Python实现单链表数据的添加、删除、插入操作
    Python:爬取网站图片并保存至本地
    100_1小记ressons analysis
    [转载]计算机领域经典书籍推荐(2013.08.07更新)
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4754389.html
Copyright © 2011-2022 走看看