编译环境:masm5.0+link3.6
assume cs:code,ds:data,ss:stack,es:data
;;;;;;;;按键的扫描码
down equ 50h
left equ 4bh
right equ 4dh
up equ 48h
ESCkey equ 1
F1 equ 3bh
F2 equ 3ch
space equ 39h
levels equ 9;放块种类个数
level equ 11;等级速度调整
data segment
;;;;定义方块形状,一个word的每4位是一个小方块的位置
tetris dw 98ech,0,0cc7h,1,98ech,0,0cc7h,1,2;反z
dw 18ebh,1,04c7h,0,18ebh,1,04c7h,0,3;z
dw 447h, 0,994bh,0,14c7h,0,88cbh,0,4;反L
dw 443h, 0,9970h,0,443h, 0,9970h,0,1;I
dw 445h, 0,4cbh, 0,14c7h,1,996ch,0,5;L
dw 94c7h,0,98ebh,0,446h, 0,94cbh,0,7;T
dw 88c7h,0,88c7h,0,88c7h,0,88c7h,0,6;田
tetris1 dw 0,0,0,0,0,0,0,0,8eh ;一个点,有穿透属性
dw 22h ,0,84cbh,10h, 22h , 0,84cbh,10h,5h;...
;这里一tetris1为分界线,在它前的显示4次,从它往后都是5次,另外,颜色不许有第4位的高亮属性
nowdot dw 0 ;位置y:x 当前显示的方块的位置
nowtetris dw 0,0,0,0,0;当前方块的形状(2字),颜色,种类的指针,第几个子形状*4
nexttetris dw 0,0,0,0,0;同nowtetris,下一个要显示的方块
oldtetris dw 0,0,0,0,0
nowtime db 0;;;; 时间
mark db 0,0;;;; 得到的分数
lptetris dw 0,18,36
dw 18*3,18*4,18*5
dw 18*6,18*7,18*8
;;;直接定址表,每个种类的偏移地址
color db 0;颜色
over db "GBABMBEBOBVBEBRB!B"
db "RBeBsBtBaBrBtB BkBeByB(BYB)B B BQBuBiBtB B(BoBtBhBeBrB BaBnByB BkBeByB)B"
;;;;;;;;;游戏失败提示
quit db "QBuBiBtB?B B(BYB/BNB)B"
;ESC键退出提示
szlevel db "LEVEL:"
score db "S@C@O@R@E@:@"
winner db "Thank you for everyone.You are winner!$"
helps db 24," :deformation"
db 25," :moves down "
db 27," :moves left "
db 26," :moves right"
db "space:pause "
db "F1 : about "
db "ESC : exit "
about db " About Tetris "
db " Version 1.0 "
db " www.asmedu.net "
db "Copyright (c) 2012"
data ends
stack segment
db 128 dup (?);;;;128字节栈
stack ends
code segment
oldint1ch dw 0,0;旧int1ch的地址
time db 0,0
timechar db 4,2,0
newint1c:
pushf ;新1ch中断入口
call dword ptr cs:oldint1ch ; 这里都是老程序了
inc cs:time
offlevel:
cmp cs:time,level;offlevel指向这个15来达到控制下落速度的目的
jb returnd
mov cs:time,0
inc cs:time+1
call showtime
returnd:
iret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
showtime:
push ax ;主意不要寄存器冲突就好
push cx
push si
push di
push es
mov ax,0b800h
mov es,ax
mov di,1742
xor si,si
mov cx,3
mov ah,2
mov al,':'
mov es:[di+4],ax
mov es:[di+10],ax;先将两个":"显示出来
s1:push cx
mov cl,4
mov al,cs:timechar[si]
out 70h,al
in al,71h
mov ah,al
shr ah,cl
and al,0fh
add ax,3030h
mov es:[di],ah
mov ah,2
mov es:[di+1],ah
mov es:[di+2],ax
inc si
add di,6
pop cx
loop s1
pop es
pop di
pop si
pop cx
pop ax
ret
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;void paint proto lptetris:word,color:word
;功能:采取xor显示,在相同位置显示相同形状的方块,第一次是显示,第二次是清除
; 入口 : lptetris指向方块结构的指针,color方块的颜色
; 出口 :无
paint:
push bp
mov bp,sp
push cx
push bx
push dx
push si
push di
mov cx,4
mov bx,[bp+4];方块指针
mov ax,[bx]
mov dx,[bp+6];颜色
mov dh,1
xchg dh,dl
mov si,dx
mov dx,[bx+2]
cmp word ptr [bx+6],offset tetris1
jb loop1
mov cx,5
loop1:
push cx
push dx
push ax
mov cx,5
xor dx,dx
and ax,31
div cx
mov bx,nowdot;当前位置
add bl,dl
add bh,al
mov al,80
mul bh
mov di,ax;位置x=(ax&15)%4+nowdot低8位
mov al,bl
mov ah,0
shl ax,1
add di,ax;位置y=(ax%15)/4+nowdot高8位
xor es:[di],si;
pop ax
pop dx
call div32
pop cx
loop loop1
loop_2:
pop di
pop si
pop dx
pop bx
pop cx
pop bp
ret 4
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;viod gettetris proto lptetris
;功能 :随机设置要显示的方块
;入口 :指向4字指针(方块的形状,颜色,当前种类指针,第几个形状)
;返回 :无
;
gettetris:
push bp
mov bp,sp
push bx
push si
push cx
mov si,[bp+4]
in al,40h;;汇编没有rand函数,从40h端口读取一个字节当随机数,毕竟伪随机数的算法得好多代码
mov ah,0
mov cl,levels
div cl
xchg ah,al
shl al,1
mov ah,0
mov bx,ax
mov bx,lptetris[bx]
mov [si+6],bx;种类指针
push [bx+16];颜色
pop [si+4]
in al,40h
mov ah,0
mov cl,4
div cl
xchg ah,al
shl al,1
shl al,1
mov ah,0
mov [si+8],ax;第几个形状(*2)
add bx,ax
push [bx+2]
push [bx]
pop [si];形状
pop [si+2];形状
pop cx
pop si
pop bx
mov sp,bp
pop bp
mov nowdot,107h;x:y
ret 2
;<<<<<<<<<<<<<<<<<<<<<<<<<<<
; bool canmovedot proto [bp+4]:位置
;canmove的穿透版,判断能否下落
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
canmovedot:
push bp
mov bp,sp
push bx
push di
mov bx,[bp+4]
cmp bh,23;不允许超过第23行
ja @cannot
mov al,80
mul bh
mov di,ax
mov bh,0
shl bx,1
or bx,bx
jz @cannot;第0列是边界线,不允许
cmp bx,38
ja @cannot;第20列是边界,不允许
add di,bx
inc di;测试的是颜色
@can1:
test byte ptr es:[di],08
jz @can;当前位置没有高亮属性,就可以返回允许(0标志)
add di,80;测试下一行
cmp di, 1900;不能超过第23行
jb @can1
@cannot:
mov ax,1;1 no
jmp canret
@can:
xor ax,ax;0 ok
canret:
pop di
pop bx
mov sp,bp
pop bp
ret 2
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; bool canmove proto dot:[bp+4],lpmodel:[bp+6]
;功能:判断给定位置能否显示给定形状
;入口: dot指定的位置,lpmodel指定形状指针
;出口: 如果可以显示返回0,否则返回1
canmove:
push bp
mov bp,sp
push cx
push bx
push dx
push di
mov cx,4
mov bx,[bp+6]
mov ax,[bx]
mov dx,[bx+2]
or ax,ax
jnz @l_oop1
push [bp+4]
call canmovedot
jmp nret
@l_oop1:
cmp word ptr [bx+6],offset tetris1+18
jb l_oop1
mov cx,5
l_oop1:
push cx
push dx
push ax
mov cx,5
xor dx,dx
and ax,31
div cx
mov bx,[bp+4];当前位置
add bl,dl
add bh,al
cmp bh,23
ja l_oop3
mov al,80
mul bh
mov di,ax;位置x=(ax&31)%5+nowdot低8位
mov al,bl
mov ah,0
shl ax,1
or ax,ax
jz l_oop3
cmp ax,38
ja l_oop3
add di,ax;位置y=(ax%31)/5+nowdot高8位
test byte ptr es:[di+1],8;
jz l_oop2
l_oop3: mov ax,1
add sp,6
jmp nret
l_oop2:
pop ax
pop dx
call div32;ax>>=5
pop cx
loop l_oop1
nret:
pop di
pop dx
pop bx
pop cx
pop bp
ret 4
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
div32:
push bx
push ax
mov ax,dx
xor dx,dx
mov cx,32
div cx
mov bx,ax
pop ax
div cx
mov dx,bx
pop bx
ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; void movewindow proto
;功能:把上一行(x-1)复制到当前行x
;入口:无
;出口:无
movewindow:
push cx
push di
push bx
push ds
push es
pop ds
push bp
mov bp,sp
mov cx,[bp+12];;取testtetris函数的当前行cx值
pop bp
dec cx
moveloop:
push cx
mov cx,38
mov di,39
lea si,[bx+di-80]
lea di,[bx+di]
std
rep movsb
pop cx
sub bx,80
loop moveloop
mov cx,38
mov al,0
mov di,82
cld
rep stosb;第一行填0
pop ds
inc mark
pop bx
add bx,80
pop di
pop cx
ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;void testtetris proto
;功能:判断是否可以得分,如果可以,就清除满的那行,并让上面的"砖头 落"下来
;入口 无
;出口 无
testtetris:
push cx
push di
push bx
mov bx,1840
mov di,39
mov cx,23
@loop:
push cx;;如果会调用movewindow函数,这个值会被movewindow从栈中复制
mov cx,18
@loop1:
test byte ptr es:[bx+di],8
jz @loop2
sub di,2
loop @loop1
call movewindow
@loop2:
pop cx
sub bx,80
mov di,39
loop @loop
pop bx
pop di
pop cx
ret
;<<<<<<<<<<<<<<<
;void printfc void
;显示分数
printfc:
push bx
push di
mov di,1270;显示位置
mov al,mark
mov ah,0
mov bl,5
div bl
cmp al,1
jnz @p1;;;;;;;;;;;;设置速度
mov byte ptr cs:[offlevel+5],level-3
mov word ptr es:[1424],432h
jmp @p4
@p1:
cmp al,2
jnz @p2
mov byte ptr cs:[offlevel+5],level-5
mov word ptr es:[1424],433h
jmp @p4
@p2:
cmp al,3
jnz @p3
mov byte ptr cs:[offlevel+5],level-7
mov word ptr es:[1424],434h
jmp @p4
@p3:
cmp al,4
jnz @p4
mov byte ptr cs:[offlevel+5],level-8
mov word ptr es:[1424],435h
@p4:
mov al,mark
mov bl,10
@p:
mov ah,0
div bl
add ah,30h
mov byte ptr es:[di],ah
mov byte ptr es:[di+1],4
or al,al
jz retret
dec di;倒序显示
dec di
jmp @p
retret:
pop di
pop bx
ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;void setint1ch proto void
;设置1c中断
setint1ch:
push es
xor ax,ax
mov es,ax
push es:[1ch*4]
pop cs:oldint1ch
push es:[1ch*4+2]
pop cs:oldint1ch+2
cli
mov word ptr es:[1ch*4],offset newint1c
mov es:[1ch*4+2],cs
sti
setret:
pop es
ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;;程序开始
main:
mov ax,stack
mov ss,ax
mov sp,128
mov ax,data
mov ds,ax
xor ax,ax
int 10h;设置屏幕40*25
mov ah,1
mov ch,20h
int 10h;不显示光标
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
mov ax,0b800h
mov es,ax
call init
mov ax,offset nexttetris
push ax
call gettetris
mov nowdot,0945h
push nexttetris+4
mov ax,offset nexttetris
push ax
call paint;显示 "下一个"方块
mov ax,offset nowtetris
push ax
call gettetris
push nowtetris+4
mov ax,offset nowtetris
push ax
call paint;显示当前方块
mov al,cs:time+1
mov nowtime,al;获得当前秒数
startthis:
mov al,cs:time+1
cmp al,nowtime;获得当前秒数,并和nowtime比较,不同就可以下落了
jnz @3
jmp @2
@3: ;时间到了,是时候往下"落"了
mov nowtime,al
mov ax,offset nowtetris
push ax
mov ax,nowdot
inc ah;
push ax
call canmove;判断可以"落"不
or ax,ax
jnz @1
push nowtetris+4;清除当前显示
mov ax,offset nowtetris
push ax
call paint
inc byte ptr nowdot+1;"落"一行
push nowtetris+4
mov ax,offset nowtetris
push ax
call paint;显示
jmp @2
@1:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;到底了
push nowtetris+4
mov ax,offset nowtetris
push ax
call paint;清除当前显示
mov ax,15
push ax
mov ax,offset nowtetris
push ax
call paint;;;;;;改变颜色(前景高亮+白色)
mov al,mark
push ax
call testtetris;判断是否可以得分
pop ax
mov ah,mark
sub ah,al
jz tests
dec ah
add mark,ah
tests:
call printfc
mov al,mark
cmp al,250
jb @next@1
call @winner
@next@1:
push es
push ds
pop es
mov si,offset nexttetris
mov di,offset nowtetris
mov cx,10
cld
rep movsb;把下一个方块给当前方块
pop es
mov nowdot,0945h
push nexttetris+4
mov ax,offset nexttetris
push ax
call paint;清除"下一个"方块
mov ax,offset nexttetris
push ax
call gettetris
push nowdot
mov nowdot,0945h
push nexttetris+4
mov ax,offset nexttetris
push ax
call paint;;;;;;;;显示"下一个"方块
pop nowdot
push nowtetris+4
mov ax,offset nowtetris
push ax
call paint;显示当前方块
mov ax,offset nowtetris
push ax
mov ax, nowdot;
inc ah
push ax
call canmove
or ax,ax;;;如果刚显示出来,但是不能往下"落",表示下面的方块很高了,要结束了
jnz restart;不能下了就结束了
@2:
mov ah,11;判断用户是否按键了
int 21h
or al,al
jnz @5;按了就读出按键的扫描码和ascii
jmp near ptr startthis
@5:
xor ax,ax
int 16h
call dispatch;处理按键
jmp startthis
restart:;;;;;失败了
mov al,0
xor di,di
mov cx,4000
cld
rep stosb
lea si,over;显示失败信息
mov di,12*80+28
MOV CX,18
rep movsb
add di,118
mov cx,72
rep movsb
xor ax,ax
int 16h;按Y再玩一次
cmp ah,15h
jnz codeend
jmp main
codeend:
call quitgame
;<<<<<<<<<<<<<<<<<<<<<<<<<<<
;void @winner proto void
;显示胜利信息并退出
@winner:
mov ax,400h
xor di,di
mov cx,1000
cld
rep stosw
mov si,offset winner
mov ah,2
mov di,13*80+2
mov cx,38
cld
@win:
lodsb
stosw
loop @win
mov ah,7
int 21h
call quitgame
ret
;<<<<<<<<<<<<<<<<<<<<<
;viod init proto
;功能:设置屏幕,"画"界线
;入口:无
;返回:无
init:
push cx
push di
push es
xor ax,ax
mov es,ax
mov cx,es:[1ch*4+2]
mov ax,cs
pop es
cmp ax,cx
jz @init1;如果中断已经设过,就不再设置
call initwindow;欢迎界面
call setint1ch;设置中断
@init1:
mov cx,1000
xor di,di
mov ax,di
cld
rep stosw
mov si,offset score;显示"score"
mov di,1250
mov cx,12
rep movsb
mov cx,6
mov di,1410
mov si,offset szlevel;显示"level:"
mov ah,10
cld
@init:
lodsb
stosw
loop @init
mov word ptr es:[di+2],431h;等级
call help;显示按键信息
call interface;画可移动区域
mov mark,0;分数
mov byte ptr cs:[offlevel+5],level;设置初始等级下落速度
call printfc;显示分数
pop di
pop cx
ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
initwindow:
push ds
push si
push di
push cx
push bx
call draw
db "TTTTT EEEEE TTTTT RRRR III SSS"
db " T E T R R I S "
db " T EEEEE T RRRR I S "
db " T E T R R I S"
db " T EEEEE T R R III SSS"
@name db "by chinatree"
@data db "Copyright (c) 2012 www.asmedu.net"
draw:
pop si;上面字符的首地址
mov color,0
push cs
pop ds
mov di,720
cld
mov cx,200
@draw:
lodsb
mov ah,al
xor ah,75h
stosw
loop @draw;TETRIS这几个大字母
mov cx,12
mov ah,3h
mov di,1550
cld
@draw3:
lodsb
stosw
loop @draw3;显示"by chinatree"
mov cx,34
mov di,1606
cld
@draw4:
lodsb
stosw
loop @draw4;显示"Copyright (c) 2012..."
mov cx,2
@draw2:
push cx
mov cx,0
@draw6:
mov ah,11
int 21h
or al,al
jnz @draw1
loop @draw6;判断用户是否按键了,如果按了,就返回,没按就延时
pop cx
loop @draw2
jmp @draw7
@draw1:
xor ax,ax
int 16h
pop cx;Illegal use of CS register
@draw7:
pop bx
pop cx
pop di
pop si
pop ds
ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;void interface proto
;功能;画出方块移动范围
;入口:无
;返回:无
interface:
push di
push cx
xor di,di
mov ax,77dbh
mov cx,40
cld
rep stosw
mov cx,23
@s:
mov es:[di],ax
mov es:[di+40],ax
mov es:[di+78],ax
add di,80
loop @s
mov cx,40
rep stosw
pop cx
pop di
ret
;<<<<<<<<<<<<<<<<<<<<<
;viod quitgame proto void
;退出
quitgame:
mov ax,2
int 10h
mov ax,0b800h
mov es,ax
mov ax,720h
mov cx,2000
xor di,di
cld
rep stosw
xor ax,ax
mov es,ax
cli
push cs:oldint1ch;把原来的中断还设回去
pop es:[1ch*4]
push cs:oldint1ch+2
pop es:[1ch*4+2]
sti
mov ax,4c00h
int 21h
;<<<<<<<<<<<<<<<<
;void help proto
;功能:显示帮助和版本信息
;入口:无
;出口:无
help:
push cx
push di
mov si,offset helps
mov di,208
mov cx,7
mov ah,6
@loop@:
push cx
mov cx,14
@lloop:
lodsb
stosw
loop @lloop
pop cx
add di,52
loop @loop@
pop di
pop cx
ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;void abouts proto void
;显示版本信息
abouts:
push es
push ds
push si
push di
push cx
push ds
push es
pop ds
xor si,si
mov di,2000
mov cx,di
cld
rep movsb
xor di,di
mov ax,di
mov cx,1000
rep stosw
pop ds
mov si,offset about
mov ah,6
mov di,904
mov cx,4
@loop1@:
push cx
mov cx,18
@loop2@:
lodsb
stosw
loop @loop2@
pop cx
add di,44
loop @loop1@
mov ah,7
int 21h
push es
pop ds
xor di,di
mov cx,2000
mov si,cx
cld
rep movsb
pop cx
pop di
pop si
pop ds
pop es
ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;viod dispatch proto
;功能判断用户是否按下了一些功能键并处理,不是就不处理
;入口:ax=扫描码(高16位):ascii(低16位)
;出口:无
dispatch:
cmp ah,left;处理左键
jnz next1
mov ax,offset nowtetris
push ax
mov ax,nowdot
dec al
push ax
call canmove
or ax,ax
jnz @l77
push nowtetris+4
mov ax,offset nowtetris
push ax
call paint
dec byte ptr nowdot;位置x-=1
push nowtetris+4
mov ax,offset nowtetris
push ax
call paint
@l77:
ret
next1:
cmp ah,up;上键
jnz next2
push es
push ds
pop es
mov si,offset nowtetris
mov di,offset oldtetris
mov cx,10
cld
rep movsb
pop es
mov bx,offset nowtetris
mov cx,[bx+6]
mov ax,[bx+8]
add ax,4
mov bl,16
div bl
xchg ah,al
mov ah,0
mov bx,ax
mov nowtetris+8,ax
add bx,cx
push [bx]
pop nowtetris
push [bx+2]
pop nowtetris+2
mov ax,offset nowtetris
push ax
push nowdot
call canmove
or ax,ax
jz @llll
push es
push ds
pop es
mov di,offset nowtetris
mov si,offset oldtetris
mov cx,10
cld
rep movsb
pop es
jmp near ptr return
@llll:
push oldtetris+4
mov ax,offset oldtetris
push ax
call paint;消除当前方块
push nowtetris+4
mov ax,offset nowtetris
push ax
call paint
ret
next2:
cmp ah,right;右键
jnz next3
mov ax,offset nowtetris
push ax
mov ax,nowdot
inc al
push ax
call canmove
or ax,ax
jnz @l9
push nowtetris+4
mov ax,offset nowtetris
push ax
call paint
inc byte ptr nowdot;位置x+=1
push nowtetris+4
mov ax,offset nowtetris
push ax
call paint
@l9:
ret
next3:
cmp ah,down;下键
jnz next4
mov ax,offset nowtetris
push ax
mov ax,nowdot
inc ah
push ax
call canmove
or ax,ax
jnz retur
push nowtetris+4
mov ax,offset nowtetris
push ax
call paint
inc byte ptr nowdot+1;位置y+=1
push nowtetris+4
mov ax,offset nowtetris
push ax
call paint
retur:
ret
next4:
cmp ah,space;空格键,暂停程序
jnz next5
@next@2:
xor ax,ax
int 16h
cmp ah,F1;暂停时只支持显示版本的F1
jnz @next_1
call dispatch;递归一次
jmp @next@2
@next_1:
cmp al,32
jnz @next@2
mov al,cs:time+1
mov nowtime,al
ret
next5:
cmp ah,F1;F1显示帮助
jnz next7
call abouts
ret
next7:
cmp ah,ESCkey;ESC退出
jnz return
push ds
push ds
push es
pop ds
mov di,1000h
mov cx,1000
xor si,si
cld
rep movsw
xor ax,ax
mov cx,1000
mov di,ax
cld
rep movsw
pop ds
mov si,offset quit
mov di,990
mov cx,22
rep movsb
xor ax,ax
int 16h
cmp ah,15h
jz return1;;;;Y退出
push es
pop ds
mov si,1000h
mov cx,1000
xor di,di
cld
rep movsw
pop ds
jmp return
return1:
call quitgame
return:
ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
code ends
end main
MASM提示Extra characters on line:
先看下那行是否有多余的字符,如果没有,查看下文件的编码方式,UTF-8等编码会在文件的开始部分加上2个字节的标志,只有ANSI编码不会添加任何东西.
1,假如第24行和第23行全是方块,在调用testdiamond函数时,会先调用movewindow清除第24行,结果就是把第23行给了第24行,然后去检测第23行(没清除前的第22行),这样当前的第24行会被漏掉.
2,显示带穿透效果的那个方块时,由于定义成0000h的形式,在paint函数中的显示时,每次显示的都是那一个点,由于采用的是xor来显示,这样第一次xor时显示,第2次消除,3显示,4清除,结果发现会出现一个空的方块,我解决的办法是根据方块形状值来有针对的显示.形状值为0时只xor一次.
现在改了,由于可以显示5次,这样虽然xor了5次,浪费了些,但是可以让代码量小些,感觉也足够了.
3,必须针对穿透属性的方块增加一中判断函数,判断方式就是给定一个位置,如果它往下能下就直接返回0表示允许,不能下时循环判断当前位置这一列往下是否有空缺的方块位置,有就返回0表示允许.
4,对于空格暂停,不能使用ah=7/int21h来做.因为它不能处理ascii为0的按键,会对按键进行递归操作.
5,改版了以前显示的方式,改为5位表示一个相对位置,并写了个段代码用于输入相对位置,得到一个数据,tc下通过:
#include <stdio.h>
int main()
{
int i[5];
int j,l;
long k;
while (scanf("%x %x %x %x %x",i,i+1,i+2,i+3,i+4))
{ /*当然这里只能输入字母等能退出了*/
/*输入比如,10 11 12 21 20这样,xy xy xy xy xy,当然这里是相对坐标*/
for(j=0,k=0;j<5;j++)
{
l=i[j]&15;
l+=(i[j]>>4)*5;
k<<=5;
k|=l;
}
printf("%lX\n",k);/*x大写表示显示的a~f用大写表示哦*/
}
return 0;
}
第一次使用自己写的代码来帮自己解决另外的一些问题,虽然比较丑陋,但是有点不一样的感觉.
6,由于使用的是判断颜色是否高亮来确定是否可以移动,定义时不能有高亮颜色位存在,否则动不了.如果使用别的方法来判断,还没有想出.不然就可以落底后不变色了.
7,对于设置等级,我把它放到了显示分数的代码块中,因为只有每个方块到底后才会调用那块代码来刷新.
8,当清除某一行时,不能忘记把最上行用0填充掉.不然会有个bug,虽然比较深.
9,为判断,显示这俩函数增加了个不除法溢出的模块,因为在右移5位时,有可能发生除法溢出,shl等指令又不能把dx:ax当成一个整体.
10,方块的下落速度是由自定义的int1ch来操作的.每秒被调18.2次,每次将某个变量加1,再判断是否可以"进位",需要进位就把另一变量加1,当主函数比较时间时,发现不同了,就是时间到了,该下落了.但是在失败后重新开始时,要进行判断,不要重复设置中断,以及开始画面,开始画面在整个进程的生命周期中只需要出现一次.
11,退出时不要忘记把中断还设回去,因为并没有安装,中断体还在自己的代码段,有可能会被后面的进程覆盖,那样系统就崩溃了.
12,随机函数还是蛮重要的,它和每种方块出现的频率有关,有时会连续出现几个相同的方块,有时间我要找个公式做个随机函数出来
13,把程序模块化是很有必要的,还有缩进格式.
14, lea指令的妙用:
lea的功能就是把源操作数[]内的表达式求值并把这个值给目的操作数.正因为这个特性,用它来做加法是非常简单的,如lea ax,[bx+si+100]就是ax=bx+si+100,这比add指令要方便吧,呵呵.
求指点.
[课程]Linux pwn 探索篇!