[转]mush版本推车机器人教学贴 作者:huacuoh
厕 所蹲坑 无聊手机上网推车的人不少推车的难点好像就是解决乱入he寻找伙计 打算写个解决这两个问题得教学贴不知道违规否?也不知道需求有多大!如果不违规明天开始慢慢写了就。声明:自己本身纯业余 代码极度不规范 大家凑合看把 主要好多代码自己都忘了什么意思了 正好利用这个机会自己整理下思路
北大侠客行MUD,中国最好的MUD 先以接到左二把那里推往南昌的镖为例说一下我的护镖流程:
1 实现需要录制两个路径:一个是从左二把走到南昌的路径;另一个是遍历所有南昌城房间的路径。
zuo_nc="s;s;sw;s;s;s;s;s;s;s;s;nw;n;nw;n;n;n;n;set action 第一阶段结束,赶快点开始找伙计"-------最后一个的目的是为了设置一个标志,提示自己此时第一阶段形成结束
blnc="n;e;w;w;e;n;n;nw;ne;w;n;n;s;s;su;se;s;s;s;e;n;s;s;enter;w;e;e;w;out;n;e;e;eu;eu;wd;wd;w;w;w;w;n;s;s;n;w;w;wu;wu;nu;enter;w;e;e;w;n;s;out;sd;wu;ed;ed;ed;e;e;e;s;w;e;e;w;s;s;n;n;n"
现在的两个路径为字符串形式,为了方便一步一步走,需要将他们分解成数组。也就是将"n;w;s"形式的路径,分解成{"n","w","s"}的形式,此时用到下面的函数
function Split(szFullString, szSeparator)
local nFindStartIndex = 1
local nSplitIndex = 1
local nSplitArray = {}
while true do
local nFindLastIndex = string.find(szFullString, szSeparator, nFindStartIndex)
if not nFindLastIndex then
nSplitArray = string.sub(szFullString, nFindStartIndex, string.len(szFullString))
break
end
nSplitArray = string.sub(szFullString, nFindStartIndex, nFindLastIndex - 1)
nFindStartIndex = nFindLastIndex + string.len(szSeparator)
nSplitIndex = nSplitIndex + 1
end
return nSplitArray
end
举例:Split(zuo_nc,";"),函数返回值就为已经分解为数组的zuo_nc的路径。
由于推车的时候,gan che to n这种命令是无效的,必须写成gan che to north这种形式,所以还要把{"n","w","s"}这种形式转化成{"north","west","south"}这种形式,用到一下函数:
-------------------------------简化方向转完整方向----------------------
function zhfx(fx)
local fx=fx
if fx=="u" then return "up" end
if fx=="d" then return "down" end
if fx=="s" then return "south" end
if fx=="e" then return "east" end
if fx=="w" then return "west" end
if fx=="n" then return "north" end
if fx=="su" then return "southup" end
if fx=="sd" then return "southdown" end
if fx=="wu" then return "westup" end
if fx=="wd" then return "westdown" end
if fx=="eu" then return "eastup" end
if fx=="ed" then return "eastdown" end
if fx=="nu" then return "northup" end
if fx=="nd" then return "northdown" end
if fx=="nw" then return "northwest" end
if fx=="ne" then return "northeast" end
if fx=="sw" then return "southwest" end
if fx=="se" then return "southeast" end
return fx
end
-------------------------------简化方向转完整方向
-------------------------------简化方向的路径转完整方向的路径----------------------
function zhfxlj(lj)
local lj=lj
local temi=1
for i,v in ipairs(lj) do lj=zhfx(v) end
return lj
end
总结:接到推往南昌的镖,之后:
lj1=zuo_nc----推镖车走的第一阶段
lj2=blnc-----推镖车走的第二阶段
lj1=zhfxlj(Split(lj1,";"))-------在需要用到某个路径走之前要先做一步这个工作。
到目前为止实际上只是接到镖之后,推车走之前的准备工作。下面才开始推车流程的第一阶段: 无论是推车行程的那个阶段,我都是利用按照顺序遍历执行数组的方向完成的:
用到的函数: lj=........------------------lj是bianli函数要遍历的数组,比如到nc的镖,要先将转化完的路径赋值给lj这个遍量
function bianli()
local i=tonumber(GetVariable("bianli_i"))-------bianli_i是个计数器,表明现在走到数组的哪一个元素了。
if tonumber(GetVariable("hubiao"))==1 then ------------hubiao个作为一个标志:如果为1就表明现在不带着镖车走,如果为0就得带着镖车走。
if lj==nil then Note("已经走完了,还走个屁啊") Executereturn end -------数组遍历完成之后就不要遍历了再
local s1="当前行走段一共"..tostring(table.getn(lj)).."步,现在为 第"..GetVariable("bianli_i").."步"..",当前命令:"..lj
Note(s1)---------以上两行是用来提醒自己的。
Execute(lj)------这才是行走的命令
elseif tonumber(GetVariable("hubiao"))==0 then
if lj==nil then Note("已经走完了,还走个屁啊") return end
local s1="当前行走段一共"..tostring(table.getn(lj)).."步,现在为 第"..GetVariable("bianli_i").."步"..",当前命令:"..lj
Note(s1)
Execute("gan che to "..lj..";xixi")
end
end具体使用方法:开始走的时候bianli_i赋值为1,然后执行函数bianli(),触发里每当看到出口,就证明该步行走成功,然后继续执行bianli(),这样当数组lj遍历执行完毕后就走到目的地了,
ps:中间遇到劫匪时候,需要将劫匪打跑后继续执行bianli()
走到目的地之后,也就是从左二把走到了南昌了,下面该步入正题了,也就是该寻找伙计了。 寻找伙计的基本原理:
1 放下镖车 ,遍历该城市的每个房间直到找到伙计,也就是遍历执行blnc这个路径直到找到伙计。找到伙计停止后,截取从起点到伙计房间走的所有方向,也就是对 blnc的第一个元素,到找到伙计后的bianli_i之间截取。由于这中间的很多房间是无效房间,比如本来n e就走到了,但是路径当中可能走的是n n n s s e,这时候需要将截取后的路径最简化。
2 翻转路径回到镖车所在地,继续按照刚才简化后的推到伙计那里
3 回到左二把那里继续下一次任务
具体的函数实现:当收到第一阶段结束,到了第二阶段找伙计时候:
SetVariable("hubiao","1")-----表示下一步走的时候不带车走。
zzlj=lj------把刚才已经走过的路径储存起来,因为现在lj要被赋值第二阶段走的路径了。
zzbianli_i=GetVariable("bianli_i")-----把刚才已经走过了多少步储存起来
lj=Split(lj2,";")---最开始接到镖的时候lj2已经被赋值blnc了
lj=zhfxlj(lj)
SetVariable("bianli_i","1")---以上四行是做遍历找伙计的准备工作然后就可以执行函数bianli()开始找伙计了,方法前一篇帖子说过了,捡到出口就执行bianli()
当发现了伙计之后,停止执行bianli()
先记录从起点到现在走了那些方向找到伙计了 local templj={}
for i=1,tostring(GetVariable("bianli_i")) do
table.insert(templj,lj)
i=i+1
end然后该将步数最简化,lj=templj
lj=jhlj(lj)用到的jhlj()函数代码如下
function jhlj(nowlj)
local nowlj=nowlj
local inowlj=1
if nowlj==nil then Note("空的简化个P啊") return end
local function jhlj1()
if nowlj==nil thenreturn
elseif nowlj==revfx(nowlj) then table.remove(nowlj,inowlj) table.remove(nowlj,inowlj) inowlj=1 jhlj1() end
inowlj=inowlj+1
jhlj1()
end
jhlj1()
returnnowlj
end将得到的简化路径添加到第一阶段的路径里,得到从左二把一直的伙计的完整路径(目前存储在zzlj变量里),以便于交镖之后翻转路径回到左二把那里for i=1,table.getn(lj) do
table.insert(zzlj,lj)
i=i+1
end然后该翻转路径回到镖车所在点。lj=revlj(lj)revlj是个翻转路径函数,也就是将n w s 变为 n e s ,代码如下function revlj(nowlj)
local lj=nowlj
local i=table.getn(lj)
local newlj={}
for newi=1,i do
newlj=revfx(lj)
end
return newlj
end
function revfx(fx)
if fx=="enterbj" then return "outbj" end
if fx=="outbj" then return "enterbj" end
if fx=="swboxiaolu" then return "boxiaolune" end
if fx==nil then return end
if fx=="south" then return "north" end
if fx=="east" then return "west" end
if fx=="west" then return "east" end
if fx=="north" then return "south" end
if fx=="southup" then return "northdown" end
if fx=="southdown" then return "northup" end
if fx=="westup" then return "eastdown" end
if fx=="westdown" then return "eastup" end
if fx=="eastup" then return "westdown" end
if fx=="eastdown" then return "westup" end
if fx=="northup" then return "southdown" end
if fx=="northdown" then return "southup" end
if fx=="northwest" then return "southeast" end
if fx=="northeast" then return "southwest" end
if fx=="southwest" then return "northeast" end
if fx=="southeast" then return "northwest" end
if fx=="enter" then return "out" end
if fx=="out" then return "enter" end
if fx=="up" then return "down" end
if fx=="down" then return "up" end
if fx=="u" then return "d" end
if fx=="d" then return "u" end
if fx=="s" then return "n" end
if fx=="e" then return "w" end
if fx=="w" then return "e" end
if fx=="n" then return "s" end
if fx=="su" then return "nd" end
if fx=="sd" then return "nu" end
if fx=="wu" then return "ed" end
if fx=="wd" then return "eu" end
if fx=="eu" then return "wd" end
if fx=="ed" then return "wu" end
if fx=="nu" then return "sd" end
if fx=="nd" then return "su" end
if fx=="nw" then return "se" end
if fx=="ne" then return "sw" end
if fx=="sw" then return "ne" end
if fx=="se" then return "nw" end
return fx
end如果到目前为止你看懂了,那找伙计的就不用再说了,回到镖车起点继续SetVariable("bubiao","0")推着车就走到伙计那里去了,然后hubiao为1,翻转路径,就回到左二把那里去了 所谓的乱入,就是本来我设计好的行走路线是a b c d e,结果在走到c房间的时候却被系统推到m房间去了。
所以解决乱入的基本思路就是以m房间为中心点进行深度遍历,一直找到c房间时遍历停止。记录从m到c的路径,添加到原来的路径当中。
也就是1, 当在c房间时候记录下c房间的所有信息。
2,乱入到m房间,打完劫匪后,镖车放下,深度遍历,、每走到一个房间和以前记录的正确的c房间信息作对比,如果相 同遍历停止,找到c房间,记录下从m到c房间的路径为n e的话,那么修正原来的路径(变量lj)为a b c (w s n e) d e,然后回到m房间从lj的第bianli_i+2步开始行走就ok了,
具体的代码实现:---------------深度遍历-------------------------------------------------------------
------------------------------------------------------------------------------------allchukou={}
cengshu=0
gotorightlj={}
gotorightljb={}
goforward=1
---------------触发每前进一步层数加1并抓取当前出口,出口列表去除来的反方向以及不可行走方向
---------------如果回退一步层数减1
---------------所有走的方向存在数组gotorightlj里
---------------最后简化路径、反转路径
function sdbianli()
maxcengshu=tonumber(GetVariable("maxcengshu"))
if allchukou==nil then Execute("say 遍历结束")return
elseif cengshu==maxcengshu or allchukou==nil then
goforward=0
Note("会退一步")
if gotorightlj~=nil then
Execute(revfx(gotorightlj))
table.remove(gotorightlj,table.getn(gotorightlj))
else
Execute("set action 遍历全部结束")
end
cengshu=cengshu-1
return
else
Note("前进一步")
-------------------------------------------------------碰到挡路或者过不去
---table.remove(gotorightlj)
---sdbianli()
---cengshu=cengshu-1
goforward=1
Execute(allchukou)
table.insert(gotorightlj,allchukou)
table.remove(allchukou,1)
cengshu=cengshu+1
end不知道这个当贴不当贴 乱入深度少,所以环形不容易出现
找伙计深度太深了
1 信息一摸一样的房间。事先录制路径时候,尽量避开信息一样的地方。
2 环形。把深度遍历稍微搞下变成广度遍历几率就会低很多。
难的是迷宫的处理,就是那种n之后s回不到原来地方的。。。。 我这是壮大推车队伍
另外给学mush的增加点信心
只用用最简单的几个语句也能写出机器人。
(完) 回复 8# suzhige
我不是老师,我只是老师的搬运工~
—— Cappuccino 回复 8# suzhige
解决办法,开始推出密信以前,不接那边的镖,或者不走那条路。
over 看了一遍不是很懂
页:
[1]
2