
我也發個批處理貪吃蛇玩玩界面比較簡陋,不太想優化了,主要是驗證下批處理下的按鍵檢測、光標定位、控制、Sleep等功能。本來想再做個人機對戰五子棋的,現在沒啥閑工夫,等空了再說。發貼有限制,腳本分兩部分發,直接復制合并到一起就行。上下左右方向鍵控制方向:
nclick="copycode($('code0'));">復制代碼
- :batch_start
- @echo off
- setlocal
- setlocal ENABLEDELAYEDEXPANSION
- rem 必須執行的步驟,初始化c#輔助程序
- call :init_cursor_control
- rem 腳本加在下面位置,其他地方不要動
- ::>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- :game_start
- for /F %%a in ('echo prompt $E^| cmd') do set _ESC=%%a
- set Wall_Max_X=50
- set Wall_Max_Y=30
- set /a Wall_Position_Max_X=%Wall_Max_X% - 1
- set /a Wall_Position_Max_Y=%Wall_Max_Y% - 1
- set Char_BlankSpace=
- set Char_Return=&echo;
- rem 0最快,數字越大越慢,設置為9時1秒一步,依次累推
- set Snake_Move_Speed=0
- set Enable_Write_Debug_log=1
- set Char_Wall=#
- set Wall_Str=
- set Snake_Body=O
- set Snake_Head=*
- set Snake_Tail=.
- set Snake_Init_Len=10
- set Snake_Str=
- set Snake_Direction=up
- set Snake_Head_X=0
- set Snake_Head_Y=0
- set Char_Food=F
- set Food_X=0
- set Food_Y=0
- set /a Snake_Move_Sleep_Time=%Snake_Move_Speed%*100
- call :set_cursor_visiable 0
- set /a WindowLines=%Wall_Max_Y% + 1
- mode con: cols=%Wall_Max_X% lines=%WindowLines%
- for /l %%l in (1,1,%Wall_Max_Y%) do (
- if %%l equ 1 (
- for /l %%c in (1,1,%Wall_Max_X%) do set Wall_Str=!Wall_Str!!Char_Wall!
- ) else if %%l equ %Wall_Max_Y% (
- set Wall_Str=!Wall_Str!!Char_Return!
- for /l %%c in (1,1,%Wall_Max_X%) do set Wall_Str=!Wall_Str!!Char_Wall!
- ) else (
- set Wall_Str=!Wall_Str!!Char_Return!
- set Wall_Str=!Wall_Str!!Char_Wall!
- set /a BlankCount=%Wall_Max_X% - 2
- for /l %%c in (1,1,!BlankCount!) do set Wall_Str=!Wall_Str!!Char_BlankSpace!
- set Wall_Str=!Wall_Str!!Char_Wall!
- )
- )
- echo %Wall_Str%
- set /a Snake_Init_X = (%Wall_Max_X% - 2) / 2
- set /a Snake_Init_Y = (%Wall_Max_Y% - 2 - %Snake_Init_Len%) / 2
- set /a Snake_End_Y = %Snake_Init_Y% + %Snake_Init_Len% - 1
- set /a Snake_Head_X = %Snake_Init_X%
- set /a Snake_Head_Y = %Snake_Init_Y%
- for /l %%l in (!Snake_Init_Y!,1,!Snake_End_Y!) do (
- call :set_cursor_position !Snake_Init_X! %%l
- if %%l equ !Snake_Init_Y! (
- echo !Snake_Head!
- ) else if %%l equ !Snake_End_Y! (
- echo !Snake_Tail!
- ) else (
- echo !Snake_Body!
- )
- call :add_position_to_snake_str_tail !Snake_Init_X! %%l
- )
- call :random_gen_food
- :snake_loop
- call :sleep_until_key_press %Snake_Move_Sleep_Time% pressed_key
- if %pressed_key% equ UpArrow (if %Snake_Direction% neq down set Snake_Direction=up)
- if %pressed_key% equ DownArrow (if %Snake_Direction% neq up set Snake_Direction=down)
- if %pressed_key% equ LeftArrow (if %Snake_Direction% neq right set Snake_Direction=left)
- if %pressed_key% equ RightArrow (if %Snake_Direction% neq left set Snake_Direction=right)
- set /a snake_last_head_x = %Snake_Head_X%
- set /a snake_last_head_y = %Snake_Head_Y%
- if %Snake_Direction% equ up set /a Snake_Head_Y = %Snake_Head_Y% - 1
- if %Snake_Direction% equ down set /a Snake_Head_Y = %Snake_Head_Y% + 1
- if %Snake_Direction% equ left set /a Snake_Head_X = %Snake_Head_X% - 1
- if %Snake_Direction% equ right set /a Snake_Head_X = %Snake_Head_X% + 1
- call :get_snake_tail_position snake_tail_x snake_tail_y
- call :check_position_in_snake %Snake_Head_X% %Snake_Head_Y% in_snake
- if %snake_tail_x% equ %Snake_Head_X% (
- if %snake_tail_y% equ %Snake_Head_Y% (
- set in_snake=0
- )
- )
- if %in_snake% equ 1 (
- call :show_game_over
- pause >nul
- goto :game_start
- )
- set snake_in_wall=0
- if %Snake_Head_X% equ 0 set snake_in_wall=1
- if %Snake_Head_X% equ %Wall_Position_Max_X% set snake_in_wall=1
- if %Snake_Head_Y% equ 0 set snake_in_wall=1
- if %Snake_Head_Y% equ %Wall_Position_Max_Y% set snake_in_wall=1
- if %snake_in_wall% equ 1 (
- call :show_game_over
- pause >nul
- goto :game_start
- )
- set /a food_in_snake=0
- if %Snake_Head_X% equ %Food_X% (
- if %Snake_Head_Y% equ %Food_Y% (
- set /a food_in_snake=1
- )
- )
- if %food_in_snake% equ 0 (
- call :snake_tail_ahead
- )
- call :set_cursor_position %snake_last_head_x% %snake_last_head_y% & echo %Snake_Body%
- call :set_cursor_position %Snake_Head_X% %Snake_Head_Y% & echo %Snake_Head%
- ::call :write_log before add Snake_Str=%Snake_Str%
- call :add_position_to_snake_str_head %Snake_Head_X% %Snake_Head_Y%
- ::call :write_log after add Snake_Str=%Snake_Str%
- if %food_in_snake% equ 1 (
- call :random_gen_food
- )
- goto :snake_loop
- :show_game_over
- set /a x = (%Wall_Max_X% - 2 - 5) / 2
- set /a y = (%Wall_Max_Y% - 2) / 2
- call :set_cursor_position %x% %y%
- echo Game Over
- goto :eof
- :snake_tail_ahead
- call :get_snake_tail_position snake_tail_x snake_tail_y
- call :set_cursor_position %snake_tail_x% %snake_tail_y% & echo.%Char_BlankSpace%
- ::call :write_log before del Snake_Str=%Snake_Str%
- call :del_position_from_snake_str %snake_tail_x% %snake_tail_y%
- ::call :write_log after del Snake_Str=%Snake_Str%
- call :get_snake_tail_position snake_tail_x snake_tail_y
- call :set_cursor_position %snake_tail_x% %snake_tail_y% & echo.%Snake_Tail%
- goto :eof
- :random_gen_food
- set /a Food_X = 1 + (%RANDOM% %% (%Wall_Max_X% - 2))
- set /a Food_Y = 1 + (%RANDOM% %% (%Wall_Max_Y% - 2))
- call :check_position_in_snake %Food_X% %Food_Y% in_snake
- if %in_snake% equ 1 (goto :random_gen_food)
- call :set_cursor_position %Food_X% %Food_Y% & echo %Char_Food%
- goto :eof
- :sleep_until_key_press
- call :bat_helper_with_output sleeputilkeypress %~1
- for /f tokens=1* delims=,; %%a in (%bat_helper_output%) do (
- set %~2=%%a
- )
- goto :eof
- :check_position_in_snake
- call :get_position_string %~1 %~2 position_string
- echo %Snake_Str% | findstr /C:%position_string% >nul
- if %errorlevel% equ 0 (set %~3=1) else (set %~3=0)
- goto :eof
- :get_position_string
- set _x=%~1
- set _y=%~2
- if %_x% lss 10 (set _x=0%_x%)
- if %_y% lss 10 (set _y=0%_y%)
- set %~3=[%_x%,%_y%]
- goto :eof
- :get_position_from_string
- for /f tokens=1,2 delims=,[] %%a in (%~1) do (
- set x=%%a
- set y=%%b
- if !x:~0,1! equ 0 (set /a %~2=!x:~1,1!) else (set /a %~2=!x!)
- if !y:~0,1! equ 0 (set /a %~3=!y:~1,1!) else (set /a %~3=!y!)
- )
- goto :eof
- :get_snake_tail_position
- set snake_tail_position_str=%Snake_Str:~-7%
- call :get_position_from_string %snake_tail_position_str% %~1 %~2
- goto :eof
- :add_position_to_snake_str_head
- call :get_position_string %~1 %~2 position_string
- set Snake_Str=!position_string!!Snake_Str!
- goto :eof
- :add_position_to_snake_str_tail
- call :get_position_string %~1 %~2 position_string
- set Snake_Str=!Snake_Str!!position_string!
- goto :eof
- :del_position_from_snake_str
- call :get_position_string %~1 %~2 position_string
- set Snake_Str=!Snake_Str:%position_string%=!
- goto :eof
- :write_log
- if %Enable_Write_Debug_log% equ 0 goto :eof
- echo %date% %time% %* >> debug.log
- goto :eof
- rem 腳本加在上面位置,其他地方不要動
- ::<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- rem 腳本最后退出位置,下面的代碼不要更改
- :batch_end
- endlocal
- exit /b %errorlevel%
- rem 獲取毫秒時間戳
- :gettimestamp
- call :bat_helper_with_output gettimestamp
- for /f tokens=1 delims= %%a in (%bat_helper_output%) do (set %~1=%%a)
- goto :eof
- rem 獲取光標是否可見
- :get_cursor_visiable
- call :bat_helper getcursorvisiable
- set /a return_code=%errorlevel%
- ::echo getcursorvisiable return_code=%errorlevel%
- if %return_code%==0 set /a %~1=0
- if %return_code%==1 set /a %~1=1
- goto :eof
- rem 設置光標是否可見
- :set_cursor_visiable
- call :bat_helper setcursorvisiable %~1
- ::echo setcursorvisiable return_code=%errorlevel%
- goto :eof
- rem 獲取backspace回退鍵
- :get_back_space
- for /F %%a in ('prompt $h & for %%b in (1) do rem')do set %~1=%%a
- goto :eof
- rem 設置光標位置
- :set_cursor_position
- set /a x=%~2 + 1
- set /a y=%~1 + 1
- <nul set /p =%_ESC%[!x!;!y!H
- ::call :bat_helper setcursorposition %~1 %~2
- goto :eof
- rem 獲取當前窗口光標位置以及窗口尺寸
- :get_cursor_info
- call :bat_helper_with_output getcursorposition
- for /f tokens=1,2,3,4 delims=,; %%a in (%bat_helper_output%) do (set %~1=%%a & set %~2=%%b & set %~3=%%c & set %~4=%%d)
- goto :eof
- rem 調用helper程序,并且將helper程序輸出保存到bat_helper_output,返回值保存到bat_helper_errorlevel
- :bat_helper_with_output
- set bat_helper_output= <nul
- for /f delims= %%i in ('%bat_helper_exe_file_path% %*') do (set bat_helper_errorlevel=%errorlevel% & set bat_helper_output=%%i & goto :eof)
- set bat_helper_errorlevel=%errorlevel%
- goto :eof
- rem 調用helper程序,helper程序輸出直接到終端,返回值保存到bat_helper_errorlevel
- :bat_helper
- %bat_helper_exe_file_path% %*
- set bat_helper_errorlevel=%errorlevel%
- goto :eof
- rem 初始化c#輔助程序,如果未找到就進行編譯
- :init_cursor_control
- :: find csc.exe
- set csc=
- for /r %SystemRoot%Microsoft.NETframework %%# in (*csc.exe) doset csc=%%#
- if not exist %csc% (
- echo no .net framework installed
- exit /b 10
- )
- set bat_helper_exe_file_path=%tmp%bat_helper.exe
- if not exist %bat_helper_exe_file_path% (
- call :gen_helper_csharp_source
- call %csc% /nologo /warn:0 /out:%bat_helper_exe_file_path% %tmp%bat_helper.cs || (
- exit /b %errorlevel%
- )
- )
- goto :eof
- rem 從此腳本中獲取c#源碼
- :gen_helper_csharp_source
- for /f tokens=1,2 delims=: %%n in ('findstr /N /C:helper_csharp_start %~dpsfnx0') do (
- ::echo %%n %%o
- if %%o==helper_csharp_start (
- set /a helper_csharp_start_line=%%n+1
- ::echo helper_csharp_start_line=!helper_csharp_start_line!
- more +!helper_csharp_start_line! %~dpsfnx0 > %tmp%bat_helper.cs
- goto :eof
- )
- )
- goto :eof

