📄 snake.asm
字号:
pop dx
pop cx
pop bx
pop ax
ret
Load_File endp
;*************************************
;将本局游戏的分数和历史分数进行排名
Set_Rank proc near
push ax
push bx
push cx
lea bx,Rank_ABC
Cmp_A: mov ax,[bx]
cmp ax,Gscore
;若本局分数和历史最高相等,则保持原顺序
;退出比较
jz exit_cmp
;若本局分数比历史最高低,则和历史第二高比较
ja Cmp_B
;程序运行到此处,本局分数为历史最高,放在第一位
mov cx,[bx+2]
mov [bx+4],cx
mov cx,[bx]
mov [bx+2],cx
mov cx,Gscore
mov [bx],cx
jmp exit_cmp
Cmp_B:
mov ax,[bx+2]
cmp ax,Gscore
;若本局分数和历史第二高相等,则保持原顺序
;退出比较
jz exit_cmp
;若本局分数比历史第二高低,则和历史第三高比较
ja Cmp_C
;程序运行到此处,本局分数为历史第二高,放在第二位
mov cx,[bx+2]
mov [bx+4],cx
mov cx,Gscore
mov [bx+2],cx
jmp exit_cmp
Cmp_C:
mov ax,[bx+4]
cmp ax,Gscore
;若本局分数比历史第三高低,则保持原顺序
;退出比较
jae exit_cmp
;程序运行到此处,本局分数为历史第三高,放在第三位
mov cx,Gscore
mov [bx+4],cx
exit_cmp:
pop cx
pop bx
pop ax
ret
Set_Rank endp
;**********************************
;查看游戏分数排名情况
View_Rank proc near
push ax
push bx
push dx
push cx
;关闭所有进入子菜单的'开关'
mov Direct_set3,0
mov Direct_set1,0
mov Direct_set2,0
;绘制第三项子菜单的窗口框架
;范围(200,200)-(330,265)
mov cx,200
mov al,0
INC_Cr:
inc cx
mov dx,200
INC_Dr: inc dx
int 10h
cmp dx,264
jnz INC_Dr
cmp cx,329
jnz INC_Cr
mov al,10
mov cx,200
mov dx,200
line15r:
int 10h
inc cx
cmp cx,330
jnz line15r
mov cx,200
mov dx,265
line16r:
int 10h
inc cx
cmp cx,330
jnz line16r
mov dx,200
mov cx,200
line17r:
int 10h
inc dx
cmp dx,265
jnz line17r
mov dx,200
mov cx,330
line18r:
int 10h
inc dx
cmp dx,266
jnz line18r
;第三项子菜单的选项
;第一项'1-'
mov dh,13
mov dl,29
mov al,'1'
call View_Video
inc dl
mov al,'-'
call View_Video
inc dl
;第二项'2-'
mov dh,14
mov dl,29
mov al,'2'
call View_Video
inc dl
mov al,'-'
call View_Video
inc dl
;第三项'3-'
mov dh,15
mov dl,29
mov al,'3'
call View_Video
inc dl
mov al,'-'
call View_Video
inc dl
;显示游戏分数排名情况
;从文件中载入游戏信息,保存到内存缓冲区
call Load_File
mov bx,offset File_Area
add bx,12
;取出数据,并显示
;显示第一名
mov cx,[bx]
mov BTD,cx
mov Ctr_Jmp,0
mov H_Value,13
mov L_Value,31
call Bin_to_Dec
add bx,2
;显示第二名
mov cx,[bx]
mov BTD,cx
mov Ctr_Jmp,0
mov H_Value,14
mov L_Value,31
call Bin_to_Dec
add bx,2
;显示第三名
mov cx,[bx]
mov BTD,cx
mov Ctr_Jmp,0
mov H_Value,15
mov L_Value,31
call Bin_to_Dec
;等待用户的键盘信息,避免窗口一闪而过
mov ah,01h
int 21h
pop cx
pop dx
pop bx
pop ax
jmp far ptr start
ret
View_Rank endp
;**********************************
;同用发声程序
;参见清华大学<<IBM-PC汇编语言程序设计>>第二版
;第286页
Soundf proc near
push ax
push bx
push cx
push dx
push di
mov dx,2000
in al,61h
and al,11111100b
Trig: xor al,2
out 61h,al
mov cx,10000
Delay: loop Delay
dec dx
jne Trig
pop di
pop dx
pop cx
pop bx
pop ax
ret
Soundf endp
;**********************************
;绘制鼠标图案
Draw_Mouse proc near
push ax
push bx
push cx
push dx
mov ah,0ch
mov al,10
mov bh,0
mov cx,Mouse_X
mov dx,Mouse_Y
call draw_one_point
pop dx
pop cx
pop bx
pop ax
ret
Draw_Mouse endp
;**********************************
;清除鼠标图案
Clear_Mouse proc near
push ax
push bx
push cx
push dx
mov ah,0ch
mov al,00
mov bh,0
mov cx,Mouse_X
mov dx,Mouse_Y
call draw_one_point
pop dx
pop cx
pop bx
pop ax
ret
Clear_Mouse endp
;**********************************
;检测鼠标状态
Scan_Mouse proc near
push ax
push bx
push cx
push dx
;限制鼠标水平活动范围
mov ax,7
mov cx,18
mov dx,466
int 33h
;限制鼠标垂直活动范围
mov ax,8
mov cx,18
mov dx,466
int 33h
;检测鼠标当前状态
mov bx,0
mov ax,3
int 33h
;对鼠标的现实位置进行校准
call Balance_Shake
;保存扫描到的鼠标坐标
mov Mouse_X,cx
mov Mouse_Y,dx
;判断是否按下了鼠标的左键
cmp_bx_left:
push bx
and bx,1
cmp bx,1
pop bx
jnz cmp_bx_right
;当按下鼠标左键时设置Control_Kind=1
;表明当前由鼠标控制蛇的运动方向
;记录鼠标左键按下时鼠标的坐标,作为蛇移动的指定位置
mov Control_Kind,1
mov Mouse_Down_X,cx
mov Mouse_Down_Y,dx
;判断是否按下了鼠标的右键
;鼠标右键功能为'自动导航'
;即自动寻找食物
cmp_bx_right:
push bx
and bx,2
cmp bx,2
pop bx
jnz exit_Scan_Mouse
;当鼠标右键功能时设置Control_Kind=1
;表明当前由鼠标控制蛇的运动方向
;记录食物的坐标,作为蛇移动的指定位置
mov Control_Kind,1
mov ax,Food
mov Mouse_Down_X,ax
mov ax,Food+2
mov Mouse_Down_Y,ax
exit_Scan_Mouse:
pop dx
pop cx
pop bx
pop ax
ret
Scan_Mouse endp
;**********************************
;在鼠标控制蛇运动方向的时候,设置
;坐标(CX,DX)的值
Set_the_CX_and_DX_Together proc near
push ax
push bx
push cx
push dx
push si
push di
;清空键盘控制的方向标志变量
mov Directive,0
mov ax,0
add ax,HalfPoint
add ax,HalfPoint
mov Mouse_Point,ax
;清空鼠标控制的方向标志变量
;以便进行下面的设置
and DirectiveM,0000h
;得到鼠标按下左键时候的坐标
mov ax,Mouse_Down_X
mov bx,Mouse_Down_Y
;得到蛇头的坐标
mov cx,snake_H
mov dx,snake_H+2
;在鼠标控制下,存放蛇头的坐标是否已经到达
;鼠标指定坐标附近的信息
mov Mouse_Snake_Meet,0
;开始判断蛇头是否在指定坐标附近
;附近的定义为:以指定坐标为中心,
; 上下左右12个像素单位的范围
mov si,ax
mov di,bx
sub si,cx
jae Test_di
neg si
Test_di:
sub di,dx
jae do_other
neg di
do_other:
;得到蛇头横纵坐标和指定位置的横纵座标的差的绝对值
;比较它们的值是否同时满足'附近'的定义
;如果满足,则设置Mouse_Snake_Meet为1
cmp si,12
jae Go_on_Judge
cmp di,12
jae Go_on_Judge
mov Mouse_Snake_Meet,1
;=============================================================
;DirectiveM 控制 CX 和 DX 的增减情况
; 0000 保持CX 保持Dx ,即指定的位置与蛇头的位置相同。
; 0001 保持CX 增加DX ,即指定的位置在蛇头的垂直下方。
; 0010 保持CX 减小DX ,即指定的位置在蛇头的垂直上方。
;
; 0100 增加CX 保持DX ,即指定的位置在蛇头的水平右方。
; 0101 增加CX 增加DX ,即指定的位置在蛇头的右下方。
; 0110 增加CX 减小DX ,即指定的位置在蛇头的右上方。
;
; 1000 减小CX 保持DX ,即指定的位置在蛇头的水平左方。
; 1001 减小CX 增加DX ,即指定的位置在蛇头的左下方。
; 1010 减小CX 减小DX ,即指定的位置在蛇头的左上方。
;=============================================================
Go_on_Judge:
;****judge
cmp ax,snake_H
jb DEC_CX
cmp ax,snake_H
ja INC_CX
cmp ax,snake_H
je NON_CX
DEC_CX: or DirectiveM,1000h
jmp CMP_DX
INC_CX: or DirectiveM,0100h
jmp CMP_DX
NON_CX: or DirectiveM,0000h
jmp CMP_DX
CMP_DX:
cmp bx,snake_H+2
jb DEC_DX
cmp bx,snake_H+2
ja INC_DX
cmp bx,snake_H+2
je NON_DX
DEC_DX: or DirectiveM,0010h
jmp CX_DX
INC_DX: or DirectiveM,0001h
jmp CX_DX
NON_DX: or DirectiveM,0000h
jmp CX_DX
CX_DX:
mov ax,Mouse_Point
;****NON_DX
cmp DirectiveM,0000h
jz NON_CX_NON_DX
cmp DirectiveM,0100h
jz INC_CX_NON_DX
cmp DirectiveM,1000h
jz DEC_CX_NON_DX
jmp INCDX
NON_CX_NON_DX:
jmp exit_Set_Together
INC_CX_NON_DX: cmp Mouse_Snake_Meet,0
jz Nothing1
add Mouse_Down_X,ax
Nothing1: add cx,ax
jmp exit_Set_Together
DEC_CX_NON_DX: cmp Mouse_Snake_Meet,0
jz Nothing2
sub Mouse_Down_X,ax
Nothing2: sub cx,ax
jmp exit_Set_Together
INCDX:
;****INC_DX
cmp DirectiveM,0001h
jz NON_CX_INC_DX
cmp DirectiveM,0101h
jz INC_CX_INC_DX
cmp DirectiveM,1001h
jz DEC_CX_INC_DX
jmp DECDX
NON_CX_INC_DX: cmp Mouse_Snake_Meet,0
jz Nothing3
add Mouse_Down_Y,ax
Nothing3: add dx,ax
jmp exit_Set_Together
INC_CX_INC_DX: cmp Mouse_Snake_Meet,0
jz Nothing4
add Mouse_Down_X,ax
add Mouse_Down_Y,ax
Nothing4: add cx,ax
add dx,ax
jmp exit_Set_Together
DEC_CX_INC_DX: cmp Mouse_Snake_Meet,0
jz Nothing5
sub Mouse_Down_X,ax
add Mouse_Down_Y,ax
Nothing5: sub cx,ax
add dx,ax
jmp exit_Set_Together
DECDX:
;****DEC_DX
cmp DirectiveM,0010h
jz NON_CX_DEC_DX
cmp DirectiveM,0110h
jz INC_CX_DEC_DX
cmp DirectiveM,1010h
jz DEC_CX_DEC_DX
NON_CX_DEC_DX: cmp Mouse_Snake_Meet,0
jz Nothing6
sub Mouse_Down_Y,ax
Nothing6: sub dx,ax
jmp exit_Set_Together
INC_CX_DEC_DX: cmp Mouse_Snake_Meet,0
jz Nothing7
add Mouse_Down_X,ax
sub Mouse_Down_Y,ax
Nothing7: add cx,ax
sub dx,ax
jmp exit_Set_Together
DEC_CX_DEC_DX: cmp Mouse_Snake_Meet,0
jz Nothing8
sub Mouse_Down_X,ax
sub Mouse_Down_Y,ax
Nothing8: sub cx,ax
sub dx,ax
jmp exit_Set_Together
;============================================
; 鼠标指定位置的座标和蛇头坐标的关系说明
; 当蛇头没有在指定范围内出现的时候,CX和DX的
;增减情况由DirectiveM数据表给出
; 当蛇头在指定范围内出现的时候,CX和DX的增减
;情况依然由DirectiveM数据表给出,同时指定坐标的
;横纵坐标值的增减情况也和CX与DX的增减情况相同
; 这样做是为了解决蛇移动到指定目标之后就立刻
;死亡的情况.
;============================================
exit_Set_Together:
;设定蛇头坐标
mov snake_H,cx
mov snake_H+2,dx
mov snake_B,cx
mov snake_B+2,dx
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
Set_the_CX_and_DX_Together endp
;**********************************
;鼠标位置校准函数
;游戏中出现的方块的中心必须遵守这样的
;规则:
;横坐标减去2之后可以被8整除
;中坐标可以直接被8整除
Balance_Shake proc near
push ax
push bx
;校准横坐标
mov ax,cx
sub ax,2
and ax,0007h
sub cx,ax
;校准纵坐标
mov ax,dx
and ax,0007h
sub dx,ax
pop bx
pop ax
ret
Balance_Shake endp
;**********************************.
;游戏结束时显示的信息'Game Over'
Dead_Msg proc near
push ax
push dx
mov dh,14
mov dl,26
mov al,'G'
call View_Video
inc dl
mov al,'a'
call View_Video
inc dl
mov al,'m'
call View_Video
inc dl
mov al,'e'
call View_Video
inc dl
mov al,' '
call View_Video
inc dl
mov al,' '
call View_Video
mov al,'O'
call View_Video
inc dl
mov al,'v'
call View_Video
inc dl
mov al,'e'
call View_Video
inc dl
mov al,'r'
call View_Video
call Waitf
call Waitf
call Waitf
call Waitf
call Waitf
call Waitf
pop dx
pop ax
ret
Dead_Msg endp
;*************************************
;按下'q'键时显示的信息'Save Information'
Quit_Msg proc near
push ax
push dx
mov dh,14
mov dl,26
mov al,'S'
call View_Video
inc dl
mov al,'a'
call View_Video
inc dl
mov al,'v'
call View_Video
inc dl
mov al,'e'
call View_Video
inc dl
mov al,' '
call View_Video
inc dl
mov al,' '
call View_Video
mov al,'I'
call View_Video
inc dl
mov al,'n'
call View_Video
inc dl
mov al,'f'
call View_Video
inc dl
mov al,'o'
call View_Video
inc dl
mov al,'r'
call View_Video
inc dl
mov al,'m'
call View_Video
mov al,'a'
call View_Video
inc dl
mov al,'t'
call View_Video
inc dl
mov al,'i'
call View_Video
inc dl
mov al,'n'
call View_Video
call Waitf
call Waitf
call Waitf
call Waitf
call Waitf
pop dx
pop ax
ret
Quit_Msg endp
code ends
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -