微机原理project,第一次用汇编写游戏,感觉还行,DOS窗口运行,小蛇有点难看……
这个程序可以实现速度的选择,成绩的显示,以及游戏终止等操作。
还有一些不足:判断小蛇是否触墙或是咬到自己的算法太占用内存,并且效率不高,可以有改进,如对屏幕字符的判读;延时程序和随机函数比较山寨;跳转指令比较乱(我再看一遍依已然不知所云了,真不知道当时怎么一句一句写出来的……)
DATAS SEGMENT
SNAKE DB "-============#$" ;@
BLOCK DB " ",13,10
DB " ",13,10
DB " +++++++++++ ++++++++++ ",13,10
DB " +++++++++++ ++++++++++ ",13,10
DB " ++ ++ ",13,10
DB " ++ +++++ ++ ",13,10
DB " ++ +++++ ++ ",13,10
DB " ++ ++ ",13,10
DB " ++ ++ ++ ++ ",13,10
DB " ++ +++ ++ ",13,10
DB " ++ +++ ++ ",13,10
DB " ++ ++ ++ ++ ",13,10
DB " ++ ++ ",13,10
DB " ++ ++ ",13,10
DB " ++ +++++ ++ ",13,10
DB " ++ +++++ ++ ",13,10
DB " ++ ++ ",13,10
DB " ++++++++++++++++++++++++ ",13,10
DB " ++++++++++++++++++++++++ ",13,10,"$"
COUNT EQU $-BLOCK
BLOCKPOSI DW 1000 DUP(0)
B_Length DW 0
Posi DW 100 DUP(0)
S_Length DW 14
COLS DB 0,24
ROWS DB 1,58
COL DW 23
ROW DW 55
Tail DW 26
HEAD DW ?
FOOD DW ?
NUMS DB 0
ANTI_DIR DB 75
CUR_DIR DB 77
CUR_DIR_2 DB 77
WAIT_TIME DW 0
WAIT_NUM DW 9
MSG3 DB "Choose Game Speed On Right Side$"
MSG1 DB "PRESS ANY KEY TO EXIT GAME$"
MSG2 DB "After Pressing ESC:$"
OVER DB "GAME OVER!$"
SPEED DB "Choose Game Speed:$"
NO DB "NORMAL$"
LO DB "LOW$"
FA DB "FAST$"
ENDPOSI DW 1040H
SPEED2 DW 0740H
SCORE DB "SCORE: $"
INFO DB "Snake By Jiangxl$"
RESTART DB "Restart$"
CONTINUE DB "Resume$"
STOP DB "Quit$"
CHOOSE DW 0
CHOICE DW 0
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
;设置光标
SETCUR MACRO
MOV AH,2
MOV BH,0
INT 10H
ENDM
;输出蛇
PUTCHAR MACRO CH
MOV AH,9
MOV AL,CH
MOV BH,0
MOV BL,1EH
MOV CX,1
INT 10H
ENDM
SHOWSCORE MACRO
MOV DX,0249H
SETCUR
MOV AH,0
MOV AL,NUMS
MOV DH,10
DIV DH
MOV BH,AH
MOV DL,AL
ADD DL,30H
MOV AH,2
INT 21H
MOV DL,BH
ADD DL,30H
INT 21H
ENDM
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS,ES:DATAS
START:
MOV AX,DATAS
MOV DS,AX
MOV ES,AX
;设定显示模式
MOV AH,0
MOV AL,3
INT 10H
;显示得分
MOV DX,0242H
SETCUR
LEA DX,SCORE
MOV AH,9
INT 21H
;显示速度
MOV DX,053DH
SETCUR
LEA DX,SPEED
MOV AH,9
INT 21H
;慢速
MOV DX,0742H
SETCUR
LEA DX,LO
MOV AH,9
INT 21H
;正常
MOV DX,0942H
SETCUR
LEA DX,NO
MOV AH,9
INT 21H
;快速
MOV DX,0B42H
SETCUR
LEA DX,FA
MOV AH,9
INT 21H
;红色边框
MOV AH,06
MOV AL,0
MOV BH,207
MOV CX,0
MOV DX,183BH
INT 10H
;我的信息
MOV DX,0016H
SETCUR
LEA DX,INFO
MOV AH,9
INT 21H
;终止信息
MOV DX,0E3DH
SETCUR
LEA DX,MSG2
MOV AH,9
INT 21H
MOV DX,1042H
SETCUR
LEA DX,RESTART
MOV AH,9
INT 21H
MOV DX,1242H
SETCUR
LEA DX,CONTINUE
MOV AH,9
INT 21H
MOV DX,1442H
SETCUR
LEA DX,STOP
MOV AH,9
INT 21H
;记录障碍物位置
MOV CX,COUNT
MOV SI,0
MOV DI,0
MOV DX,0200H
T1: CMP BLOCK[DI],' '
JZ T2
MOV BLOCKPOSI[SI],DX
ADD SI,2
INC B_Length
T2: INC DL
CMP DL,60
JB T3
MOV DL,0
INC DH
T3: INC DI
LOOP T1
RESTARTING:
;初始化
MOV SPEED2,0740H
MOV NUMS,0
SHOWSCORE
MOV S_Length,14
MOV Tail,26
MOV ANTI_DIR,75
MOV CUR_DIR,77
MOV CUR_DIR_2,77
;蓝色清屏
MOV AH,06
MOV AL,0
MOV BH,1EH
MOV CX,0102H
MOV DX,1739H
INT 10H
;隐藏光标
MOV CX,1000h
MOV AH,1
INT 10H
;选择速度
MOV DX,030CH
SETCUR
LEA DX,MSG3
MOV AH,9
INT 21H
CALL SET_SPEED
;显示障碍物
MOV DX,0200H
SETCUR
LEA DX,BLOCK
MOV AH,9
INT 21H
;中央显示黄色小蛇
MOV AH,06
MOV AL,0
MOV BH,1EH
MOV CX,030CH
MOV DX,0330H
INT 10H
MOV DX,030CH
SETCUR
LEA DX,SNAKE
MOV AH,9
INT 21H
;记录初始位置
MOV DX,030CH
ADD DX,S_Length
DEC DX
MOV CX,S_Length
MOV SI,0
G1: MOV Posi[SI],DX
DEC DX
ADD SI,2
LOOP G1
;初始食物
CALL PUT_FOOD
GAMESTART:
;监视键盘
MOV ENDPOSI,1040H
MOV AH,11H
INT 16H
JZ DELAY
MOV AH,10H
INT 16H
;ESC
CMP AL,1BH
JZ END2
;若方向相反则等待
CMP ANTI_DIR,AH
JZ GAMESTART
MOV CUR_DIR,AH
JMP SNAKE_MOVE
DELAY:
;延时
MOV AH,0
INT 1AH
CMP DX,WAIT_TIME
JB GAMESTART
ADD DX, WAIT_NUM
MOV WAIT_TIME, DX
MOV DX,02BBH ;循环次数
LB: XOR CX,CX
LA:
LOOP LA
DEC DX
JNZ LB
SNAKE_MOVE:
MOV DX,Posi[0]
UP:
CMP CUR_DIR,72
JNZ DOWN
DEC DH
MOV ANTI_DIR,80
JMP MOVE
LEFT:
CMP CUR_DIR,75
JNZ RIGHT
DEC DL
MOV ANTI_DIR,77
JMP MOVE
RIGHT:
CMP CUR_DIR,77
JNZ OTHER
INC DL
MOV ANTI_DIR,75
JMP MOVE
DOWN:
CMP CUR_DIR,80
JNZ LEFT
INC DH
MOV ANTI_DIR,72
JMP MOVE
OTHER:
MOV AL,CUR_DIR_2
MOV CUR_DIR,AL
JMP GAMESTART
MOVE:
;保留更新的蛇头坐标
MOV HEAD,DX
MOV AL,CUR_DIR
MOV CUR_DIR_2,AL
;更新位置坐标
MOV SI,Tail
MOV CX,S_Length
UPDATE:
MOV DX,Posi[SI]
MOV Posi[SI+2],DX
SUB SI,2
LOOP UPDATE
;判断是否吃到食物
MOV DX,HEAD
CMP DX,FOOD
JNZ MOVE_HEAD
INC NUMS
SHOWSCORE
ADD Tail,2
INC S_Length
MOV SI,Tail
MOV DX,Posi[SI]
MOV Posi[SI+2],DX
CALL PUT_FOOD
MOVE_HEAD:
;检查蛇头是否咬到自身,触墙
MOV AX,HEAD
LEA DI,Posi
MOV CX,S_Length
REPNZ SCASW
JZ END1
LEA DI,BLOCKPOSI
MOV CX,B_Length
REPNZ SCASW
JZ END1
MOV CX,2
LEA DI,ROWS
REPNZ SCASB
JZ END1
MOV CX,2
MOV AL,AH
LEA DI,COLS
REPNZ SCASB
JZ END1
;移动蛇头
MOV DX,Posi[0]
SETCUR
PUTCHAR '='
MOV DX,HEAD
MOV Posi[0],DX
SETCUR
PUTCHAR '#'
;移动蛇尾
MOV SI,Tail
MOV DX,Posi[SI]
SETCUR
PUTCHAR '-'
MOV DX,Posi[SI+2]
SETCUR
PUTCHAR ' '
JMP GAMESTART
END2:
MOV DX,1040H
SETCUR
PUTCHAR 01H
MOV DX,1240H
SETCUR
PUTCHAR ' '
MOV DX,1440H
SETCUR
PUTCHAR ' '
E2: MOV AH,0
INT 16H
CMP AL,0DH
JZ GETEND
MOV DX,ENDPOSI
SETCUR
PUTCHAR ' '
ADD DH,2
CMP DH,14H
JBE E1
MOV DH,10H
E1: MOV ENDPOSI,DX
SETCUR
PUTCHAR 01H
JMP E2
GETEND:
MOV AH,06
MOV AL,0
MOV BH,07H
MOV CX,1040H
MOV DX,1440H
INT 10H
MOV DX,ENDPOSI
CMP DX,1040H
JNZ C1
JMP RESTARTING
C1: CMP DX,1240H
JNZ C2
JMP GAMESTART
C2: JMP END_FINAL
END1:
;清屏
MOV AH,06
MOV AL,0
MOV BH,4FH
MOV CX,0A14H
MOV DX,1024H
INT 10H
MOV DX,0B18H
SETCUR
LEA DX,OVER
MOV AH,9
INT 21H
MOV DX,0D16H
SETCUR
PUTCHAR 01H
MOV DX,0F16H
SETCUR
PUTCHAR ' '
MOV DX,0D18H
SETCUR
LEA DX,RESTART
MOV AH,9
INT 21H
MOV DX,0F18H
SETCUR
LEA DX,STOP
MOV AH,9
INT 21H
MOV CHOOSE,0
MOV CHOICE,0
WAIT_INPUT2:
MOV AH,0
INT 16H
CMP AL,0DH
JZ SET_GO2
SELECT2:
INC CHOOSE
CWD
MOV AX,CHOOSE
MOV CX,2
DIV CX
MOV CHOICE,DX
CMP DX,0
JNZ S2
MOV DX,0D16H
SETCUR
PUTCHAR 01H
MOV DX,0F16H
SETCUR
PUTCHAR ' '
JMP WAIT_INPUT2
S2:
MOV DX,0D16H
SETCUR
PUTCHAR ' '
MOV DX,0F16H
SETCUR
PUTCHAR 01H
JMP WAIT_INPUT2
SET_GO2:
CMP CHOICE,0
JZ RESTARTING
END_FINAL:
MOV BH,4FH
MOV DX,0612H
SETCUR
LEA DX,MSG1
MOV AH,9
INT 21H
W: MOV AH,1
INT 16H
JZ W
MOV AH,4CH
INT 21H
SET_SPEED PROC
MOV DX,0740H
SETCUR
PUTCHAR 01H
MOV DX,0940H
SETCUR
PUTCHAR ' '
MOV DX,0B40H
SETCUR
PUTCHAR ' '
P2: MOV AH,0
INT 16H
CMP AL,0DH
JZ GETSET
MOV DX,SPEED2
SETCUR
PUTCHAR ' '
ADD DH,2
CMP DH,0BH
JBE P1
MOV DH,07H
P1: MOV SPEED2,DX
SETCUR
PUTCHAR 01H
JMP P2
GETSET:
MOV AH,06
MOV AL,0
MOV BH,07H
MOV CX,0740H
MOV DX,0B40H
INT 10H
MOV DX,SPEED2
SETCUR
PUTCHAR 01H
CMP DX,0740H
JNZ N
MOV WAIT_NUM,8
JMP RETURN
N: CMP DX,0940H
JNZ F
MOV WAIT_NUM,4
JMP RETURN
F: MOV WAIT_NUM,0
RETURN:
RET
SET_SPEED ENDP
;随机放置食物
PUT_FOOD PROC
REPUT:
;取时钟滴答数
MOV AH,0
INT 1AH
;计算行号
MOV BX,DX
MOV AX,DX
XOR DX,DX
DIV COL
INC DX
MOV CX,DX
;计算列号
MOV AX,BX
XOR DX,DX
DIV ROW
ADD DX,2
MOV DH,CL
MOV FOOD,DX
;检查食物位置是否被小蛇占据
MOV AX,DX
LEA DI,Posi
MOV CX,S_Length
REPNZ SCASW
;发现被占据,则重新生成
JZ REPUT
LEA DI,BLOCKPOSI
MOV CX,B_Length
REPNZ SCASW
JZ REPUT
;否则在该位置放置食物
SETCUR
PUTCHAR 01H
RET
PUT_FOOD ENDP
CODES ENDS
END START