471字节的俄罗斯方块

dwing的作品,TASM编译

 

;471 bytes GAME! By Dwing
;Only for DOS/Win9x/WinME/DosBox(注意不能直接在Win2000以上系统运行)
.model tiny
.386
.code
$shape  equ 008h
$backg  equ 0dbh
$up     equ 72
$left   equ 75
$right  equ 77
$down   equ 80

        org 100h
start:  int 10h                 ;设置显示模式0(40*25*16色字符模式)
        push 0b800h             ;字符缓冲区段=b800h
        pop ds                  ;ds=b800h
        push ds
        pop es                  ;es=b800h
        xchg ax,di              ;di=0000h
        mov ax,0700h+$backg     ;开始画边框,ax=字符(0dbh)及属性(灰色)
        mov cx,ax               ;cx=数量
        rep stosw               ;覆盖全屏
        mov ax,0e30h            ;开始画数码框,ax=字符('0')及属性(黄色)
        mov cl,6                ;cl=数字个数(6)
        mov di,2*(40*23+17)     ;di=数字显示屏幕偏移位置
        rep stosw               ;显示数码
        xor ax,ax               ;开始画中间空框,ax=空字符
        mov di,2*(40*2+15)      ;di=空框第一行屏幕偏移位置
@nextbl:mov cl,10               ;cl=每行块数(10)
        rep stosw               ;画一行空格
        add di,2*(15+15)        ;计算下一行屏幕偏移位置
        cmp di,2*(40*22+15)     ;判断是否画完最后一行(共20行)
        jb  short @nextbl       ;没画完则循环

@rernd: in  al,40h              ;开始随机选择方块类型,al=时间随机值
        and al,0111b            ;al只取0-7
        jz  short @rernd        ;如果是0则重新选择(只选1-7,共7种)
        dec ax                  ;1-7变为0-6
        mov bx,2*(40*2+15+4)    ;方块起始屏幕偏移位置
        jnz short @t            ;如果不是0(长条形方块需特殊处理)则跳转
        mov bx,2*(40+15+4)      ;长条形方块的起始屏幕偏移位置上移一行
@t:     xchg ax,bp              ;bp=方块起始屏幕偏移位置

        call @isok              ;判断新产生的方块能否放置
        jz  short @goon         ;能放置则跳转
@end:   call @dispb             ;不能放置情况:先显示方块
        push cs
        pop ds                  ;ds=当前程序段
        lea dx,msg1             ;dx="GAMEOVER"信息地址
        mov ah,9                ;ah=9(显示字符串)
        int 21h                 ;显示"GAMEOVER"
@esc:   in  al,60h              ;读键盘
        dec al                  ;"ESC"扫描码=1
        jnz short @esc          ;如果没有按"ESC"则跳回继续读键盘
        mov ax,3                ;ax=DOS默认显示模式(3)
        int 10h                 ;设置显示模式3(80*25*16色字符模式)
        retn                    ;退出

@goon:  mov cl,0ffh             ;新方块能放置情况:先进入延时状态
        cmp cl,40h              ;cl=循环等待次数
        jae short @wait         ;确认cl不小于40
        mov cl,40h
@wait:  call @dispb             ;显示当前新方块
        push cx                 ;进入等待状态
        xor cx,cx               ;cx=等待时间(微秒)低字
        mov dx,1000             ;dx=等待时间(微秒)高字
        mov ah,86h
        int 15h                 ;等待
        pop cx                  ;退出等待状态

@t4:    mov ah,1
        int 16h                 ;判断键盘缓冲区是否有字符

        popa                    ;退出消除一行部分
        inc dx                  ;分数基值+1
        add dh,dl               ;累计当前分数
@skip:  add si,2*40             ;下一行偏移位置
        cmp si,2*(40*22)        ;判断是否判断完所有行
        jb  short @nextl        ;没有则继续下一行判断
        and dx,dx               ;判断是否有得到当前的分数
        jz  short @t_           ;没有则跳过
