自己写的贪吃蛇(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
- 自己写的贪吃蛇(3)
- 自己写的贪吃蛇(1)
- 自己写的贪吃蛇(2)
- 自己写的贪吃蛇(4)
- 自己写的贪吃蛇
- 分享自己写的一个贪吃蛇的游戏(Linux)
- 用java的swing框架自己写贪吃蛇游戏
- 我自己写的第一个游戏--贪吃蛇(c语言实现)
- 我自己写的第一个游戏--贪吃蛇(windows下c语言实现)
- QT写的贪吃蛇(C++)
- JS写的贪吃蛇
- c#写的贪吃蛇
- Java写的贪吃蛇
- jquery 写的贪吃蛇。。
- c++写的贪吃蛇
- QT5写的贪吃蛇
- glut写的贪吃蛇
- glut写的贪吃蛇
- Flask Web 开发 测试
- Android横竖屏切换导致Actvivty生命周期变化和解决方法
- Leetcode 121. Best Time to Buy and Sell Stock 股票买卖 解题报告
- 237. Delete Node in a Linked List
- Unix网络编程之epoll函数模拟10万客户端链接服务器
- 自己写的贪吃蛇(3)
- iOS 推送 逻辑
- js判断来路是否是百度等搜索索引进行弹窗或自动跳转
- DocX.dll(无需安装OFFICE操作word文档)
- 分布式Session问题
- 自学-ES6篇-Proxy和Reflect
- Mongoose学习参考文档
- 第7周项目3-负数把正数赶出队列
- 2.Observables - 简要介绍Observable的观察者模型