A*算法实现

1.A*基本流程图

2.扩展节点方法

3.A*最短路径条件

代码:

1.main.lua

require "Lib"

--create scene
local gameScene = cc.Scene:create()
gameScene:addChild(GameLayer:create())

2.Lib.lua

require "src/GameLayer"
require "src/Cube"
require "src/Constant"

3.Constant.lua

CubeSplit = 3
CellWidth = cc.Director:getInstance():getWinSize().width/10
CellHeight = cc.Director:getInstance():getWinSize().height/10
CubeWidth = CellWidth - CubeSplit --格子宽
CubeHeight = CellHeight - CubeSplit --格子高

4.Cube.lua

--地图方格
Cube = class("Cube", function ()
	return cc.Node:create()
end)

Cube.CUBE_TYPE_WALL = 1             --墙
Cube.CUBE_TYPE_START = 2            --起点格子
Cube.CUBE_TYPE_DESTANATION = 3      --目标地格子
Cube.CUBE_TYPE_AVIABLE = 4          --可以行走的格子

function Cube:create(row, col, type)
    local view = Cube:new()
    view:__init(row, col, type)
    return view
end

function Cube:__init(row, col, type)
    self.row = row
    self.col = col
    self.type = type

    self:addBgByType()
end

function Cube:addBgByType()
    local layerColor = nil
    local lblDesp = nil
    local fontSize = 15
    local color = {
        black = cc.c3b(0,0,0),
        red = cc.c3b(255,0,255),
        yellow = cc.c3b(255,255,0),
        white = cc.c3b(255,255,255),
        blue = cc.c3b(0,0,255),
        green = cc.c3b(0,255,127)
    }

    if self.type == Cube.CUBE_TYPE_WALL then
        layerColor = cc.LayerColor:create(color.blue, CubeWidth, CubeHeight)  --黑色
        lblDesp = cc.Label:createWithSystemFont("墙","Arial",fontSize)
    elseif self.type == Cube.CUBE_TYPE_START then
        layerColor = cc.LayerColor:create(color.red, CubeWidth, CubeHeight)   --紫红
        lblDesp = cc.Label:createWithSystemFont("起始点","Arial",fontSize)
    elseif self.type == Cube.CUBE_TYPE_DESTANATION then
        layerColor = cc.LayerColor:create(color.yellow, CubeWidth, CubeHeight) --黄
        lblDesp = cc.Label:createWithSystemFont("终点","Arial",fontSize)
    elseif self.type ==  Cube.CUBE_TYPE_AVIABLE then
        layerColor = cc.LayerColor:create(color.white, CubeWidth, CubeHeight)  --白
    else
        layerColor = cc.LayerColor:create(color.green, CubeWidth, CubeHeight)  --白
        layerColor:setOpacity(100)
    end

    layerColor:ignoreAnchorPointForPosition(false)
    self:addChild(layerColor)

    if lblDesp then
        lblDesp:setColor(cc.c3b(0,0,0))
        self:addChild(lblDesp)
    end
end

function Cube:getPositionByRowCol()
    return cc.p( CellWidth * (self.col-0.5), CellHeight * (self.row-0.5))
end

5.GameLayer.lua

GameLayer = class("GameLayer",function()
    return cc.Layer:create()
end)

function GameLayer:create()
    local view = GameLayer.new()
    view:__init()
    return view
end

function GameLayer:__init()
    self:addMap()
end

--是否出界
function GameLayer:checkIsInSide(cube)
    return cube.row >= 1 and cube.row <= 10 and cube.col >= 1 and cube.col <= 10 and not self:checkIsInSide(cube)
end

--判断2个格子是否一样
function GameLayer:isEqual(cube1, cube2)
    return cube1.row == cube2.row and cube1.col == cube2.col
end

--背景格子
function GameLayer:initBg()
    for row = 1, 10 do
        for col = 1, 10 do
            local cube = Cube:create(row, col, Cube.CUBE_TYPE_AVIABLE)
            cube:setPosition(cube:getPositionByRowCol())
            self:addChild(cube)
        end
    end
end

