本帖最后由 路过 于 2021-6-15 00:24 编辑
模型设计参考http://www.bathome.net/thread-4892-1-1.html并作出如下改进:
1.图案可自定义;
2.支持更多移动指令;
3.支持更多盘数[默认最小2最多13];
4.支持任意合法状态的汉诺塔求解;
5.内置作弊指令[修改步数,强制移动等]。 | @echo off | | title 汉诺塔V1.2 | | color 0f | | set #=3 | | set #q=%path% | | for /f "delims== eol=#" %%z in ('set ') do (set "%%z=") | | set path=%#q% | | setlocal enabledelayedexpansion | | | | ::自定义图标序列C、最少盘数Mi和最多盘数Ma、柱子名称[#x、#y、#z皆1个字符]. | | ::忽略ping时的最小盘数#p,注意图标序列中不能出现柱子名称 | | set C=_1234567890JQK | | set/a Ma=13,Mi=2,#q=0 | | set #x=a | | set #y=b | | set #z=c | | set #p=8 | | call :Help %#% | | | | :Wait 等待用户输入 | | cls&echo;当前盘子数:%#% | | set /p Sz=s开始游戏,[%Mi%-%Ma%]重定义盘子数 | | for /l %%a in (%Mi%,1,%Ma%) do (if !Sz!==%%a (call :Win %%a)) | | if /i !Sz!==s (goto :Init) | | goto :Wait | | | | :Init 游戏初始化 | | set "Sz=" | | for /l %%a in (1,1,%#%) do (set _!C:~%%a,1!=%#x%) | | set $=%#x% %#y% %#z% | | for /f "delims==" %%z in ('set .') do (set "%%z=") | | for %%b in (%$%) do (set $w=!$:%%b =! | | for %%c in (!$w!) do (set .%%b%%c=3)) | | for /l %%a in (1,1,%#%) do ( | | for %%b in (%$%) do (set .!C:~%%a,1!%%b=1 | | set .!C:~%%a,1!%%b#=4) | | ) | | for /l %%a in (1,1,%#%) do (for %%b in (%$%) do (set $w=!$:%%b =! | | for %%c in (!$w!) do (set .!C:~%%a,1!%%b%%c=2))) | | set/a Sp=0,lin=0 | | if !#q!==1 (set/a .1152=5) | | | | ::绘图常量初始化 | | for /f "delims==" %%z in ('set $') do (set "%%z=") | | for %%b in (%#x% %#y% %#z%) do ( | | for /l %%a in (1,1,%#%) do (set "$%%b=!$%%b! ") | | set $%%b=!$%%b!%%b!$%%b! | | ) | | for /l %%a in (1,1,%#%) do (set $w=!$w!%C:~0,1% | | for /l %%b in (%%a,1,%#%) do (set w=!C:~%%b,1! | | set $%%b=!$%%b!!w! | | ) | | set w=!C:~%%a,1! | | set $%%a=!$%%a:~0,-1!!w!!$%%a:~0,-1! | | for /l %%b in (%%a,1,%#%) do (set "$%%a= !$%%a! ") | | ) | | set $w=!$w!!$w!%C:~0,1% | | set $=!$1:1= ! | | | | :Loop 显示游戏 | | call :Move_Draw !Sz! | | set/a Sz=1,St=0 | | for /l %%a in (1,1,%#%) do (for /f %%b in ("!C:~%%a,1!") do (if !_%%b!==%#z% (set/a St+=1))) | | if !St!==%#% ( | | set/a "St=(1<<%#%)-1" | | if !Sp! lss !St! (echo;最少步数!St!,开了是吧!) | | if !Sp! equ !St! (echo;方法最便捷,太厉害了!) | | if !Sp! gtr !St! (echo;最少步数!St!,继续努力!) | | pause & goto :Wait | | ) | | echo;b返回 s求解 r重玩 q作弊开关 | | if !#q!==1 (echo;1152直接过关 +/-增减1步,++/--增减10步,+++/---增减100步) | | set /p Sz=请输入移动指令或命令: | | if /i !Sz!==b (goto :Wait) | | if /i !Sz!==q (if !#q! neq 1 (set #q=1) else (set #q=0)) | | if /i !Sz!==s (Call :Solute %#z%) | | if /i !Sz!==r ( | | for /l %%a in (1,1,%#%) do (set _!C:~%%a,1!=%#x%) | | set/a Sp=0,lin=0 | | ) | | if !#q!==1 ( | | for %%a in (+ -) do ( | | if !Sz!==%%a (set/a Sp%%a=1) | | if !Sz!==%%a%%a (set/a Sp%%a=10) | | if !Sz!==%%a%%a%%a (set/a Sp%%a=100) | | ) | | if !Sp! lss 0 (set Sp=0) | | ) | | goto :Loop | | | | :Solute 任意状态求解 | | set/a lin=0 | | set lst=%1 | | set all=%#x%%#y%%#z% | | for /l %%a in (%#%,-1,1) do (set/a nxt=%%a-1 | | for /f %%b in ("!C:~%%a,1!") do ( | | if !_%%b! neq !lst! ( | | for /f "tokens=1-2" %%c in ("!lst! !_%%b!") do ( | | set be=!all:%%c=! | | set be=!be:%%d=! | | set ".cm!lin!=call :Best_Solute !nxt! !be! %%c %%d" | | set/a lin+=1 | | set ".cm!lin!=call :Move_Draw %%b%%c#" | | set/a lin+=1 | | set lst=!be! | | ) | | ) | | ) | | ) | | (set #q=1 | | for /l %%z in (!lin!,-1,0) do (!.cm%%z!) | | set #q=%#q%) | | set "Sz=" | | goto :eof | | | | :Best_Solute 获取最优解 | | if %1 equ 0 goto :eof | | set/a n=%1-1 | | call :Best_Solute %n% %2 %4 %3 | | set w=!C:~%1,1! | | call :Move_Draw !w!%3# | | set/a n=%1-1 | | call :Best_Solute %n% %4 %3 %2 | | goto :eof | | | | :Move_Draw 绘图与移动检测 | | set qq=0 | | if defined .%1 ( | | set qq=!.%1! | | set Sz=%1 | | set/a M1=0,D1=0,M2=0,D2=0 | | set End=!Sz:~-1! | | ) | | if !qq!==1 (::1b型 | | for /f %%a in ("!Sz:~0,1!") do (set Sz=%%a!_%%a!!End! | | if !_%%a! neq !End! (set/a qq+=1)) | | ) | | if !qq!==2 (::1ab型 | | set M1=!Sz:~1,1!&set M2=!Sz:~0,1! | | for /l %%a in (%#%,-1,1) do (for /f %%b in ("!C:~%%a,1!") do (if !_%%b!==!M1! (set D1=%%b))) | | if !D1!==!M2! (set Sz=!Sz:~1,2!&set/a qq+=1) | | ) | | if !qq!==3 (::ab型 | | set qq=!Sz:~0,1! | | set/a M1=0,D1=0,M2=0,D2=0 | | for /l %%a in (%#%,-1,1) do (for /f %%b in ("!C:~%%a,1!") do (if !_%%b!==!qq! (set M1=%%a&set D1=%%b) | | if !_%%b!==!End! (set M2=%%a&set D2=%%b))) | | if !M1! neq 0 (if !M2!==0 (set _!D1!=!End!&set/a Sp+=1) else (if !M2! gtr !M1! (set _!D1!=!End!&set/a Sp+=1))) | | ) | | if !#q!!qq!==14 (::1b#型 | | set D1=!Sz:~0,1! | | set D2=!Sz:~1,1! | | set _!D1!=!D2! | | if !lin! neq 0 (if %#% lss %#p% (ping/n 2 127.0>nul)) | | set/a Sp+=1 | | ) | | if !qq!==5 (for /l %%a in (1,1,%#%) do (set _!C:~%%a,1!=%#z%)) | | | | ::绘图 | | for /l %%a in (1,1,%#%) do (for %%b in (%#x% %#y% %#z%) do (set k%%b%%a=%$%)) | | set/a _%#x%_=#,_%#y%_=#,_%#z%_=# | | for /l %%a in (%#%,-1,1) do ( | | for /f %%b in ("!C:~%%a,1!") do ( | | for /f %%c in ("!_%%b!") do (set k%%c!_%%c_!=!$%%a! | | set/a _%%c_-=1) | | ) | | ) | | (cls&echo; | | for /l %%a in (1,1,%#%) do (echo; !k%#x%%%a! !k%#y%%%a! !k%#z%%%a!) | | echo; %$w% %$w% %$w% | | echo; !$%#x%! !$%#y%! !$%#z%! | | echo;已用步数%Sp%) | | goto :eof | | | | :Help 帮助 | | mode con cols=80 lines=25 | | (echo; | | echo; 批处理汉诺塔V1.2 Made By 路过 ^& 1152 | | echo; | | echo; 有三根柱子,从左到右命名为%#x%%#y%%#z%。最初所有的圆盘都位于第一根柱子%#x%上,将所有 | | echo;的圆盘移动到第三根柱子%#z%上则通关。有两个限制:①在小圆盘上不能放大圆盘②一次只 | | echo;能移动一个圆盘。以3个圆盘为例,左边是游戏刚开始的状态,右边为通关时的状态。 | | echo; | | echo; %C:~1,1% ^| %C:~1,1% | | echo; %C:~2,1%%C:~2,1%%C:~2,1% ^| %C:~2,1%%C:~2,1%%C:~2,1% | | echo; %C:~3,1%%C:~3,1%%C:~3,1%%C:~3,1%%C:~3,1% ^| %C:~3,1%%C:~3,1%%C:~3,1%%C:~3,1%%C:~3,1% | | echo; %C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1% %C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1% %C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1% ^| %C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1% %C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1% %C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1%%C:~0,1% | | echo; %#x% %#y% %#z% ^| %#x% %#y% %#z% | | echo; | | echo; 字符串“%C:~1%”中每个字符代表不同圆盘,字符重复的次数代表大小。提供以下移动指令 | | echo; | | echo; ①输入移动圆盘和目的地,如“%C:~1,1%%#y%”代表将圆盘%C:~1,1%移到%#y%柱上。 | | echo; ②输入圆盘所在柱和目的地,如“%#x%%#y%”代表将%#x%柱最上面的圆盘移到%#y%柱上。 | | echo; ③输入圆盘^|所在柱^|目的地,如“%C:~1,1%%#x%%#y%”代表将%#x%柱上的圆盘%C:~1,1%移到%#y%柱上。 | | echo; ④输入圆盘^|目的地^|#,如“%C:~1,1%%#y%#”代表将圆盘%C:~1,1%强制移到%#y%柱上【需开启作弊】。 | | echo; | | echo; 移动指令和命令需完整输入并回车,只有正确的指令才会被执行,错误的须重新输入 | | echo;&pause) | | | | :Win 加载窗口 | | set/a #=%1,wx=6*%1+18,wy=%1+10 | | mode con cols=%wx% lines=%wy% | | goto :eofCOPY |
|