Board logo

标题: [游戏娱乐] 批处理绘制迷宫 [打印本页]

作者: CrLf    时间: 2012-4-14 21:32     标题: 批处理绘制迷宫

本帖最后由 CrLf 于 2012-4-15 03:37 编辑

[attach]5148[/attach]
(解谜宫代码见此贴:http://bbs.bathome.net/viewthread.php?tid=13619

其实思路上和 neor 与本顿的代码大同小异,主要是沾了 for 天生高效的光...话不多说,上原始代码:
  1. @echo off
  2. set>tmp
  3. ::设定
  4. set "墙=█"
  5. set "路= "
  6. set 演示=rem
  7. set /a 行=40,列=40
  8. rem 参数设置初始化,"演示=rem" 代表不进行实时绘制
  9. set /a 屏宽=列*2+1,屏高=行+3,endline=行*列-列,now=列+1
  10. mode con: lines=%屏高% cols=%屏宽%
  11. echo %time%
  12. rem 改变窗口尺寸及显示时间
  13. set "fail= "
  14. rem 必要的变量初始化
  15. setlocal enabledelayedexpansion
  16. for /l %%a in (1 1 !列!) do set $=!$!!墙!
  17. (
  18. for /f "delims==" %%a in (tmp) do set %%a=
  19. del tmp>nul
  20. for %%b in (行 列 屏高 屏宽 墙 路 endline) do set %%b=
  21. rem 清除作为常数的多余变量,以下仅以 %str% 的形式取值
  22. for /l %%a in (3 1 %行%) do set $=!$!%$%
  23. set $=%$%%路%%路%!$:~,-2!
  24. rem 生成框架,将整个迷宫存储于变量 $
  25. for /l %%a in () do (
  26. set /a "ra=!random!%%4,ra=now+(^!~-ra*%列%-^!ra*%列%-ra/2+ra/3*2),test=ra%% %列%*(ra/%列%)*(-~ra%% %列%)*^!(ra/(%endline%))"
  27. rem 随机取得延伸方向,并检测其是否在边界
  28. for %%Z in (!ra!) do (
  29. if "!fail: %%Z =!"=="!fail!" (
  30. set "fail=!fail!%%Z "
  31. if !test! neq 0 (
  32. set tmp=!$:~%%Z!!$:~,%%Z!
  33. set test=!tmp:~1,1!!tmp:~-1,1!!tmp:~-%列%,1!!tmp:~%列%,1!
  34. rem 先将探测指针后与探测指针前的变量内容交换,可理解为将指针位置的坐标轴暂时设为原点
  35. rem 便于以 c 语言指针的方式进行取值而避开对前后左右四个偏移量的计算
  36. if "!test:%路%=!"=="%墙%%墙%%墙%" (
  37. set $=!tmp:~-%%Z!%路%!tmp:~1,-%%Z!
  38. set now=!ra!
  39. set ok=!now! !ok!
  40. set "fail= "
  41. rem 当发现一个正确的目标点时,抵达该点,清空失败记录
  42. rem 并修改该点的状态为 %路%,同时记录在过往路线中
  43. %演示% echo !$!%$%&echo;
  44. )
  45. )
  46. )
  47. )
  48. for /f "tokens=4" %%b in ("!fail!") do (
  49. rem 当 !fail! 中的失败记录数达到四个时触发此循环
  50. if defined ok (
  51. for /f "tokens=1*" %%c in ("!ok!") do set now=%%c&set ok=%%d
  52. set "fail= "
  53. rem 按照成功记录回退,!ok! 中始终只记录一条路线,记录被清空时认为迷宫绘制完成
  54. ) else (
  55. set /a "ra=!random!%%(%行%*2+%列%*2-6),ra+=-~ra/%列%,test=ra/%列%,tmp=ra%%%列%,tmp=^!(test)*tmp+^!(test-1)*((tmp+1)*%列%-1)+^!(test-2)*(%endline%+tmp-1)+^!(test-3)*(tmp+1)*%列%"
  56. rem 随机设置终点位置
  57. for %%Z in (!tmp!) do (
  58. set tmp=!$:~%%Z!!$:~,%%Z!
  59. set "test=!tmp:~1,1!!tmp:~-1,1!!tmp:~-%列%,1!!tmp:~%列%,1!"
  60. rem 获取上下左右的状态
  61. if "!test:%墙%=!"=="%路%" (
  62. echo !tmp:~-%%Z!%路%!tmp:~1,-%%Z!
  63. echo !time!
  64. pause>nul&exit
  65. rem 测试若该点可用并与路相接则设为终点并打印迷宫
  66. )
  67. )
  68. )
  69. )
  70. )
  71. )
复制代码
绘制迷宫效果:
[attach]5147[/attach]
作者: CrLf    时间: 2012-4-14 21:35

本帖最后由 CrLf 于 2012-4-15 04:08 编辑

为了能更自由地控制生成的迷宫,在原基础上改了一个扩展设置自定义版,代码中默认开启了实时显示,如要关闭则在扩展设置中修改 %演示% 为 0:
  1. @echo off&setlocal enabledelayedexpansion
  2. set>tmp
  3. ::设定
  4. set "墙=█"
  5. set "路= "
  6. set /a 行=40,列=40
  7. rem 基本设置
  8. set /a 屏宽=列*2+1,屏高=行+3,endline=行*列-列,now=列+1
  9. mode con: lines=%屏高% cols=%屏宽%
  10. echo %time%
  11. rem 改变窗口尺寸及显示时间
  12. set /a 钜率=4,钜率衰减=400,起始点间隔下限=80,演示=1
  13. rem 扩展设置
  14. rem %钜率%控制走直线的概率,%钜率衰减%控制钜率随着绘制进度而降低
  15. rem %起始点间隔下限%设置终点离起点至少有多远,%演示%设置实时绘制
  16. for /l %%a in (1 1 %列%) do set $=!$!!墙!
  17. if "%演示%"=="1" title 开始于%time%&set "_演示=echo ^!$^!%$%&echo;"
  18. set /a "_间隔=(%行%*2+%列%*2-6-%起始点间隔下限%0/5)"
  19. if defined 起始点间隔下限 (
  20. set /a "1/(起始点间隔下限/(行+列-6)),起始点间隔下限=行+列-6" 2>nul
  21. set "_间隔=%_间隔%+!起始点间隔下限!0/10"
  22. )
  23. if defined 钜率 (
  24. set _钜率1=if ^^!random:~-1^^! gtr ^^!钜率^^! set /a "ra=^!random^!%%4,f=^^^!~-ra*%列%-^^^!ra*%列%-ra/2+ra/3*2"
  25. set _钜率2=ra=now+f
  26. if defined 钜率衰减 set _钜率衰减=set /a "num+=1,钜率-=^^^!(num%%%钜率衰减%)"
  27. ) else set "_钜率2=ra=^!random^!%%4,ra=now+(^^^!~-ra*%列%-^^^!ra*%列%-ra/2+ra/3*2)"
  28. rem 扩展设置初始化
  29. set "fail= "
  30. rem 必要的变量初始化
  31. (
  32. for /f "delims==" %%a in (tmp) do set %%a=
  33. del tmp>nul
  34. for %%b in (
  35. _钜率1 _钜率2 _钜率衰减 _间隔 _演示
  36. endline 行 列 屏高 屏宽 墙 路 起始点间隔下限 钜率衰减 演示
  37. ) do set %%b=
  38. rem 清除作为常数的多余变量,保证效率及可靠性,后文以 %str% 的形式取值
  39. for /l %%a in (3 1 %行%) do set $=!$!%$%
  40. set $=%$%%路%%路%!$:~,-2!
  41. rem 生成框架,将整个迷宫存储于变量 $
  42. for /l %%a in () do (
  43. %_钜率1%
  44. set /a "%_钜率2%,test=ra%% %列%*(ra/%列%)*(-~ra%% %列%)*^!(ra/(%endline%))"
  45. rem 随机取得延伸方向,并检测其是否在边界
  46. for %%Z in (!ra!) do (
  47. if "!fail: %%Z =!"=="!fail!" (
  48. set "fail=!fail!%%Z "
  49. if !test! neq 0 (
  50. set tmp=!$:~%%Z!!$:~,%%Z!
  51. set test=!tmp:~1,1!!tmp:~-1,1!!tmp:~-%列%,1!!tmp:~%列%,1!
  52. rem 先将探测指针后与探测指针前的变量内容交换,可理解为将指针位置的坐标轴暂时设为原点
  53. rem 便于以 c 语言指针的方式进行取值而避开对前后左右四个偏移量的计算
  54. if "!test:%路%=!"=="%墙%%墙%%墙%" (
  55. %_钜率衰减%
  56. set $=!tmp:~-%%Z!%路%!tmp:~1,-%%Z!
  57. set now=!ra!
  58. set ok=!now! !ok!
  59. set "fail= "
  60. rem 当发现一个正确的目标点时,抵达该点,清空失败记录
  61. rem 并修改该点的状态为 %路%,同时记录在过往路线中
  62. %_演示%
  63. )
  64. )
  65. )
  66. )
  67. for /f "tokens=4" %%b in ("!fail!") do (
  68. rem 当 !fail! 中的失败记录数达到四个时触发此循环
  69. if defined ok (
  70. for /f "tokens=1*" %%c in ("!ok!") do set now=%%c&set ok=%%d
  71. set "fail= "
  72. rem 按照成功记录回退,!ok! 中始终只记录一条路线,记录被清空时认为迷宫绘制完成
  73. ) else (
  74. set /a "ra=!random!%%%_间隔%,ra+=-~ra/%列%,test=ra/%列%,tmp=ra%%%列%,tmp=^!(test)*tmp+^!(test-1)*((tmp+1)*%列%-1)+^!(test-2)*(%endline%+tmp-1)+^!(test-3)*(tmp+1)*%列%"
  75. rem 随机设置终点位置
  76. for %%Z in (!tmp!) do (
  77. set tmp=!$:~%%Z!!$:~,%%Z!
  78. set "test=!tmp:~1,1!!tmp:~-1,1!!tmp:~-%列%,1!!tmp:~%列%,1!"
  79. rem 获取上下左右的状态
  80. if "!test:%墙%=!"=="%路%" (
  81. echo !tmp:~-%%Z!%路%!tmp:~1,-%%Z!
  82. echo !time!
  83. pause>nul&exit
  84. rem 测试若该点可用并与路相接则设为终点并打印迷宫
  85. )
  86. )
  87. )
  88. )
  89. )
  90. )
复制代码

作者: lllsoslll    时间: 2012-4-14 23:15

顶楼下载的 绘制迷宫  自定义.bat
这个运行后图像失真,乱。。。
作者: lllsoslll    时间: 2012-4-14 23:20

建议把墙用 细线表示;
我开始都分不清那个是墙,上面钉4个钉子的是墙还是不是墙,,,,不知其他人看后什么感觉。。。

演示出路的时候 用 箭头↑    →    ↓ 表示 。。。
作者: CrLf    时间: 2012-4-15 04:06

回复 4# lllsoslll
  1. 不知失真是何意呢?
  2. 墙面用细线表示的这个提议,个人感觉对效率的影响较大且实现起来颇费手脚,更麻烦的是难以在解谜宫一贴的代码中通过边框上的出入口自动判断道路字符
  3. 路面已用全角空格代替,应可区别于墙面
  4. 箭头的提议不错,已在那个帖子中修改代码及附件。
复制代码

作者: fatcat    时间: 2012-4-17 21:23

回复 1# CrLf
下图中打圈处的点, 是否是被遗漏的:

作者: CrLf    时间: 2012-4-17 23:11

回复 6# fatcat


    确属遗漏,大概知道是什么原因,回头有空改下,多谢!




欢迎光临 批处理之家 (http://bathome.net./) Powered by Discuz! 7.2