--是否可以行走
function GameLayer:checkIsCanGo(cube)

    if cube.row <= 0 or cube.row > 10  or cube.col <= 0 or cube.col > 10 then
        return false
    end

    for _, cubeTmp in ipairs(self.mapList) do
        if cube.row == cubeTmp.row and cube.col == cubeTmp.col and cubeTmp.type == Cube.CUBE_TYPE_WALL then
            return false
        end
    end
    return true
end

--开始点
function GameLayer:initStart()
    self.startCube = Cube:create(3, 4, Cube.CUBE_TYPE_START)
    self.startCube:setPosition(self.startCube:getPositionByRowCol())
    self:addChild(self.startCube)
    table.insert(self.mapList, self.startCube)
end

--结束点
function GameLayer:initDestination()
    self.desCube = Cube:create(3, 9, Cube.CUBE_TYPE_DESTANATION)
    self.desCube:setPosition(self.desCube:getPositionByRowCol())
    self:addChild(self.desCube)
    table.insert(self.mapList, self.desCube)
end

--墙
function GameLayer:initWall()
    math.randomseed(os.time())
    for i = 1, 60 do
        local row = math.random(1,10)
        local col = math.random(1,10)
        local cube = Cube:create(row, col, Cube.CUBE_TYPE_WALL)
        if not self:isEqual(cube, self.startCube) and not self:isEqual(cube, self.desCube) then
            cube:setPosition(cube:getPositionByRowCol())
            self:addChild(cube)
            table.insert(self.mapList, cube)
        end
    end
end

function GameLayer:clearMap()
    self:removeAllChildren()
    self.mapList = {}
end

--480 * 320
--格子大小  48 * 32
function GameLayer:addMap()
    self:clearMap()
    self:initBg()
    self:initStart()
    self:initDestination()
    self:initWall()
    self:findAStarPath()
end

function GameLayer:tableInclude(cubeList, cube)
    local isResult = false
    for i = 1, #cubeList do
        if self:isEqual(cube, cubeList[i]) then
            isResult = true
            break
        end
    end
    return isResult
end

function GameLayer:tableRemove(cubeList, cube)
    for i = 1, #cubeList do
        if self:isEqual(cube, cubeList[i]) then
            table.remove(cubeList, i)
            break
        end
    end
end

function GameLayer:findValueInTable(cubeList, cube)
    for i = 1, #cubeList do
        if self:isEqual(cube, cubeList[i]) then
            return cubeList[i]
        end
    end
end

function GameLayer:findAStarPath()
    --以左下角为起点,顺时针转一圈
    local dirList = {
        {-1,-1},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1}
    }
    self.openList = {}
    self.closeList = {}

    table.insert(self.openList, self.startCube)
    self.startCube.g = 0
    self.startCube.h = self:getManhattonDis(self.startCube)
    self.startCube.f = self.startCube.g + self.startCube.h

    while true do
    	if #self.openList == 0 then
    	   print("Fail, not find !!!")
    	   break
    	else
            local firstCubeInOpenList = self.openList[1]
            table.remove(self.openList, 1)
            table.insert(self.closeList, firstCubeInOpenList)
    	    if self:isEqual(firstCubeInOpenList, self.desCube) then
    	       self.desCube.parent = firstCubeInOpenList
    	       print("Success, find !!!")
               self:printPath()
    	       break
    	    else
    	       for i = 1, 8 do
    	           local dir = dirList[i]
                   local tmpCube = Cube:create(firstCubeInOpenList.row + dir[1], firstCubeInOpenList.col + dir[2], self.startCube.type)
                   if not self:checkIsCanGo(tmpCube) then

                   elseif not self:tableInclude(self.openList, tmpCube) and not self:tableInclude(self.closeList, tmpCube) then
                       self:getOrGetAndSetCubeFGH(firstCubeInOpenList, tmpCube, i)
                       table.insert(self.openList, tmpCube)
                   elseif self:tableInclude(self.openList, tmpCube) then
                        local newFTmp = self:getOrGetAndSetCubeFGH(firstCubeInOpenList, tmpCube, i, true)
                        if newFTmp < self:findValueInTable(self.openList, tmpCube).f then
                            self:getOrGetAndSetCubeFGH(firstCubeInOpenList, tmpCube, i)
                        end
                   elseif self:tableInclude(self.closeList, tmpCube) then
                        local newFTmp = self:getOrGetAndSetCubeFGH(firstCubeInOpenList, tmpCube, i, true)
                        if newFTmp < self:findValueInTable(self.closeList, tmpCube).f then
                            self:tableRemove(self.closeList, tmpCube)
                            table.insert(self.openList, tmpCube)
                            self:getOrGetAndSetCubeFGH(firstCubeInOpenList, tmpCube, i)
                        end
                   end
    	       end
    	    end

    	    --按照f值升序排列openList
    	    local sortFunction = function(cube1, cube2)
    	       return cube1.f < cube2.f
    	    end
            table.sort(self.openList, sortFunction)
