找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 20419|回复: 0

[游戏娱乐] 批处理解迷宫

[复制链接]
发表于 2011-8-11 00:22:21 | 显示全部楼层 |阅读模式
本帖最后由 CrLf 于 2012-4-15 03:58 编辑

迷宫规格不大于 64*64 ,边界上只有有效的一对出入口,通道字符统一,行进时不走斜线。
(绘制迷宫帖子链接:http://bbs.bathome.net/viewthread.php?tid=16385

2011.08.11 首发,用 call 简单实现解迷宫,但是作为草稿的第一版兼容性差、且效率低,于是同日更新了效率更高的 for 版,不过依然没有解决兼容性的问题。
2011.08.13 更新,写出兼容性很强的优化自适应版,核心算法不变,但是能够自动判定迷宫尺寸、出入口位置,优化了各方向的寻路次序(判断大方向),并用新的路径算法实现标记回路,避免回路导致的死循环。
2011.08.15 更新,再次修正错误和优化代码之后,不再畏惧死循环。同时提升了第五版的效率,超过第四版,并且避免了在该版设计之初,剪枝过程中会舍近求远的缺陷。
2011.09.01 更新,纠正原先修改时忽略的逻辑错误,修改后的第五版效率随着迷宫复杂度的增加将明显降低,于是又不如第四版优越了(上次更新时白高兴了)...
2012.04.14 最后更新,为了与绘制迷宫一贴相呼应,以版本4为基础,加入些许自适应判断功能,以便自动区分路与墙,并自动设置窗口大小、添加方向箭头,虽然未使用新算法,但为符合时间顺序故命名为版本6

以下为第六版代码:
  1. @echo off&setlocal enabledelayedexpansion
  2. set>$
  3. (for /f "delims==" %%a in ($) do set %%a=
  4. path %path%)
  5. rem 不使用 for /f 直接解析命令输出,是为了避免开启新进程影响效率
  6. :::::::::::清洁变量环境,提升脚本效率:::::::::::::

  7. rem -----------------一、自适应判断-------------------

  8. (set /p .1=
  9. set "$=!.1!#"
  10. for %%a in (32 16 8 4 2 1) do (
  11.         if !$:~%%a^,1!. NEQ . set /a mx+=%%a&set $=!$:~%%a!
  12. )
  13. rem 二分回溯法判断迷宫宽度

  14. for /f %%a in (迷宫.txt) do set /a my+=1
  15. rem 计算图形高度

  16. for /l %%a in (2 1 !my!) do (
  17.         set /p .%%a=
  18.         rem 把迷宫图形分行保存为变量
  19.         set /a #!.%%a:~,1!+=1,#!.%%a:~-1!+=1
  20.         rem 统计竖边框字符
  21. )

  22. for %%z in (!my!) do for /l %%a in (2 1 !mx!) do (
  23.         set /a #!.1:~%%a,1!+=1,#!.%%z:~%%a,1!+=1
  24.         rem 统计横边框字符
  25. )
  26. rem mx、my为迷宫宽、高,.1~.N分别记载迷宫每一行的内容
  27. )<迷宫.txt

  28. set /a xx=mx*2+1,yy=my+3
  29. mode con:lines=%yy% cols=%xx%
  30. echo %time%
  31. rem 调整窗口大小并显示时间

  32. set #>$
  33. for /f "tokens=1,2 delims=#=" %%a in ($) do (
  34.         set #%%a=
  35.         if %%b==2 set 路=%%a
  36. )
  37. rem 获取路对应的字符
  38. ::::::::::::::::::收集基本信息::::::::::::::::::::

  39. set /a nx=mx-1,all=mx*my
  40. ::nx 为宽度减一,用于后面的偏移,all 为寻路时的总迭代上限
  41. set "use= "
  42. for /l %%a in (0 1 %nx%) do (
  43.         if defined .%%a (
  44.                 for /l %%b in (0 1 %nx%) do (
  45.                         if "!.%%a:~%%b,1!"=="%路%" set use= %%b.%%a!use!
  46.                         rem 保存可用坐标到 use 变量
  47.                 )
  48.                 if "!.%%a:~,1!"=="%路%" (
  49.                         set se=!se! 0-%%a
  50.                         set t=!t!2
  51.                 )
  52.                 if "!.%%a:~-1!"=="%路%" (
  53.                         set se=!se! %nx%-%%a
  54.                         set t=!t!1
  55.                 )
  56.         )
  57.         if "!.1:~%%a,1!"=="%路%" (
  58.                 set se=!se! %%a-1
  59.                 set t=!t!4
  60.         )
  61.         if "!.%my%:~%%a,1!"=="%路%" (
  62.                 set se=!se! %%a-%my%
  63.                 set t=!t!3
  64.         )
  65.         rem 保存边界出入口位置到变量 se,保存边界入口反方向的对应值到变量 t(方向:1下2右3上4左)
  66. )
  67. :::::::::::::::::::进一步分析:::::::::::::::::::::

  68. rem --------------------二、优化----------------------

  69. for %%a in (!se!) do if defined start (set end=%%a) else set start=%%a
  70. ::设置 se 变量中的第一个坐标为起点,第二个坐标为终点
  71. for /f "tokens=1-4 delims=-" %%a in ("%start%-%end%") do (
  72.         set /a fx=%%a-%%c,fy=%%d-%%b
  73.         if !fx:-^=! gtr !fy:-^=! (
  74.                 set f= 2 3 4 1
  75.         ) else set f= 3 2 1 4
  76.         if !fx! lss 0 (
  77.                 set f=!f: 1= @!
  78.                 set f=!f: 3= 1!
  79.                 set f=!f: @= 3!
  80.         )
  81.         if !fy! lss 0 (
  82.                 set f=!f: 2= @!
  83.                 set f=!f: 4= 2!
  84.                 set f=!f: @= 4!
  85.         )
  86.         rem 判断大方向,把最可能的方向作为首选,其余按概率排列
  87.         set /a "fs=1+%%a/%nx%*2+^!~-%%b+(%%b/%my%)*3""
  88.         set /a "fe=1+2*^!%%c+3*^!~-%%d+%%d/%my%"
  89.         rem 计算在 ff 变量中的偏移量,用于获取与出入口方向对应的方向符号
  90. )
  91. set "ff=@→↓←↑"
  92. ::设置出入口的方向标志
  93. set try="%start:-= %"
  94. set "t=%t:~,1% "
  95. ::try 保存路线坐标,t 记录要排除的方向
  96. ::::::::::::::::规划主要探测方向::::::::::::::::::

  97. for %%a in ($ fx fy se) do set %%a=
  98. ::::::::::::::::再次清空多余变量::::::::::::::::::

  99. rem --------------------三、计算----------------------

  100. for /l %%a in (1 1 %all%) do (
  101.         for /f tokens^=1-3delims^=^,^"^  %%b in ("!t:~,2!!try!") do (
  102.         rem 获取当前坐标和方向
  103.                 for %%e in (!f:%%b^=!) do (
  104.                         rem 排除来的方向
  105.                         if defined back (
  106.                                 set /a "cx=%%c+(2*(%%e/3)-1)*^!(%%e%%2)","cy=%%d+(2*(%%e/3)-1)*(%%e%%2)","no=(%%e+2)%%5+%%e/3"
  107.                                 rem 通过步进方向与当前位置计算下一个要探测的坐标
  108.                                 for /f "tokens=1,2" %%x in ("!cx! !cy!") do (
  109.                                         if "!use: %%x.%%y =!" neq "!use!" (
  110.                                                 rem 判断此坐标是否可用
  111.                                                 if "!try:"%%x^ %%y"=!"=="!try!" (
  112.                                                         rem 判断此坐标是否已用
  113.                                                         set back=
  114.                                                         if !cx!-!cy!==%start% echo 无答案&pause&exit
  115.                                                         if !cx!-!cy!==%end% call :end
  116.                                                         rem 到达终点时调用输出模块(其实就不准备返回了...)
  117.                                                         set try="!cx! !cy!",!try!
  118.                                                         set "t=!no! !t!"
  119.                                                         rem 如果该坐标可用,并且尚未使用过,则位移到此坐标,并阻止回退。
  120.                                                 ) else set use=!use: %%x.%%y = !
  121.                                                 rem 若出现咬尾的情况,则标记此坐标不可用,并回退
  122.                                         )
  123.                                 )
  124.                         )
  125.                         rem 只要当前循环还没找到可用的去路,就按照概率依次探测三个方向上是否可用
  126.                 )
  127.                 if defined back (
  128.                         set use=!use: %%c.%%d = !
  129.                         set t=!t:~2!
  130.                         set try=!try:*,=!
  131.                 ) else set back=1
  132.                 rem 判断路线是否受阻,不畅则回退,并标记当前位置不可用
  133.         )
  134. )

  135. rem --------------------四、输出----------------------

  136. :end
  137. set f=!f:~-2!!f:~-4,2!
  138. for %%a in (!t!) do (
  139.         for /f tokens^=1-2delims^=^,^"^  %%b in ("!try!") do (
  140.                 for %%d in (!f:%%a^=!) do (
  141.                         rem 排除来的方向
  142.                         set /a "cx=%%b+(2*(%%d%%2)-1)*^!(%%d/3)","cy=%%c+(2*(%%d%%2)-1)*(%%d/3)","no=%%d+2*(%%d%%2)-1"
  143.                         for /f "tokens=1,2" %%x in ("!cx! !cy!") do (
  144.                                 set try=!try:*"%%x %%y",="%%b %%c","%%x %%y",!
  145.                                 rem 逆序拼接结果中的相邻坐标
  146.                                 set new=!new!"%%b %%c",
  147.                                 rem 保存修正过的路径在 new 变量中
  148.                         )
  149.                        
  150.                 )
  151.                 set try=!try:*,=!
  152.         )
  153. )

  154. for /f "tokens=1,2 delims=-" %%a in ("%end%") do set /a lx=%%a-1,ly=%%b

  155. for %%a in ("%end:-= %" !new!) do (
  156.         if "!lx! !ly!" neq %%a for /f "tokens=1,2" %%b in ("%%~a") do (
  157.                 set /a "n=%%b+1,fe=1+((%%b-lx+1&2)+(ly-%%c+2^2)),lx=%%b,ly=%%c"
  158.                 if %%b-%%c==%end% set fe=%fe%
  159.                 rem 计算偏移量及方向
  160.                 for /f "tokens=1,2" %%e in ("!n! !fe!") do (
  161.                         set .%%c=!.%%c:~,%%b!!ff:~%%f,1!!.%%c:~%%e!
  162.                 )
  163.                 rem 提取 try 变量,将结果对应坐标的符号转换为全角空格
  164.         )
  165. )

  166. ::转换结果为可见图形
  167. for /l %%d in (1 1 %my%) do echo !.%%d!
  168. ::打印结果
  169. echo %time%
  170. (del $ &pause&exit)>nul
  171. ::::::::::::::将结果转换为可见图形::::::::::::::::
