173 lines
5.3 KiB
Batchfile
173 lines
5.3 KiB
Batchfile
:: 2048 Game Task from RosettaCode
|
|
:: Batch File Implementation v2.0.1
|
|
|
|
@echo off
|
|
setlocal enabledelayedexpansion
|
|
|
|
rem initialization
|
|
:begin_game
|
|
set "size=4" %== board size ==%
|
|
set "score=0" %== current score ==%
|
|
set "won=0" %== boolean for winning ==%
|
|
set "target=2048" %== as the game title says ==%
|
|
for /l %%R in (1,1,%size%) do for /l %%C in (1,1,%size%) do set "X_%%R_%%C=0"
|
|
|
|
rem add two numbers in the board
|
|
call :addtile
|
|
call :addtile
|
|
|
|
rem main game loop
|
|
:main_loop
|
|
call :display
|
|
echo(
|
|
echo(Keys: WASD (Slide Movement), N (New game), P (Exit)
|
|
|
|
rem get keypress trick
|
|
set "key="
|
|
for /f "delims=" %%? in ('xcopy /w "%~f0" "%~f0" 2^>nul') do if not defined key set "key=%%?"
|
|
set "key=%key:~-1%"
|
|
|
|
set "changed=0" %== boolean for changed board ==%
|
|
set "valid_key=0" %== boolean for pressing WASD ==%
|
|
rem process keypress
|
|
if /i "!key!" equ "W" (set "valid_key=1" & call :slide "C" "1,1,%size%" "X")
|
|
if /i "!key!" equ "A" (set "valid_key=1" & call :slide "R" "1,1,%size%" "X")
|
|
if /i "!key!" equ "S" (set "valid_key=1" & call :slide "C" "%size%,-1,1" "X")
|
|
if /i "!key!" equ "D" (set "valid_key=1" & call :slide "R" "%size%,-1,1" "X")
|
|
if /i "!key!" equ "N" goto begin_game
|
|
if /i "!key!" equ "P" exit /b 0
|
|
if "%valid_key%" equ "0" goto main_loop
|
|
|
|
rem check if the board changed
|
|
if %changed% neq 0 call :addtile
|
|
|
|
rem check for win condition
|
|
if %won% equ 1 (
|
|
set "msg=Nice one... You WON^!^!"
|
|
goto gameover
|
|
)
|
|
|
|
rem check for lose condition
|
|
if %blank_count% equ 0 (
|
|
for /l %%R in (1,1,%size%) do for /l %%C in (1,1,%size%) do set "LX_%%R_%%C=!X_%%R_%%C!"
|
|
set "save_changed=%changed%" & set "changed=0" %== save actual changed for test ==%
|
|
call :slide "C" "1,1,%size%" "LX"
|
|
call :slide "R" "1,1,%size%" "LX"
|
|
if !changed! equ 0 (
|
|
set "msg=No moves are possible... Game Over :("
|
|
goto gameover
|
|
) else set "changed=!save_changed!"
|
|
)
|
|
goto main_loop
|
|
|
|
rem add number to a random blank tile
|
|
:addtile
|
|
set "blank_count=0" %== blank tile counter ==%
|
|
set "new_tile=" %== clearing ==%
|
|
rem create pseudo-array blank_tiles
|
|
for /l %%R in (1,1,%size%) do (
|
|
for /l %%C in (1,1,%size%) do (
|
|
if !X_%%R_%%C! equ 0 (
|
|
set "blank_tiles[!blank_count!]=X_%%R_%%C"
|
|
set /a "blank_count+=1"
|
|
)
|
|
)
|
|
)
|
|
if %blank_count% equ 0 goto :EOF
|
|
set /a "pick_tile=%random%%%%blank_count%"
|
|
set "new_tile=!blank_tiles[%pick_tile%]!"
|
|
set /a "rnd_newnum=%random%%%10"
|
|
rem 10% chance new number is 4, 90% chance it's 2
|
|
if %rnd_newnum% equ 5 (set "%new_tile%=4") else (set "%new_tile%=2")
|
|
set /a "blank_count-=1" %== to be used for checking lose condition ==%
|
|
goto :EOF
|
|
|
|
rem display the board
|
|
:display
|
|
cls
|
|
echo(2048 Game in Batch
|
|
echo(
|
|
set "wall=+"
|
|
for /l %%C in (1,1,%size%) do set "wall=!wall!----+"
|
|
for /l %%R in (1,1,%size%) do (
|
|
set "disp_row=|"
|
|
for /l %%C in (1,1,%size%) do (
|
|
if "!new_tile!" equ "X_%%R_%%C" (set "DX_%%R_%%C= +!X_%%R_%%C!") else (
|
|
set "DX_%%R_%%C=!X_%%R_%%C!"
|
|
if !X_%%R_%%C! lss 1000 set "DX_%%R_%%C= !DX_%%R_%%C!"
|
|
if !X_%%R_%%C! lss 100 set "DX_%%R_%%C= !DX_%%R_%%C!"
|
|
if !X_%%R_%%C! lss 10 set "DX_%%R_%%C= !DX_%%R_%%C!"
|
|
if !X_%%R_%%C! equ 0 set "DX_%%R_%%C= "
|
|
)
|
|
set "disp_row=!disp_row!!DX_%%R_%%C!|"
|
|
)
|
|
echo(%wall%
|
|
echo(!disp_row!
|
|
)
|
|
echo(%wall%
|
|
echo(
|
|
echo(Score: %score%
|
|
goto :EOF
|
|
|
|
rem the main slider of numbers in tiles
|
|
:slide
|
|
rem %%A and %%B are used here because sliding direction is variable
|
|
for /l %%A in (1,1,%size%) do (
|
|
rem first slide: removing blank tiles in the middle
|
|
set "slide_1="
|
|
set "last_blank=0" %== boolean if last tile is blank ==%
|
|
for /l %%B in (%~2) do (
|
|
if "%~1" equ "R" (set "curr_tilenum=!%~3_%%A_%%B!"
|
|
) else if "%~1" equ "C" (set "curr_tilenum=!%~3_%%B_%%A!")
|
|
if !curr_tilenum! equ 0 (set "last_blank=1") else (
|
|
set "slide_1=!slide_1! !curr_tilenum!"
|
|
if !last_blank! equ 1 set "changed=1"
|
|
set "last_blank=0"
|
|
)
|
|
)
|
|
rem second slide: addition of numbered tiles
|
|
rem slide_2 would be pseudo-array
|
|
set "slide_2_count=0"
|
|
set "skip=1" %== boolean for skipping after previous summing ==%
|
|
if "!slide_1!" neq "" for %%S in (!slide_1! 0) do (
|
|
if !skip! equ 1 (
|
|
set "prev_tilenum=%%S" & set "skip=0"
|
|
) else if !skip! equ 0 (
|
|
if %%S equ !prev_tilenum! (
|
|
set /a "sum=%%S+!prev_tilenum!"
|
|
if "%~3" equ "X" set /a "score+=sum"
|
|
set "changed=1" & set "skip=1"
|
|
rem check for winning condition!
|
|
if !sum! equ !target! set "won=1"
|
|
) else (
|
|
set "sum=!prev_tilenum!"
|
|
set "prev_tilenum=%%S"
|
|
)
|
|
set "slide_2[!slide_2_count!]=!sum!"
|
|
set /a "slide_2_count+=1"
|
|
)
|
|
)
|
|
rem new values of tiles
|
|
set "slide_2_run=0" %== running counter for slide_2 ==%
|
|
for /l %%B in (%~2) do (
|
|
if "%~1" equ "R" (set "curr_tile=%~3_%%A_%%B"
|
|
) else if "%~1" equ "C" (set "curr_tile=%~3_%%B_%%A")
|
|
for %%? in ("!slide_2_run!") do (
|
|
if %%~? lss !slide_2_count! (set "!curr_tile!=!slide_2[%%~?]!"
|
|
) else (set "!curr_tile!=0")
|
|
)
|
|
set /a "slide_2_run+=1"
|
|
)
|
|
)
|
|
goto :EOF
|
|
|
|
rem game over xD
|
|
:gameover
|
|
call :display
|
|
echo(
|
|
echo(!msg!
|
|
echo(
|
|
echo(Press any key to exit . . .
|
|
pause>nul
|
|
exit /b 0
|