--            self:printOpenList(self.openList)
    	end
    end
end

--打印开放列表
function GameLayer:printOpenList(openList)
    print("==========================================")
    for i = 1, #openList do
        local cube = openList[i]
        print("row:"..cube.row.."   col:"..cube.col.."  f:"..cube.f.."  g:"..cube.g.."  h:"..cube.h)
    end
end

--回溯打印路径
function GameLayer:printPath()
    local parentCube = self.desCube

    local resultPath = {}
    while parentCube.parent ~= nil do
        parentCube  = parentCube.parent
        local row = parentCube.row
        local col = parentCube.col

        local cube = Cube:create(row, col)
        cube:setPosition(cube:getPositionByRowCol())
        self:addChild(cube)
    end
end

--1.isOnlyGetFValue 为true: 只返回curCube的可能设置的临时f值
--2.isOnlyGetFValue为nil或false: 设置curCubed的f,g,h并且返回节点的f值
function GameLayer:getOrGetAndSetCubeFGH(srcCube, curCube, i, isOnlyGetFValue)
    if isOnlyGetFValue then
        local g
        if i == 1 or i == 3 or i == 5 or i == 7 then
            g = srcCube.g + 14
        else
            g = srcCube.g + 10
        end
        local h = self:getManhattonDis(curCube)
        local f = g + h
        return f
    else
        if i == 1 or i == 3 or i == 5 or i == 7 then
            curCube.g =  srcCube.g + 14
        else
            curCube.g =  srcCube.g + 10
        end
        curCube.h = self:getManhattonDis(curCube)
        curCube.f = curCube.g + curCube.h
        curCube.parent = srcCube
        return curCube.f
    end
end

--得到一个节点的曼哈顿距离
function GameLayer:getManhattonDis(cube)
    local value = math.abs(self.desCube.row - cube.row) + math.abs( self.desCube.col - cube.col)
    return value*10
end

return GameLayer

具体代码详见我github工程:

https://git.oschina.net/jianan/AStar/tree/master

截图实例:

说明:在随机生成的墙壁中,给定开始点和结束点,浅绿色部分为A*算法计算出来的最短路径。

1.

2.

3.

总结:当估价函数h选定后,就可以让A*是最优算法,在此处采用的是曼哈顿距离!

其它A*入门视频:

http://m.blog.csdn.net/article/details?id=17187239

http://www.jiangzhongyou.net/forum-40-1.html

时间: 2024-11-09 09:35:46

A*算法实现的相关文章

经典排序算法 - 冒泡排序Bubble sort

 原文出自于 http://www.cnblogs.com/kkun/archive/2011/11/23/bubble_sort.html 经典排序算法 - 冒泡排序Bubble sort 原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, 这样一趟过去后,最大或最小的数字被交换到了最后一位, 然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子 例子为从小到大排序, 原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 | 第一趟排序(外循环) 第

转载:DenseNet算法详解

原文连接:http://blog.csdn.net/u014380165/article/details/75142664 参考连接:http://blog.csdn.net/u012938704/article/details/53468483 本文这里仅当学习笔记使用,具体细节建议前往原文细度. 论文:Densely Connected Convolutional Networks 论文链接:https://arxiv.org/pdf/1608.06993.pdf 代码的github链接:h

基于位置信息的聚类算法介绍及模型选择

百度百科 聚类:将物理或抽象对象的集合分成由类似的对象组成的多个类的过程被称为聚类.由聚类所生成的簇是一组数据对象的集合,这些对象与同一个簇中的对象彼此相似,与其他簇中的对象相异."物以类聚,人以群分",在自然科学和社会科学中,存在着大量的分类问题.聚类分析又称群分析,它是研究(样品或指标)分类问题的一种统计分析方法.聚类分析起源于分类学,但是聚类不等于分类.聚类与分类的不同在于,聚类所要求划分的类是未知的. 分类和聚类算法一直以来都是数据挖掘,机器学习领域的热门课题,因此产生了众多的

