自己写的贪吃蛇(3)

来源:互联网 发布:sql server 2008教材 编辑:程序博客网 时间:2024/06/05 18:00

A*算法网上很多介绍了,在此就不详细介绍了。

首先是计算一个格子的(start)的相邻4个方向上的G,F,H值等
每个格子有一个index属性来标识在cells数组中的位置
target表示要到达的目标格子
opened是要将要搜寻的数组
closed是已经搜寻了的数组
snakes看着障碍物

function SnakeGame:calculateCell(start, dir, target, opend, closed, snakes)    local cell = nil    local index = start.index    local b = false    if dir == SnakeGame.Dir.LEFT then        cell = index - 1    elseif dir == SnakeGame.Dir.RIGHT then        cell = index + 1    elseif dir == SnakeGame.Dir.UP then        cell = index + self.column_num    elseif dir == SnakeGame.Dir.DOWN then        cell = index - self.column_num    end    if self.cells[cell] then        for k, v in ipairs(closed) do             if cell == v.index then                -- 已经在搜寻过了的路径里则不作处理                b = true                break            end        end        if not b then            for k, v in ipairs(snakes) do                 if cell == v.index and v ~= target then                    -- 障碍物                    b = true                    break                end            end                    end        if not b then            -- 跳行的判断            if dir == SnakeGame.Dir.LEFT then                b = self.cells[index].x > self.cells[cell].x            elseif dir == SnakeGame.Dir.RIGHT then                b = self.cells[index].x < self.cells[cell].x            elseif dir == SnakeGame.Dir.UP then                b = self.cells[index].y < self.cells[cell].y            elseif dir == SnakeGame.Dir.DOWN then                b = self.cells[index].y > self.cells[cell].y            end            if b then                local G = start.G + 1 --G值是上一个的G+1                local H = math.abs(self.cells[target.index].x - self.cells[cell].x) / self.cell_width + math.abs(self.cells[target.index].y - self.cells[cell].y) / self.cell_width                -- H是当前到目标的最短距离(其实就是横向和竖向的直线距离和)                local F = G + H                for k, v in ipairs(opend) do                     if v.index == cell then                        if F < v.F then                            -- 如果在待搜索的里面并且F值更小则替换F值和parent                            v.F = F                            v.parent = start                        end                        return nil                    end                end                -- 返回dir方向上的搜寻                return {index = cell, G = G, H = H, F = F, parent = start, dir = dir}            end        end    end    return nilend

在opend里找到最小F值的

function SnakeGame:findMinF(opend)    local key = #opend    for k, v in ipairs(opend) do         if k < #opend then            if v.F <= opend[key].F then                key = k            end        end    end    return keyend

搜寻一条最短的路径

-- 返回蛇的头部到达target的最短路径或者不存在function SnakeGame:checkAWay(snakes, target)    local opend = {}    local closed = {}    -- 用蛇的头部作为搜寻的起点    local start = {index = snakes[1].index, G = 0}    table.insert(closed, start)    local left = self:calculateCell(start, SnakeGame.Dir.LEFT, target, opend, closed, snakes)    local right = self:calculateCell(start, SnakeGame.Dir.RIGHT, target, opend, closed, snakes)    local up = self:calculateCell(start, SnakeGame.Dir.UP, target, opend, closed, snakes)    local down = self:calculateCell(start, SnakeGame.Dir.DOWN, target, opend, closed, snakes)    -- 存在则插入到opend数组里面    if left then        table.insert(opend, left)    end    if right then        table.insert(opend, right)    end    if up then        table.insert(opend, up)    end    if down then        table.insert(opend, down)    end    local find_a_way = false    while opend[1] do        local key = self:findMinF(opend)        -- 最小F值的放入closed里面        table.insert(closed, opend[key])        table.remove(opend, key)        -- 到达目标则找到最短路径        if closed[#closed].index == target.index then                 find_a_way = true                   break        end        local left = self:calculateCell(closed[#closed], SnakeGame.Dir.LEFT, target, opend, closed, snakes)        local right = self:calculateCell(closed[#closed], SnakeGame.Dir.RIGHT, target, opend, closed, snakes)        local up = self:calculateCell(closed[#closed], SnakeGame.Dir.UP, target, opend, closed, snakes)        local down = self:calculateCell(closed[#closed], SnakeGame.Dir.DOWN, target, opend, closed, snakes)        if left then            table.insert(opend, left)        end        if right then            table.insert(opend, right)        end        if up then            table.insert(opend, up)        end        if down then            table.insert(opend, down)        end    end    if find_a_way then                return closed    else        print("not find a way!")        return nil    endend

在ctor里面初始化一个数组self.targetLines = {} 用于放置最短路径每一步的方向,即蛇移动的方向

function SnakeGame:doAI(target)    if #self.targetLines > 0 then        return    end    target = target or self.tail          local closed = self:checkAWay(self.snakes, target)    if closed then        self.targetLines = {}        table.insert(self.targetLines, closed[#closed].dir)        local parent = closed[#closed].parent        local ii = 1        while parent and parent ~= closed[1] do            local index = parent.index                        local x = self.cells[index]            table.insert(self.targetLines, parent.dir)              parent = parent.parent        end              else        print("not find a way!")    endend

在generateBody末尾增加一个self:doAI()的调用,让每次生成目标tail的时候生成最短路径!

最后修改onEnter函数中的update让它沿AI最短路径跑起来

function SnakeGame:onEnter()    local time1 = tsixi.THelper:currentMilliseconds()    local update = function(dt)        if not self.is_failed then            local now = tsixi.THelper:currentMilliseconds()            if not self.parse and (now - time1 >= 50 or self.must) then                self.must = false                time1 = now                self.direction = self.targetLines[#self.targetLines]                table.remove(self.targetLines)                                  self:doMove()                            end             end    end    self:scheduleUpdateWithPriorityLua(update, 0) end

现在蛇可以自己去吃目标物了
这里写图片描述

现在这个AI还有很多问题,如果生成的红块在蛇本身的身体里时就找不到,下一节再优化这个问题

0 0
原创粉丝点击