【记录】批处理实现dfs,bfs,双向bfs,A*寻路

1 篇文章 0 订阅

演示程序
链接:http://pan.baidu.com/s/1hrMy7Qk 密码:3hhy

:: dfs By blackkitty
:: 算法描述:深搜
set xx_0=0 && set yy_0=-1
set xx_1=1 && set yy_1=0
set xx_2=0 && set yy_2=1
set xx_3=-1 && set yy_3=0
set x=%current_x% && set y=%current_y%

set flag=0
call:dfs %x% %y% 0
goto:eof

:dfs
:: <x> <y>
if "%1_%2" EQU "%end_x%_%end_y%" (set flag=1 && goto:eof)
set dic_%3=0
:dfs_loop1
set tmp=!dic_%3!
set/a dfs=%3+1
set/a nx=%1+!xx_%tmp%!
set/a ny=%2+!yy_%tmp%!
if !vis_%nx%_%ny%! EQU 0 (
    if !%map%_%nx%_%ny%! EQU 1 (
        call go %nx% %ny%
        call:dfs %nx% %ny% %dfs%
    )
)
if %flag% EQU 1 (goto:eof)
set/a dic_%3+=1
if !dic_%3! LSS 4 (goto dfs_loop1)
goto:eof
:: dbfs By blackkitty
:: 算法描述:逆向广搜
set xx_0=0&&set yy_0=-1
set xx_1=1&&set yy_1=0
set xx_2=0&&set yy_2=1
set xx_3=-1&&set yy_3=0

set l=0
set r=1
set x0=%end_x%
set y0=%end_y%
set nxt_%end_x%_%end_y%=0

:rbfs
set x=!x%l%!
set y=!y%l%!
:: 在地图上显示标记(x,y),演示搜索过程
:: call:mark %x% %y% .
set/a l+=1
if "%x%_%y%" EQU "%start_x%_%start_y%" (goto rush)
for /l %%i in (0,1,3) do (
    set/a nx=x+!xx_%%i!
    set/a ny=y+!yy_%%i!
    set/a val=%map%_!nx!_!ny!
    if "!val!" EQU "1" (
        if not defined nxt_!nx!_!ny! (
            set nxt_!nx!_!ny!=!x!_!y!
            set x!r!=!nx!
            set y!r!=!ny!
            set/a r+=1
        )
    )
)
goto rbfs

:rush
set vv=!nxt_%start_x%_%start_y%!
:rush_loop
if "%vv%" EQU "0" (goto:eof)
call go %vv:_= %
set vv=!nxt_%vv%!
goto rush_loop

:mark
:: <x> <y> 在地图上显示标记(x,y),用来演示搜索过程
set/a _x=%1*2+%maze_x% && set/a _y=%2+%maze_y%
cc %_x% %_y% && echo.%~3
goto:eof

BFS

:: dbfs By blackkitty
:: 算法描述:双向广搜
set xx_0=0&&set yy_0=-1
set xx_1=1&&set yy_1=0
set xx_2=0&&set yy_2=1
set xx_3=-1&&set yy_3=0

set l=0
set r=2
set x0=%start_x%
set y0=%start_y%
set v%start_x%_%start_y%=pre
set pre_%start_x%_%start_y%=0
set x1=%end_x%
set y1=%end_y%
set v%end_x%_%end_y%=nxt
set nxt_%end_x%_%end_y%=0

:dbfs
set x=!x%l%!
set y=!y%l%!
:: 在地图上显示标记(x,y),演示搜索过程
:: call:mark %x% %y% .
set v=!v%x%_%y%!
set/a l+=1
set/a i=0
:loop
set/a nx=%x%+!xx_%i%!
set/a ny=%y%+!yy_%i%!
if "!%map%_%nx%_%ny%!" EQU "1" (
:: 若临块为路
    if "!v%nx%_%ny%!" NEQ "%v%" (
    :: 若临块的标记与本块不同
        if defined v%nx%_%ny% (
            ::找到通路
            if "%v%" EQU "pre" (
                call:rush %x% %y% %nx% %ny%
            ) else (
                call:rush %nx% %ny% %x% %y% 
            )
            goto:eof
        )
    :: 若临块的标记与本块不同,且临块无标记
        set %v%_%nx%_%ny%=%x%_%y%
        set x%r%=%nx%&&set y%r%=%ny%&&set v%nx%_%ny%=%v%
        set/a r+=1
    )
)
set/a i+=1&&if "!i!" NEQ "4" (goto loop)
goto dbfs

