📄 snake.asm
字号:
.486
;-------------------------------------------------------------------------------
;(1) 清空键盘缓冲区
ckbuf macro
push ds
push ax
push bx
MOV AL, 0BH
MOV AH, 0CH
INT 21H
pop bx
pop ax
pop ds
endm
;-------------------------------------------------------------------------------
;(2) 产生0-n的随机数宏定义
;返回值存ah寄存器
rand macro n
push cx
push dx
xor ah,ah
int 1ah
mov ax,dx
and ax,07fh
mov dl,n
div dl
pop dx
pop cx
endm
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
DATA SEGMENT USE16
BODY DB '-O#' ;3个
DB 50 DUP('a')
;设置蛇的每个字符的初始位置坐标 (行号,列号)
COOR DB 13,23, 13,24, 13,25, 13,26
DB 13,27, 13,28, 13,29, 13,30
DB 13,31, 13,32, 13,33, 13,34
DB 13,35, 13,36
;设置蛇最大可增加 50 个长度
TAIL DB 100 DUP(?)
;设置蛇的当前长度,初始为3
LENG DB 3
DIRECTION DB 72
FOOD DB 10,10
SCOINFO DB 'SOORE:$'
SCORE DB 0H
SCOCHAR DB 4 DUP('0')
DB '$'
PAUSEINFO DB 'PAUSE--Pagedown$'
EXITINFO DB 'EXIT --Esc$'
CTRINFO DB 'Change Direction$'
CTRINFO2 DB 'with Dirction Key$'
N EQU 10000
TEN2 DW 10
DATA ENDS
STACK SEGMENT STACK
DB 100 DUP(?)
STACK ENDS
CODE SEGMENT USE16
ASSUME CS:CODE,DS:DATA,SS:STACK
START:
MOV AX,DATA
MOV DS,AX
CALL CLEARS
CALL GENFOOD
CALL SHOWINFO
;设置CTRINFO光标位置
PUSH SI
MOV AH,02H
MOV BH,0
MOV DH, 1
MOV DL, 60
INT 10H
;显示CTRINFO
MOV AH,9
MOV DX,OFFSET CTRINFO
INT 21H
;设置CTRINFO2光标位置
PUSH SI
MOV AH,02H
MOV BH,0
MOV DH, 2
MOV DL, 60
INT 10H
;显示CTRINFO2
MOV AH,9
MOV DX,OFFSET CTRINFO2
INT 21H
;设置PAUSEINFO光标位置
PUSH SI
MOV AH,02H
MOV BH,0
MOV DH, 5
MOV DL, 62
INT 10H
;显示PAUINFO
MOV AH,9
MOV DX,OFFSET PAUSEINFO
INT 21H
;设置EXITINFO光标位置
PUSH SI
MOV AH,02H
MOV BH,0
MOV DH, 4
MOV DL, 62
INT 10H
;显示EXITINFO
MOV AH,9
MOV DX,OFFSET EXITINFO
INT 21H
;-------------------------------------------
MOV CX,3000
L1: PUSH CX
CALL DELAY
CALL MOVESTEP
CALL SHOWBODY
POP CX
LOOP L1
SCAN:
MOV AH,1
INT 16H
JZ SCAN
SCAN2:
MOV AH,1
INT 16H
JZ SCAN2
LAST:
MOV AH, 4CH
INT 21H
;-------------------------------------------------------------------------------
;(1) 设置彩色文本方式+清屏+清除光标的子程序
CLEARS PROC
;设置屏幕显示方式为80×25的彩色文本方式
MOV AH,00H
MOV AL,3
INT 10H
; 先用蓝色清屏
MOV AH,6
MOV AL,0
MOV BH,10H
MOV CX,0
MOV DL,59
MOV DH,24
INT 10H
;清除光标
MOV AH,01H
MOV CH,20H
INT 10H
RET
ENDP
;-------------------------------------------------------------------------------
;(2) 从COORD为尾部的坐标开始,按照BODYY中的字符,
; 写内存LENGT中表示数字个字符到屏幕上的子程序
SHOWBODY PROC
MOV SI,OFFSET LENG
MOV CL, [SI]
MOV CH, 0H
MOV SI,OFFSET COOR
MOV DI,OFFSET BODY
SL1: ;设置光标位置
MOV AH,02H
MOV BH,0
MOV DH,[SI]
MOV DL,[SI+1]
INT 10H
;在当前光标位置处写字符
MOV AH,09H
PUSH CX ;保存CX的值
MOV AL,[DI]
MOV BH,0
MOV BL,1FH
MOV CX,1
INT 10H
POP CX
ADD SI,2
ADD DI,1
LOOP SL1
RET
ENDP
;-------------------------------------------------------------------------------
;(3)延时子程序
DELAY PROC
MOV CX,N
DL2:
PUSH CX
MOV CX,N
DL1:
LOOP DL1
POP CX
LOOP DL2
MOV AH,1
INT 16H
MOV DX,N
JNZ DL3
JMP DL4
DL3: CALL GETCHAR
CKBUF
DL4:
RET
ENDP
;-------------------------------------------------------------------------------
;(4)按照参数方向移动一步,同时擦去尾巴 的子程序
;即直接改变COOR中的坐标 ,LENGT为蛇当前长度
MOVESTEP PROC
MOV SI,OFFSET COOR ;先擦尾巴
MOV AH,02H
MOV BH,0
MOV DH,[SI]
MOV DL,[SI+1]
INT 10H
;在当前光标位置处写空白
MOV AH,09H
MOV AL,0H
MOV BH,0
MOV BL,1FH
MOV CX,1
INT 10H
;先将除头部外的坐标 前一个 放到 后一个 从后向前
MOV SI,OFFSET LENG
MOV CL, [SI]
MOV CH, 0H
DEC CX
MOV SI,OFFSET COOR
MLL: MOV AX, WORD PTR [SI+2]
MOV WORD PTR [SI],AX
ADD SI,2
LOOP MLL
;然后根据 DIRECTION 的不同值改变头部坐标
; 判断是否到达边界并修改坐标
;此时 SI 指的是头部坐标的内存位置
MOV DI,OFFSET DIRECTION
MOV DL,[DI]
CMP DL,77
JE ML0
CMP DL,72
JE ML1
CMP DL,75
JE ML2
CMP DL,80
JE ML3
ML0: ;INC BYTE PTR [SI+1]
MOV AL,[SI+1]
XOR AH,AH
INC AX
MOV BL,60
DIV BL
MOV [SI+1],AH
JMP MLEND1
ML1: ;DEC BYTE PTR [SI]
MOV AL,[SI]
XOR AH,AH
DEC AX
ADD AX,25
MOV BL,25
DIV BL
MOV [SI],AH
JMP MLEND1
ML2: ;DEC BYTE PTR [SI+1]
MOV AL,[SI+1]
XOR AH,AH
DEC AX
ADD AX,60
MOV BL,60
DIV BL
MOV [SI+1],AH
JMP MLEND1
ML3: ;INC BYTE PTR [SI]
MOV AL,[SI]
XOR AH,AH
INC AX
MOV BL,25
DIV BL
MOV [SI],AH
MLEND1: ;判断是否碰到食物,若是,则根据当前方向增长头部
MOV AX,WORD PTR [SI]
MOV DI,OFFSET FOOD
MOV BX,[DI]
CMP AX,BX
JNE MLEND2
MOV DI,OFFSET LENG
MOV AL,[DI]
XOR AH,AH
DEC AX
INC BYTE PTR [DI]
MOV DI,OFFSET BODY
ADD DI,AX
MOV BYTE PTR [DI], 'O'
MOV BYTE PTR [DI+1], '#'
MOV DI,OFFSET SCORE
INC BYTE PTR [DI]
CALL SHOWINFO
;根据方向修改增长后的头部坐标 ,此时 SI 指向原来的头部
MOV DI,OFFSET DIRECTION
MOV AL,[DI]
CMP AL,77
JE ML00
CMP AL,72
JE ML01
CMP AL,75
JE ML02
CMP AL,80
JE ML03
ML00: MOV AL,[SI+1]
XOR AH,AH
INC AX
MOV BL,60
DIV BL
MOV [SI+3],AH
MOV BL,[SI]
MOV [SI+2],BL
JMP MFOOD
ML01: MOV AL,[SI]
XOR AH,AH
DEC AX
ADD AX,25
MOV BL,25
DIV BL
MOV [SI+2],AH
MOV BL,[SI+1]
MOV [SI+3],BL
JMP MFOOD
ML02: MOV AL,[SI+1]
XOR AH,AH
DEC AX
ADD AX,60
MOV BL,60
DIV BL
MOV [SI+3],AH
MOV BL,[SI]
MOV [SI+2],BL
JMP MFOOD
ML03: MOV AL,[SI]
XOR AH,AH
INC AX
MOV BL,25
DIV BL
MOV [SI+2],AH
MOV BL,[SI+1]
MOV [SI+3],BL
MFOOD:
CALL GENFOOD
MLEND2:
;
RET
ENDP
;-------------------------------------------------------------------------------
;(5) 读取键盘输入并根据输入和原来的方向改变DIRECTION 的子程序 ,
; 并判断是否暂停
GETCHAR PROC NEAR
MOV AH,0H
INT 16H
cmp ah,01 ;为ESC键吗?
JE GEL2
CMP AH,81 ;先判断是否是Pagedown暂停
JE GEL1
MOV BL,AH
XOR BH,BH
MOV SI,OFFSET DIRECTION
MOV AL,[SI]
XOR AH,AH
ADD AX,BX
CMP AX, 152
JE GEND
MOV [SI],BL
JMP GEND
GEL1: CKBUF
MOV AH,0H
INT 16H
CMP AH,01
JE GEL2
CMP AH,81
JNE GEL1
JMP GEND
GEL2: MOV AH,4CH
INT 21H
GEND:
;CKBUF
RET
ENDP
;-------------------------------------------------------------------------------
;(6) 在 FOOD 内存 随机产生一个 坐标,并显示食物
GENFOOD PROC NEAR
GENL1:
RAND 24
MOV BL,AH
RAND 59
MOV BH,AH
MOV SI,OFFSET LENG
MOV CX,[SI]
MOV SI,OFFSET COOR
GENL2:
CMP BX,WORD PTR [SI]
JE GENL1
ADD SI,2
LOOP GENL2
MOV SI,OFFSET FOOD
MOV [SI],BX
;设置光标位置
MOV AH,02H
MOV BH,0
MOV DH,[SI]
MOV DL,[SI+1]
INT 10H
;在当前光标位置处写字符
MOV AH,09H
MOV AL,'@'
MOV BH,0
MOV BL,1FH
MOV CX,1
INT 10H
RET
ENDP
;-------------------------------------------------------------------------------
; (7) 显示信息子程序
SHOWINFO PROC NEAR
;设置SCOINFO光标位置
PUSH SI
MOV AH,02H
MOV BH,0
MOV DH, 13
MOV DL, 67
INT 10H
;显示INFO
MOV AH,9
MOV DX,OFFSET SCOINFO
INT 21H
;转化SOCOE为SCORECHAR并显示
MOV SI,OFFSET SCOCHAR+3
MOV DI,OFFSET SCORE
MOV AL,[DI]
XOR AH,AH
MOV DX, 0H
MOV CX, 4
SLL1:DIV TEN2
MOV DI,AX
MOV AL,DL
ADD AL,30H
MOV [SI],AL
MOV AX,DI
DEC SI
MOV DX,0H
LOOP SLL1
MOV AH,9
MOV DX,OFFSET SCOCHAR
INT 21H
POP SI
RET
ENDP
CODE ENDS
END START
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -