happysxyf 发表于 2017-1-18 21:13:25

用二进制算法实现俄罗斯方块

本帖最后由 happysxyf 于 2017-1-18 21:34 编辑

俄罗斯方块是一款经典的方块游戏,在俄罗斯方块中存在多种旋转体系法则,比如下面图片中显示的两种:

这里,我们为了实现记录各种方块的形状,使用了抽象的二进制表
□□□□
□■■□
□□■■
□□□□
然后将表首尾相接成为链条。
实现方法:
REM 设置旋转体系:依次为TGM、SRS(第二代超级形码)
::set "SHAPE=0x159D0x89AB0x159D0x89AB0x126A0x48560x159A0x45260x926A0x456A0x15920x04560x48590x48590x48590x48590x59260x01560x59260x01560x41590x45960x15960x41560x156A0x41520x156A0x4152"
set "SHAPE=0x159D0x89AB0x26AE0x45670x01590x48560x159A0x45260x81590x456A0x15920x04560x48590x48590x48590x48590x48150x459A0x59260x01560x41590x45960x15960x41560x04590x85960x156A0x4152"

在图层的移动中,使用了图像动态显示技术,就是只处理变化的点,其实每次只需要处理4个点
实现方法
for %%p in (!POS!,!POS!,!POS!,!POS!) do (
        set/a "POS_X=(%%p>>2)+X+Dx,POS_Y=(%%p&0x3)+Y+Dy"
        set/a "CHE=P[!POS_X!][!POS_Y!]"
)

