Assembly codeInit_game macro op1,op2,op3,op4,op5,op6 mov cx,00h mov dh,op1 mov dl,op2 op6:mov ah,02h ;设置光标位置 mov bh,00h int 10h push cx mov ah,0ah ;重复显示相同字符 mov al,op3 ;要显示的字符 mov bh,00h ;页号 mov cx,01h ;显示的次数 int 10h pop cx inc cx inc op4 cmp cx,op5 jne op6 ;不等则转移endm clear_screen macro op1,op2,op3,op4 ;清屏宏定义 mov ah,06h mov al,00h mov bh,07h mov ch,op1 mov cl,op2 mov dh,op3 mov dl,op4 int 10h mov ah,02h ;设置光标位置 mov bh,00h ;页号为0 mov dh,00h ;行号为0 mov dl,00h ;列号为0 int 10h endm menu macro op1,op2,op3 ;菜单显示宏定义 mov ah,02h ;设置光标位置 mov bh,00h mov dh,op1 mov dl,op2 int 10h mov ah,09h lea dx,op3 ;显示op3 int 21h endm data segment ZK db "WELCOME TO PLAY$" no db "date:2003/6/24$" meg db "press Enter key to continue.......$" meg1 db "when a letter is dropping,please hit it!$" meg2 db "press space key to pause!$" meg3 db "press ESC key to return main interface!$" meg4 db "press letter 'E' to exit!$"meg5 db "press Enter key to return main interface!$" speed dw 600d letters db "jwmilzoeucgpravskntxhdyqfb" db "iytpkwnxlsvxrmofzhgaebudjq" db "nwimzoexrphysfqtvdcgljukda" letters_bak db "jwmilzoeucgpravskntxhdyqfb" db "iytpkwnxlsvxrmofzhgaebudjq" db "nwimzoexrphysfqtvdcgljukda" time db 'you have take time:$'letter_counter db 0 life_flag db 78 dup(0) position_flag db 78 dup(0) present_position db 1 start_hour db 0start_min db 0start_second db 0 end_hour db 0end_min db 0end_second db 0data ends stack segment para stack 'stack' db 64 dup(0) stack ends code segment main proc far assume cs:code,ds:data,ss:stack start: mov ax,data mov ds,ax mov letter_counter,00h mov present_position,1 lea si,position_flag mov ah,00h mov cx,00h init_postion_flag: ;对position_flag依次赋值为00h mov [si],ah inc si inc cx cmp cx,78d jne init_postion_flag lea di,letters lea si,letters_bak mov cx,00h init_letters: ;将letters_bak的值赋给letters mov ah,[si] mov [di],ah inc si inc di inc cx cmp cx,78d jne init_letters mov ah,00h lea si,life_flag mov cx,00h init_life_flag: ;对life_flag依次赋值为00h mov [si],ah inc si inc cx cmp cx,78d jne init_life_flag mov cx,00h mov ah,01h or ch,00010000b int 10h clear_screen 00d,00d,24d,79d ;清屏 Init_game 00d,00d,0ah,dl,80d,nextsign1 ;循环显示边框 Init_game 24d,00d,0ah,dl,80d,nextsign2 Init_game 00d,00d,0ah,dh,25d,nextsign3 Init_game 00d,79d,0ah,dh,25d,nextsign4 menu 05d,15d,ZK ;在第5行15列显示ZK menu 07h,15d,no ;在第7行15列显示no menu 09d,15d,meg menu 11d,15d,meg1 menu 13d,15d,meg2 menu 15d,15d,meg3 menu 17d,15d,meg4 put: mov ah,02h ;设置光标位置 mov bh,00h mov dh,22d mov dl,33d int 10h mov ah,01h ;从键盘输入任意字符 int 21h cmp al,0dh je speed3 ;是回车转移到speed3 cmp al,45h ;空格转移到exit je exit exit: mov ah,4ch int 21h speed3: mov ax,speed+12 mov speed,ax jmp begin ;开始游戏 begin: clear_screen 01d,01d,23d,78d ;清屏宏调用 clear_screen 01d,01d,23d,78d Init_game 23d,01d,01h,dl,78d,nextsign5 ;此时dl是33d ;call start_time ;;;;;;;;;;;;;调用之后就不能正常显示字母 mov ah,02h ;设置光标位置 mov bh,00h mov dh,01h mov dl,01h int 10h mov cx,00h lea si,letters nextletter: mov ah,02h ;显示letters mov dl,[si] int 21h inc si inc cx cmp cx,78d je nextcycle jmp nextletter from_front: sub present_position,78d jmp gobackto_si find_zero: cmp letter_counter,78d je recycle cmp present_position,78d je from_one mov ah,00h nextsi: add present_position,01h inc si cmp [si],ah je gobackto_di cmp present_position,78d je from_one jmp nextsi from_one:mov present_position,01h jmp gobackto_si recycle:mov letter_counter,00h mov present_position,01d lea si,position_flag mov cx,00h mov ah,00h clearsi: mov [si],ah inc cx cmp cx,78d je nextcycle inc si jmp clearsi nextcycle: lea di,letters lea si,position_flag add present_position,31d ;32d.present_position是用来指定当前光标的所在列 cmp present_position,78 ja from_front ;大于则转移gobackto_si: add si,word ptr present_position dec si ;指定position_flag第32位置 mov ah,[si] ;获取position_flag第32位置的值 cmp ah,01h je find_zero gobackto_di: mov ah,01h mov [si],ah add di,word ptr present_position dec di mov dl,present_position ;设置光标位置在present_position处 mov ah,02h mov bh,00h mov dh,01h int 10h mov cx,00h nextrow: push cx mov cx,00h out_cycle: ; 延迟 push cx mov cx,00h in_cycle: ;这种延迟有点怪。。。。还是用 add cx,01h cmp cx,1000 jne in_cycle push dx mov ah,06h ;从键盘输入字符。AL=输入字符 mov dl,0ffh int 21h pop dx jz pass ;上面哪个运算会改变标志位.pop? cmp al,1bh ;如果键入ESC,则返回主菜单 je to_start1 cmp al," " ;如果键入SPACE,则游戏暂停 je pause cmp al,[di] ;输入字母正确!则字母消失 je disappear pass: pop cx ;显示字母 inc cx cmp cx,speed je print jmp out_cycle pause: push dx ;暂停处理 mov ah,06h ;等待输入一个字符 mov dl,0ffh int 21h pop dx cmp al," " jne pause jmp pass to_start1: ;返回主菜单 call end_time clear_screen 00,00,24,79 mov ah,09h lea dx,time int 21h mov ah,02h mov dh,10 mov dl,30 int 10h mov bx,0 mov bl,end_hour sub bl,start_hour call take_time mov ah,02h mov dl,':' int 21h mov bx,0 mov bl,end_min sub bl,start_min call take_time mov ah,02h mov dl,':' int 21h mov bx,0 mov bl,end_second sub bl,start_second call take_time mov ah,02h mov dh,11 mov dl,30 int 10h mov ah,09h lea dx,meg5 int 21hput1: mov ah,01h int 21h cmp al,0dh jz start jmp put1print: mov ah,0ah ;在当前光标位置写空格 mov al," " mov bh,00h mov cx,01h int 10h inc dh ;列号+1 mov ah,02h ;改变光标位置 mov bh,00h int 10h mov ah,0ah ;在当前光标位置写字母 mov al,[di] mov bh,00h mov cx,01h int 10h pop cx inc cx cmp cx,21d ;一个字母下落过程中有21行 je print_next_letter jmp nextrow ;下一行 disappear: ;击中字母后输出空格 pop cx pop cx mov ah,0ah mov al," " mov bh,00h mov cx,01h int 10h jmp hit print_next_letter: lea si,life_flag add si,word ptr present_position dec si mov ah,0ah mov al," " mov bh,00h mov cx,01h int 10h inc dh mov ah,02h mov bh,00h int 10h mov ah,0ah mov al," " mov bh,00h mov cx,01h int 10h mov ah,1 mov [si],ah ;没击中,将lift_flag相应列号的值设为1 hit: mov ah,02h mov bh,00h mov dh,01h mov dl,present_position int 10h mov al,[di] ; 出现下一个新字母的数法 add al,7 cmp al,7ah ja convey_letter ;大于z就转 mov ah,0ah ;在下落位置处产生一个新字母 mov bh,00h mov cx,01h int 10h mov [di],al add letter_counter,01h jmp nextcycle convey_letter: sub al,7ah add al,61h mov ah,0ah mov bh,00h mov cx,01h int 10h mov [di],al add letter_counter,01h jmp nextcycle clear_screen 01,01,23,78 mov ah,02h mov bh,00h mov dh,11d mov dl,20d int 10h inc dh inc dh mov ah,02h mov bh,00h int 10h notkey: mov ah,07h int 21h cmp al,0dh je to_start cmp al,1bh je over jmp notkey to_start: clear_screen 00,00,24,79 jmp start over: clear_screen 01,01,23,78 mov ah,02h mov bh,00h mov dh,11d mov dl,15h int 10h mov ah,02h mov bh,00h mov dh,13d mov dl,15h int 10h mov ah,07h int 21h mov ah,07h int 21h clear_screen 00,00,24,79 mov ax,4c00h int 21h main endp start_time proc push ax push bx push cx push dx mov ah,2ch int 21h mov start_hour,ch mov start_min,cl mov start_second,dh pop dx pop cx pop bx pop ax retstart_time endpend_time proc push ax push bx push cx push dx mov ah,2ch int 21h mov end_hour,ch mov end_min,cl mov end_second,dh pop dx pop cx pop bx pop ax retend_time endp take_time proc mov ax,bx mov cx,0 mov bx,10 let1: mov dx,0 inc cx idiv bx push dx cmp ax,0 jnz let1 let2: pop ax add ax,0030h mov dl,al mov ah,2 int 21h loop let2 rettake_time endp code ends end start ;每次下落后产生一个新字母,下落顺序是每次列号+32,只有小写.通过present_position来控制光标位置