密码算法详解——AES

0 AES简介 美国国家标准技术研究所在2001年发布了高级加密标准(AES).AES是一个对称分组密码算法,旨在取代DES成为广泛使用的标准. 根据使用的密码长度,AES最常见的有3种方案,用以适应不同的场景要求,分别是AES-128.AES-192和AES-256.本文主要对AES-128进行介绍,另外两种的思路基本一样,只是轮数会适当增加. 1 算法流程 AES加解密的流程图如下: AES加密过程涉及到4种操作:字节替代(SubBytes).行移位(ShiftRows).列混淆(MixCo

矩阵乘法的Strassen算法详解

题目描述 请编程实现矩阵乘法,并考虑当矩阵规模较大时的优化方法. 思路分析 根据wikipedia上的介绍:两个矩阵的乘法仅当第一个矩阵B的列数和另一个矩阵A的行数相等时才能定义.如A是m×n矩阵和B是n×p矩阵,它们的乘积AB是一个m×p矩阵,它的一个元素其中 1 ≤ i ≤ m, 1 ≤ j ≤ p. 值得一提的是,矩阵乘法满足结合律和分配率,但并不满足交换律,如下图所示的这个例子,两个矩阵交换相乘后,结果变了: 下面咱们来具体解决这个矩阵相乘的问题. 解法一.暴力解法 其实,通过前面的分析

关于SVM数学细节逻辑的个人理解(三) :SMO算法理解

第三部分:SMO算法的个人理解 接下来的这部分我觉得是最难理解的?而且计算也是最难得,就是SMO算法. SMO算法就是帮助我们求解: s.t.   这个优化问题的. 虽然这个优化问题只剩下了α这一个变量,但是别忘了α是一个向量,有m个αi等着我们去优化,所以还是很麻烦,所以大神提出了SMO算法来解决这个优化问题. 关于SMO最好的资料还是论文<Sequential Minimal Optimization A Fast Algorithm for Training Support Vector

基于Spark MLlib平台的协同过滤算法---电影推荐系统

基于Spark MLlib平台的协同过滤算法---电影推荐系统 又好一阵子没有写文章了,阿弥陀佛...最近项目中要做理财推荐,所以,回过头来回顾一下协同过滤算法在推荐系统中的应用. 说到推荐系统,大家可能立马会想到协同过滤算法.本文基于Spark MLlib平台实现一个向用户推荐电影的简单应用.其中,主要包括三部分内容: 协同过滤算法概述 基于模型的协同过滤应用---电影推荐 实时推荐架构分析     一.协同过滤算法概述 本人对算法的研究,目前还不是很深入,这里简单的介绍下其工作原理. 通常,

算法 希尔排序

希尔排序 Shell Sort 介绍: 希尔排序(Shell Sort)也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本. 该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个"增量"的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序.因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率比直接插入排序有较大提高. 执行流程: 首先

算法 排序NB二人组 堆排序 归并排序

参考博客:基于python的七种经典排序算法     常用排序算法总结(一) 序前传 - 树与二叉树 树是一种很常见的非线性的数据结构,称为树形结构,简称树.所谓数据结构就是一组数据的集合连同它们的储存关系和对它们的操作方法.树形结构就像自然界的一颗树的构造一样,有一个根和若干个树枝和树叶.根或主干是第一层的,从主干长出的分枝是第二层的,一层一层直到最后,末端的没有分支的结点叫做叶子,所以树形结构是一个层次结构.在<数据结构>中,则用人类的血统关系来命名,一个结点的分枝叫做该结点的"

【机器学习实战】第2章 K-近邻算法(k-NearestNeighbor,KNN)

第2章 k-近邻算法 <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default"></script> KNN 概述 k-近邻(kNN, k-NearestNeighbor)算法主要是用来进行分类的. KNN 场景 电影可以按照题材分类,那么如何区分 动作片 和 爱情片 呢? 动作片:打斗次数更多 爱情片