俄罗斯方块代码如下:
@echo off
::**************Happy's俄罗斯方块***********
REM 使用说明:
REM A左D右;W旋转;S加速下落;
REM Q退出;P暂停;方向键继续;
::**************Settings高级设置************
REM 设置窗体
title &setlocal enabledelayedexpansion
mode con cols=35 lines=25&color F0
REM 开启防闪烁,用于画质增强
set F1=1
REM 设置时钟T, 越小下落越快
set T=190
REM 默认皮肤
set "SKIN= ■"
REM 设置旋转体系:依次为TGM、SRS(第二代超级形码)
::set "SHAPE=0x159D0x89AB0x159D0x89AB0x126A0x48560x159A0x45260x926A0x456A0x15920x04560x48590x48590x48590x48590x59260x01560x59260x01560x41590x45960x15960x41560x156A0x41520x156A0x4152"
set "SHAPE=0x159D0x89AB0x26AE0x45670x01590x48560x159A0x45260x81590x456A0x15920x04560x48590x48590x48590x48590x48150x459A0x59260x01560x41590x45960x15960x41560x04590x85960x156A0x4152"
::**************方向控制台******************
if "%1"=="CONTROLP" (
        title &MODE CON cols=15 lines=1
        for /l %%i in (1,1,100000) do (
                set "KEY="
                for /f "delims=" %%a in ('xcopy /W . 2^>NUL') do (
                        if not defined KEY (
                                set "KEY=%%a"&set "KEY=!KEY:~-1!"
                                echo %%i!KEY!>key.ini&if /i "!KEY!"=="Q" (exit)
                        )
                )
        )
)
start "" "%~f0" CONTROLP
::**************先导程序********************
REM 准备元素
set/a "LEVEL=1,SCORE=0, RU=!random!%%7,RI=(!random!%%4)*6"
for /l %%N in (0,24,144) do (set/a "N=%%N/24"&set "SHAPE!N!=!SHAPE:~%%N,24!")
for /l %%N in (0,1,1   ) do (set "E%%N=!SKIN:~%%N,1!")
for /l %%N in (1,1,10) do (set "LINES=!LINES!━"   )
for /l %%N in (1,1,300 ) do (set "SPACE=!SPACE!"    )
REM 构建显存
:DISPLAY_RAM
for /l %%j in (0,1,21) do (
        set "#[%%j]=1"
        for /l %%i in (0,1,11) do (
                set/a "BOUNDARY=(%%i)*(%%i-11)*(%%j-21)"
                if !BOUNDARY! equ 0 (set "P[%%i][%%j]=1") else (set "P[%%i][%%j]=0")
        )
)
::**************主体程序********************
REM ~~~随机块体
:RANDOM_SHAPE
set/a "NU=RU,NI=RI, RU=!random!%%7,RI=(!random!%%4)*6, X=4,Y=1"
echo RW>key.ini
REM ~~~计数面板
set "V1=!LEVEL!    "
set "V2=!SCORE!    "
set "READM=LEVEL:!V1:~0,3!"
set "READM=SCORE:!V2:~0,3!"
set "READM=NEXT"
REM ~~~读取按键
:READKEY
set/a "Dx=0,Dy=0"
set/p KEY=<key.ini
if /i "!KEY:~-1!"=="P" (goto :READKEY)
if not "!PRE_KEY!"=="!KEY!" (
        set PRE_KEY=!KEY!
        if /i "!KEY:~-1!"=="A" (set "Dx=-1")
        if /i "!KEY:~-1!"=="D" (set "Dx=1" )
        if /i "!KEY:~-1!"=="W" (
                set "Cache=!SHAPE%NU%:~%NI%,6!"
                set/a "Xf=X,NI+=6,NI%%=24"
                REM ~~~16进制超级转码
                for /l %%j in (0,1,3) do (
                        set/a "POS[%%j]=Cache&0xF, Cache=Cache>>4" 2>NUL
                )
                if "!KEY!"=="RW" (
                        set "Cache2=!SHAPE%RU%:~%RI%,6!"
                        for /l %%J in (0,1,3) do (
                                set/a "RPOS[%%J]=Cache2&0xF, Cache2=Cache2>>4" 2>NUL
                                for /l %%I in (0,1,3) do (
                                        set "R[%%I][%%J]=0"
                                )
                        )       
                        for %%p in (!RPOS!,!RPOS!,!RPOS!,!RPOS!) do (
                                set/a "RPOS_X=%%p>>2,RPOS_Y=%%p&0x3"
                                set "R[!RPOS_X!][!RPOS_Y!]=1"
                        )
                        for /l %%J in (0,1,3) do (
                                set "TP="
                                for /l %%I in (0,1,3) do (
                                        set "TP=!TP!!R[%%I][%%J]!"
                                )
                                set "TP=!TP:0=%E0%!"
                                set "TP=!TP:1=%E1%!"
                                set/a "SN=%%J+8"
                                set "READM[!SN!]=!TP!"
                        )
                        echo WO>key.ini
                )
                goto :DATA_PROCESSING
        )
        if /i "!KEY:~-1!"=="Q" (exit)
)
if /i "!KEY:~-1!"=="S" (set "Dy=1"&goto :DATA_PROCESSING)
REM ~~~下落体系
if !Mark! equ 0 (
        set "Mark=1"
        set "T1=!time:~9,2!"
) else (
        set/a "TS=2!time:~9,2!-1!T1!"
        set/a "TS=1!TS:~-2!"
        if !TS! lss !T! (set "Dy=0") else (set/a "Dy=1,Mark=0")
)
if !Dx! equ 0 if !Dy! equ 0 (goto :READKEY)
REM ~~~数据处理
:DATA_PROCESSING
SETLOCAL
for %%p in (!POS!,!POS!,!POS!,!POS!) do (
        set/a "POS_X=(%%p>>2)+X+Dx,POS_Y=(%%p&0x3)+Y+Dy"
        set/a "CHE=P[!POS_X!][!POS_Y!]"
        if !CHE! equ 0 (
                set "P[!POS_X!][!POS_Y!]=1"
        ) else (
                if !Dx! neq 0 (
                        ENDLOCAL
                        goto :READKEY
                )
                if !Dy! equ 1 (
                        ENDLOCAL
                        if !Y! lss 2 (
                                echo GAME OVER!
                                ping -n 2 127.1>NUL
                                goto :DISPLAY_RAM
                        )
                        REM ~~~固化块体
                        set "POS_Y_MAX=0"
                        for %%P in (!POS!,!POS!,!POS!,!POS!) do (
                                set/a "POS_X=(%%P>>2)+X,POS_Y=(%%P&0x3)+Y"
                                if !POS_Y_MAX! lss !POS_Y! (set "POS_Y_MAX=!POS_Y!")
                                set "P[!POS_X!][!POS_Y!]=1"
                        )
                        REM ~~~关卡得分
                        for /l %%J in (!Y!,1,!POS_Y_MAX!) do (
                                set "TP="
                                for /l %%I in (1,1,10) do (
                                        set "TP=!TP!!P[%%I][%%J]!"
                                )
                                if "!TP!"=="1111111111" (
                                        set/a "SCORE+=10"
                                        set "#%%J=1"
                                        if !SCORE! equ 400 (
                                                for /l %%N in (!Y!,1,!POS_Y_MAX!) do (set "#%%N=")
                                                set/a "SCORE=0,LEVEL+=1,T-=10"
                                                goto :DISPLAY_RAM
                                        )
                                )
                        )
                        REM ~~~极品消行
                        for /l %%J in (20,-1,5) do (
                                if defined #%%J (
                                        set "#%%J="
                                        set/a "MarkJ=%%J-1, GK=1"
                                        for /l %%N in (1,1,3) do (
                                                if defined #!MarkJ! (set/a "MarkJ-=1")
                                        )
                                        set "#!MarkJ!=1"
                                        for /l %%I in (1,1,10) do (
                                                set/a "P[%%I][%%J]=P[%%I][!MarkJ!]"
                                        )
                                )
                        )
                        if defined GK (for /l %%J in (20,-1,5) do (set "#[%%J]=1")&set "GK=")
                        goto :RANDOM_SHAPE
                )
                if /i "!KEY:~-1!"=="W" (
                        ENDLOCAL
                        echo OW>key.ini
                        set/a "NI=(NI+12)%%24"
                        goto :READKEY
                )
        )
)
REM ~~~绘图引擎
if !F1! equ 1 (2>NUL echo         !SPACE!&set/p=<NUL) else (cls)
echo ┏%LINES%┓
for /l %%j in (0,1,5) do (set/a "MARK_Y=Y+%%j,#[!MARK_Y!]=1")
for /l %%j in (1,1,20) do (
        if not defined #[%%j] (
                echo;
        ) else (
                set "TP="
                for /l %%i in (1,1,10) do (set "TP=!TP!!P[%%i][%%j]!")
                set "TP=!TP:1=%E1%!"
                set "TP=!TP:0=%E0%!"
                echo ┃!TP!┃!READM[%%j]!
        )
)
echo ┗%LINES%┛
echoCopyRight@2016~2018 BY HAPPY
ENDLOCAL&for /l %%j in (1,1,20) do (set "#[%%j]=")
set/a "X+=Dx,Y+=Dy"
goto :READKEY
可执行代码下载
效果图:

页: [1]
查看完整版本: 用二进制算法实现俄罗斯方块