@t00:   mov di,2*(40*23+21)     ;数码位屏幕偏移位置(第2位)
@t0:    mov byte ptr[di],30h    ;置0
        dec di                  ;进一位(倒退2个字节长度)
        dec di
        cmp di,2*(40*23+20)     ;判断是否进入第3位
        jnz short @t000         ;如果不是则跳过
        dec byte ptr cs:[@goon+1];每100分等待次数减1(加速)
@t000:  inc byte ptr[di]        ;当前数码位+1
        cmp byte ptr[di],3ah    ;判断数码位是否超过9
        jz  short @t0           ;如果是则跳转(进位)
        dec dh                  ;当前分数累计值-1
        jnz short @t00          ;如果分数没加完则继续累加
@t_:    jmp @rernd              ;继续产生下一个新方块

@isok:  mov si,bp               ;判断是否能放置方块子模块
        shl si,2                ;si=方块形状标号*4(占4个字节)
        xor ax,ax
        mov dx,ax               ;ax=dx=0
        add si,offset bks       ;si=方块形状位置描述指针
        push cx                 ;保存cx
        mov cl,4                ;cl=方块数(4)
@nextb: db 2eh                  ;lodsb cs: (al<=cs:[si])
        lodsb                   ;载入方块位置描述(位置偏移)
        mov di,ax
        or  dx,[di+bx]          ;判断小方块是否冲突
        loop @nextb             ;继续判断下一个位置描述
        pop cx                  ;恢复cx
        retn                    ;返回

@dispb: mov al,$shape           ;显示方块子模块,al=方块形状标号
        mov ah,cs:[bp+bkc]      ;ah=方块颜色值
@disp:  mov si,bp
        shl si,2                ;si=方块形状标号*4(占4个字节)
        push cx                 ;保存cx
        mov cl,4                ;cl=方块数(4)
@nextb_:movzx di,cs:[si+bks]    ;取方块描述
        mov [di+bx],ax          ;显示一个小方块
        inc si                  ;si=下一个位置描述
        loop @nextb_            ;继续画下一个小方块
        pop cx                  ;恢复cx
        retn                    ;返回

bkc     db  2                   ;方块颜色值
        db  9,12,13,14, 11,10
        db  9,9,9,      12,13
        db  11,11,11,   10,10,10
        db  2
bkv     db  18                  ;方块形状链表
        db  7,10,11,4,  12,15
        db  8,9,1,      2,3
        db  13,14,5,    16,17,6
        db  0                   ;下面是方块形状描述
bks     db 40*2,41*2,42*2,43*2  ;  ****                 0
        db  1*2,40*2,41*2,42*2  ;   *     **   **    ** 基本形状*7
        db  1*2, 2*2,40*2,41*2  ;  ***   **     **   ** 1-4
        db  0*2, 1*2,41*2,42*2  ;
        db  0*2, 1*2,40*2,41*2  ;
        db  0*2,40*2,41*2,42*2  ;    *       *      
        db  2*2,40*2,41*2,42*2  ;    ***   ***          5-6
        db  1*2,40*2,41*2,81*2  ;   *         *         扩展形状*12
        db 40*2,41*2,42*2,81*2  ;  **   ***   **
        db  1*2,41*2,42*2,81*2  ;   * *  *  * *         7-9
        db  0*2,40*2,41*2,81*2  ;     **   **
        db  1*2,40*2,41*2,80*2  ;      *   *            10-11
        db  1*2,41*2,80*2,81*2  ;    *        **  
        db 40*2,41*2,42*2,82*2  ;    *   ***  *
        db  1*2, 2*2,41*2,81*2  ;   **     *  *         12-14
        db  0*2, 1*2,41*2,81*2  ;*  **        *
        db 40*2,41*2,42*2,80*2  ;*   *   ***  *
        db  1*2,41*2,81*2,82*2  ;*   *   *    **        15-17
        db  2*2,42*2,82*2,122*2 ;*                      18
msg1    db 9,9,'GAMEOVER',9,9,'$'
end start

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值