复制代码
迷宫样本:
  1. █████████████████████████████
  2. █▓▓▓▓▓▓▓█▓▓▓▓▓▓▓█▓▓▓█▓▓▓▓▓█▓▓
  3. █▓█████▓█████▓█▓▓▓███▓▓██▓▓▓█
  4. █▓▓▓▓▓█▓▓▓▓▓█▓███▓▓▓█▓▓▓█████
  5. ███▓█▓█▓███▓▓▓█▓▓▓█▓███▓▓▓▓▓█
  6. █▓▓▓█████▓█████████▓▓▓█████▓█
  7. ███▓▓█▓▓▓▓▓▓▓▓▓▓█▓▓▓█▓▓▓▓▓█▓█
  8. █▓██▓█▓██████▓█▓█▓███████▓█▓█
  9. █▓▓▓▓▓▓▓▓▓▓▓███▓█▓▓▓█▓▓▓▓▓█▓█
  10. █▓▓▓█▓██▓██▓▓▓█▓███▓███████▓█
  11. █▓▓▓█▓▓▓▓▓█▓█▓█▓▓▓█▓▓▓▓▓▓▓█▓█
  12. █▓███████▓█▓█████▓█████▓███▓█
  13. █▓▓▓▓█▓▓█▓█▓█▓▓▓▓▓█▓▓▓█▓█▓▓▓█
  14. ████▓█▓██▓███▓███████▓█▓███▓█
  15. █▓▓▓▓█▓▓▓▓▓█▓▓▓█▓▓▓█▓▓▓▓█▓▓▓█
  16. ██████████▓█▓███▓█▓██▓███▓███
  17. █▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓█▓▓█▓▓▓█▓▓▓█
  18. █▓████▓█▓█▓███████▓████▓███▓█
  19. █▓▓▓▓█▓███▓█▓▓█▓▓▓▓▓█▓▓▓█▓▓▓█
  20. ████▓█▓▓▓█▓██▓█████▓█▓███▓███
  21. ▓▓▓▓▓█▓█▓▓▓▓█▓▓▓▓▓▓▓█▓▓▓▓▓▓▓█
  22. █████████████████████████████
复制代码
详见附件,附件包含:
  1. 【使用向导】.bat
  2. 解迷宫1 call.bat
  3. 解迷宫2 for.bat
  4. 解迷宫3 优化自适应.bat
  5. 解迷宫4 拼接相邻.bat
  6. 解迷宫5 拼接相邻2.bat
  7. 解迷宫6 拼接相邻 自适应.bat
  8. 迷宫 单线.txt
  9. 迷宫 宽线有回路.txt
  10. 迷宫.txt
复制代码

解谜宫效果:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

评分

参与人数 1技术 +1 收起 理由
老刘1号 + 1 6x

查看全部评分

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 00:15 , Processed in 0.019093 second(s), 8 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表