2048: Difference between revisions

Content added Content deleted
m (→‎{{header|Phix}}: added syntax colouring the hard way)
(→‎{{header|Batch File}}: highly improved version!)
Line 2,779: Line 2,779:


=={{header|Batch File}}==
=={{header|Batch File}}==
<lang dos>::2048 Game Task from RosettaCode.org
<lang dos>:: 2048 Game Task from RosettaCode
::Batch File Implementation
:: Batch File Implementation v2.0


@echo off
@echo off
setlocal enabledelayedexpansion
setlocal enabledelayedexpansion
cls


rem initialization
:begin_game
:begin_game
%== Set variables ==%
set "size=4" %== board size ==%
set "score=0"
set "score=0" %== current score ==%
set "won=0"
set "won=0" %== boolean for winning ==%
set "target=2048" %== as the game title says ==%
set "SUP_score=0"
for /l %%A in (1,1,4) do for /l %%B in (1,1,4) do set /a "X_%%A%%B=0"
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
call :addtile
call :addtile


%== Main game loop ==%
rem main game loop
:main_loop
:main_loop
set "changed=0"
call :display
echo(
echo Keys: WASD (Slide Movement^), N (New game^), P (Exit^)

%== Get Keypress ==%
set "key="
for /f "delims=" %%? in ('xcopy /w "%~f0" "%~f0" 2^>nul') do if not defined key set "key=%%?"
set "key=%key:~-1%"

%== Process keypress ==%
if /i "!key!"=="W" (
for /l %%? in (1,1,4) do call :slide X_1%%? X_2%%? X_3%%? X_4%%?
)
if /i "!key!"=="A" (
for /l %%? in (1,1,4) do call :slide X_%%?1 X_%%?2 X_%%?3 X_%%?4
)
if /i "!key!"=="S" (
for /l %%? in (1,1,4) do call :slide X_4%%? X_3%%? X_2%%? X_1%%?
)
if /i "!key!"=="D" (
for /l %%? in (1,1,4) do call :slide X_%%?4 X_%%?3 X_%%?2 X_%%?1
)
if /i "!key!"=="N" goto :begin_game
if /i "!key!"=="P" exit /b

%== Check if the board changed ==%
if %changed% neq 0 call :addtile

%== Check if already won ==%
if %won% equ 1 (
set "msg=Nice one... You WON^!^!"
goto :gameover
)

%== Check for lose condition ==%
set /a "real_blanks=blank_count-1"
if %real_blanks% leq 0 (
for /l %%A in (1,1,4) do for /l %%B in (1,1,4) do set "TRY_%%A%%B=!X_%%A%%B!"
set "TRY_changed=%changed%" & set "changed=0"
set "SUP_score=1"
for /l %%? in (1,1,4) do call :slide TRY_%%?1 TRY_%%?2 TRY_%%?3 TRY_%%?4
for /l %%? in (1,1,4) do call :slide TRY_1%%? TRY_2%%? TRY_3%%? TRY_4%%?
if !changed! equ 0 (
set "msg=No moves are possible... Game Over :("
goto :gameover
) else (set "changed=!TRY_changed!" & set "SUP_score=0")
)
goto main_loop


::~~~~~~~~~~~~~~~~~~~~ Sub Procedures ~~~~~~~~~~~~~~~~~~~~::
%== Game Over xD ==%
:gameover
call :display
call :display
echo(
echo(
echo(Keys: WASD (Slide Movement), N (New game), P (Exit)
echo(!msg!
echo(
echo(Keys: N (New game^), P (Exit^)


rem get keypress trick
:key_loop
set "key="
set "key="
for /f "delims=" %%? in ('xcopy /w "%~f0" "%~f0" 2^>nul') do if not defined key set "key=%%?"
for /f "delims=" %%? in ('xcopy /w "%~f0" "%~f0" 2^>nul') do if not defined key set "key=%%?"
set "key=%key:~-1%"
set "key=%key:~-1%"
if /i "!key!"=="N" goto :begin_game
if /i "!key!"=="P" exit /b
goto :key_loop


set "changed=0" %== boolean for changed board ==%
%== The main slider of numbers in tiles ==%
set "valid_key=0" %== boolean for pressing WASD ==%
:slide
rem process keypress
set "next="
if /i "!key!" equ "W" (set "valid_key=1" & call :slide "C" "1,1,%size%" "X")
set "slide_1="
if /i "!key!" equ "A" (set "valid_key=1" & call :slide "R" "1,1,%size%" "X")
set "slide_2="
if /i "!key!" equ "S" (set "valid_key=1" & call :slide "C" "%size%,-1,1" "X")
for %%? in (%*) do if !%%?! neq 0 set "slide_1=!slide_1! !%%?!"
if /i "!key!" equ "D" (set "valid_key=1" & call :slide "R" "%size%,-1,1" "X")
for %%? in (!slide_1!) do (
if /i "!key!" equ "N" goto begin_game
set "scan=%%?"
if "!scan!"=="!next!" (
if /i "!key!" equ "P" exit /b 0
if "%valid_key%" equ "0" goto main_loop
set /a "next*=2"

if !SUP_score! equ 0 set /a "score+=!next!"
rem check if the board changed
%== WINNING CONDITION!!! ==%
if %changed% neq 0 call :addtile
if "!next!" equ "2048" set "won=1"

set "scan="
rem check for win condition
)
if %won% equ 1 (
set "slide_2=!slide_2! !next!"
set "next=!scan!"
set "msg=Nice one... You WON^!^!"
goto gameover
)
)

set "slide_2=!slide_2! !next!"
rem check for lose condition
for /l %%? in (1,1,4) do set "final_%%?=0"
if %blank_count% equ 0 (
set "cnt=0" & for %%? in (!slide_2!) do if !cnt! lss 4 (
for /l %%R in (1,1,%size%) do for /l %%C in (1,1,%size%) do set "LX_%%R_%%C=!X_%%R_%%C!"
set /a "cnt+=1"
set "save_changed=%changed%" & set "changed=0" %== save actual changed for test ==%
set "final_!cnt!=%%?"
call :slide "C" "1,1,%size%" "LX"
)
call :slide "R" "1,1,%size%" "LX"
if not "!%1!!%2!!%3!!%4!"=="!final_1!!final_2!!final_3!!final_4!" set "changed=1"
set "cnt=0" & for %%? in (%*) do (
if !changed! equ 0 (
set "msg=No moves are possible... Game Over :("
set /a "cnt+=1"
goto gameover
set /a "%%?=final_!cnt!"
) else set "changed=!save_changed!"
)
)
goto :EOF
goto main_loop


%== Add number to tile ==%
rem add number to a random blank tile
:addtile
:addtile
set "blank_count=0" %== blank tile counter ==%
set "blank_list="
rem create pseudo-array blank_tiles
set "blank_count=0"
for /l %%A in (1,1,4) do for /l %%B in (1,1,4) do (
for /l %%R in (1,1,%size%) do (
for /l %%C in (1,1,%size%) do (
if !X_%%A%%B! equ 0 (
if !X_%%R_%%C! equ 0 (
set "blank_list=!blank_list!X_%%A%%B"
set /a blank_count+=1
set "blank_tiles[!blank_count!]=X_%%R_%%C"
set /a "blank_count+=1"
)
)
)
)
set /a "pick_tile=(%random% %% %blank_count%)*4"
)
set /a "rnd=%random%%%10+1"
if %blank_count% equ 0 goto :EOF
set "tile_new=!blank_list:~%pick_tile%,4!"
set /a "pick_tile=%random%%%%blank_count%"
if %rnd%==5 (set !tile_new!=4) else (set !tile_new!=2)
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
goto :EOF


%== Display the table ==%
rem display the board
:display
:display
cls
cls
echo 2048 Game in Batch
echo(2048 Game in Batch
echo(
echo(
set "wall=+"
for /l %%A in (1,1,4) do (
for /l %%B in (1,1,4) do (
for /l %%C in (1,1,%size%) do set "wall=!wall!----+"
for /l %%R in (1,1,%size%) do (
set "DX_%%A%%B=!X_%%A%%B!"
set "disp_row=|"
if !tile_new!==X_%%A%%B (set "DX_%%A%%B= +!X_%%A%%B!") else (
for /l %%C in (1,1,%size%) do (
if !X_%%A%%B! lss 1000 set "DX_%%A%%B= !DX_%%A%%B!"
if !X_%%A%%B! lss 100 set "DX_%%A%%B= !DX_%%A%%B!"
if "!new_tile!" equ "X_%%R_%%C" (set "DX_%%R_%%C= +!X_%%R_%%C!") else (
if !X_%%A%%B! lss 10 set "DX_%%A%%B= !DX_%%A%%B!"
set "DX_%%R_%%C=!X_%%R_%%C!"
if !X_%%A%%B! equ 0 set "DX_%%A%%B= "
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= "
echo +----+----+----+----+
)
echo ^|!DX_%%A1!^|!DX_%%A2!^|!DX_%%A3!^|!DX_%%A4!^|
set "disp_row=!disp_row!!DX_%%R_%%C!|"
)
echo(%wall%
echo(!disp_row!
)
)
echo(%wall%
echo +----+----+----+----+
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!"
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(
echo(Press any key to exit . . .
echo Score: %score%
pause>nul
goto :EOF</lang>
exit /b 0</lang>
{{out}}
{{out}}
<pre>2048 Game in Batch
<pre>2048 Game in Batch