新年送礼!
dwing吧
全部回复
仅看楼主
level 13
dwing 楼主
;2006年新年公开我写的471字节俄罗斯方块汇编程序源代码及详细注释!;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 100hstart: 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 ;判断键盘缓冲区是否有字符
2006年01月02日 15点01分 1
level 13
dwing 楼主
jz short @loop ;没有按键则跳出键盘处理部分 xor ax,ax call @disp ;清除新方块的显示 int 16h ;读取键盘缓冲区字符=>ah mov al,ah ;al=ah cmp al,$up ;判断是否是上方向键 jnz short @k1 ;不是则跳转 push bp ;保存当前新方块的摆放形状 movzx bp,cs:[bp+bkv] ;改变新方块的摆放形状 call @isok ;判断是否能放置 jz short @loop_ ;能放置则跳出键盘处理部分 pop bp ;不能放置则恢复新方块原来形状 loop @wait ;继续下一次等待@k1: push bx ;保存当前新方块的位置 cmp al,$left ;判断是否是左方向键 jnz short @k2 ;不是则跳转 dec bx ;新方块左移一个位置(2个字节) dec bx@test: call @isok ;判断是否能放置 jz short @loop_ ;能放置则跳出键盘处理部分 pop bx ;不能放置则恢复新方块原来位置 loop @wait ;继续下一次等待@k2: cmp al,$right ;判断是否是右方向键 jnz short @k3 ;不是则跳转 inc bx ;新方块右移一个位置(2个字节) inc bx jmp short @test ;剩下的处理同"左方向键"@k3: pop bx ;恢复新方块原来位置 cmp al,1 ;判断是否是ESC键 jz short @end ;如果是则跳转到退出程序段 jmp short @ok ;如果是其他按键则跳出延时状态@loop_: pop ax ;清除保存的新方块位置@loop: loop @wait ;继续下一次等待@ok: push ax ;保存按键扫描码 xor ax,ax ;延时过后进入方块下落部分 call @disp ;清除新方块的显示 add bx,2*40 ;新方块下移一个位置(2个字节) call @isok ;判断是否能放置 pop ax ;恢复按键扫描码 jnz short @down ;如果不能放置新方块则跳转 cmp al,$down ;判断是否是下方向键 jz short @ok ;如果是则继续下落 jmp short @goon ;不是则进入下一次延时@down: sub bx,2*40 ;恢复新方块原来位置 call @dispb ;显示新方块 xor ax,ax ;进入判断是否有一行已满 mov dx,ax ;ax=dx=0 mov si,2*(40*2+15) ;si=中间空框的起始屏幕偏移位置@nextl: mov di,si ;di=当前判断的屏幕偏移位置 mov cl,11 ;判断10次(10+1) repnz scasw ;扫描一行 jz short @skip ;如果有空位则跳出 pusha ;进入消除一行部分 mov si,di sub si,2*40 ;si=上一行屏幕偏移位置 mov cx,si ;cx=移动字符个数 std rep movsb ;移下一行 cld mov di,2*(40*2+15) ;di=中间空框最上一行的屏幕偏移位置 mov cl,10 ;一行10个方块 rep stosw ;清除最上一行
2006年01月02日 15点01分 2
level 13
dwing 楼主
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 2bkv 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 ;* 18msg1 db 9,9,'GAMEOVER',9,9,'$'end start
2006年01月02日 15点01分 3
level 2
今年过节不收礼,多谢dwing的脑黄金,呵呵
2006年01月09日 08点01分 4
level 0
佩服,短短470行代码,做出这么漂亮的游戏,佩服!
2006年11月29日 07点11分 6
level 0
请问要用什么编译啊?
2006年11月29日 11点11分 7
level 13
dwing 楼主
TASM
2006年11月29日 13点11分 8
level 0
写得非常简练
2006年12月02日 14点12分 9
level 0
非常感谢虽然还没看但比我上个下700多行的厉害多了谢谢
2007年04月28日 16点04分 10
level 2
哈哈 谢谢啊
2007年07月14日 05点07分 11
level 0
这出来是什么东西啊~~~~~~~
2007年12月13日 01点12分 12
level 1
可以编译运行就是不知道按键如何设置!
2007年12月28日 08点12分 13
level 13
dwing 楼主
按键设置:$up equ 72 $left equ 75 $right equ 77 $down equ 80 后面的值是键盘扫描码.
2007年12月28日 11点12分 14
level 0
dwing今年送什么呀?
2008年01月01日 00点01分 15
level 13
dwing 楼主
今年元旦前后这几天由于种种事务很难接触到电脑,所以送礼要推迟了.
2008年01月01日 14点01分 16
level 11
收呀收
2008年01月01日 18点01分 17
level 13
dwing 楼主
主页已上传,礼物是loca的源代码.ENJOY!
2008年01月04日 06点01分 18
level 0
感谢
2008年01月08日 05点01分 19
level 1
win xp怎么运行啊?我一运行就gameover
2008年01月25日 05点01分 20
level 13
dwing 楼主
我在程序中已经写了:;Only for DOS/Win9x/WinME/DosBox(注意不能直接在Win2000以上系统运行)原因是DOS的一个精确计时中断在NT内核的虚拟DOS环境中没有实现.如果要在Win2000以上系统中正常运行,需要使用DOS模拟器,到这里下载:http://www.dosbox.com/
2008年01月25日 05点01分 21
1 2 尾页