:rush
set vv=%1_%2
:rvs_loop
if "!pre_%vv%!" EQU "0" (goto rvs_lopp_end)
set nxt_!pre_%vv%!=%vv%
set vv=!pre_%vv%!
goto rvs_loop
:rvs_lopp_end
set nxt_%1_%2=%3_%4
set vv=!nxt_%start_x%_%start_y%!
:rush_loop
if "%vv%" EQU "0" (goto:eof)
call go %vv:_= %
set vv=!nxt_%vv%!
goto rush_loop

:mark
:: <x> <y> 在地图上显示标记(x,y),用来演示搜索过程
set/a _x=%1*2+%maze_x% && set/a _y=%2+%maze_y%
cc %_x% %_y% && echo.%~3
goto:eof

DBFS

:: astar By blackkitty
:: 算法描述:逆向启发式A*
set xx_0=0&&set yy_0=-1
set xx_1=1&&set yy_1=0
set xx_2=0&&set yy_2=1
set xx_3=-1&&set yy_3=0

set new=1
set x0=%end_x%
set y0=%end_y%
set nxt_%end_x%_%end_y%=0
set gn0=0
set fn0=0
set list=n0
set/a maxfn=!%map%_width!*!%map%_height!

:astar
set vv=_
set minfn=%maxfn%
:: 从列表选取fn最小的位置
for %%k in (%list%) do (
    if !f%%k! LSS !minfn! (
        set minfn=!f%%k!
        set vv=%%k
    )
)
:: 从列表中删除这个位置
set list=!list:%vv%=!
set vv=%vv:~1%
set x=!x%vv%!
set y=!y%vv%!

:: 在地图上显示标记(x,y),演示搜索过程
call:mark %x% %y% .

if "%x%_%y%" EQU "%start_x%_%start_y%" (goto rush)
for /l %%i in (0,1,3) do (
    set/a nx=x+!xx_%%i!
    set/a ny=y+!yy_%%i!
    set/a val=%map%_!nx!_!ny!
    if "!val!" EQU "1" (
        if not defined nxt_!nx!_!ny! (
            set nxt_!nx!_!ny!=!x!_!y!
            :: 加入列表
            set list=!list! n!new!
            :: 计算gn
            set/a gn!new!=!gn%vv%!+1
            :: 计算fn保存至fn!new!
            call:fn !nx! !ny! gn!new! fn!new!
            set x!new!=!nx!
            set y!new!=!ny!
            set/a new+=1
        )
    )
)
goto astar

:rush
pause>nul
set vv=!nxt_%start_x%_%start_y%!
:rush_loop
if "%vv%" EQU "0" (goto:eof)
call go %vv:_= %
set vv=!nxt_%vv%!
goto rush_loop


:fn
:: <x> <y> [gn] [ret] 起点到x,y的估计代价(fn = gn + hn)
:: gn 终点到(x,y)的实际代价
:: hn 起点到(x,y)的估计代价,估值为起点到(x,y)的曼哈顿距离
set/a tmp=%1-%start_x%
if %tmp% LSS 0 (set/a tmp=-tmp)
set %4=%tmp%
set/a tmp=%2-%start_y%
if %tmp% LSS 0 (set/a tmp=-tmp)
set/a %4=!%4!+%tmp%+!%3!
goto:eof

:mark
:: <x> <y> 在地图上显示标记(x,y),用来演示搜索过程
set/a _x=%1*2+%maze_x% && set/a _y=%2+%maze_y%
cc %_x% %_y% && echo.%~3
goto:eof

astar

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值