现在的位置: 首页 > 综合 > 正文

汇编写的贪吃蛇的程序(别人写的,我把注释全部写上了,下次我重写一个代码更简洁的)

2013年10月22日 ⁄ 综合 ⁄ 共 8043字 ⁄ 字号 评论关闭

DATA SEGMENT PARA PUBLIC 'DATA'
X DW 40
Y DW 40
MUL_RAX DB 3
GEWEI DB 0 ;个位
SHIWEI DB 0 ;十位
BAIWEI DB 0 ;百位
QIANWEI DB 0 ;千位
WANWEI DB 0 ;万位
S_HEAD_X DW ? ;蛇头X轴坐标
S_HEAD_Y DW ? ;蛇头Y轴坐标
S_TAIL_X DW ? ;蛇尾X轴坐标
S_TAIL_Y DW ? ;蛇尾Y轴坐标
S_LENGTH DW 100 ;蛇初始长度为100
EGG_X DW 50 ;初始化蛋的X轴坐标
EGG_Y DW 150 ;初始化蛋的Y轴坐标
EGG_X_D DW ?
EGG_Y_R DW ?
S_DIRTIN DB 4 ;蛇头的方向,上1(X--,Y),下2(X++,Y)
; 左3(X,Y--),右4(X,Y++)
C_SPEED DB 'GAME SPEED(1-5):$'
SPEED DW 100
S_RADIX DB ?
TEMP_DIR DB 4
TEMPX DW ? ;蛇尾X轴坐标的临时存放单元
TEMPY DW ? ;蛇尾Y轴坐标的临时存放单元
CHAR DB 'Play Again?(Y/N)$'
UP DB ? ;上
DOWN DB ? ;下
LEFT DB ? ;左
RIGHT DB ? ;右
SUP EQU 48H ;上的扫描码
SDOWN EQU 50H ;下的扫描码
SLEFT EQU 4BH ;左的扫描码
SRIGHT EQU 4DH ;右的扫描码
SESC EQU 01H ;ESC的扫描码
SKEYN EQU 31H ;N的扫描码
SKEYL EQU 26H ;L的扫描码
SKEYS EQU 1FH ;S的扫描码
SKEYQ EQU 10H ;Q的扫描码
NGAME DB 'New game',0AH,0DH,'$'
LGAME DB 'Load game',0AH,0DH,'$'
SGAME DB 'Save game',0AH,0DH,'$'
QGAME DB 'Quit game$'
GMENU DW 8 DUP (?)
DATA ENDS

STACK SEGMENT PARA STACK 'STACK'
DW 256 DUP (0)
STACK ENDS

CODE SEGMENT PARA PUBLIC 'CODE'
PROC1 PROC FAR
ASSUME CS:CODE,DS:DATA,SS:STACK
START:
PUSH DS;1kb=1024字节=512个字
MOV AX,0
PUSH AX
MOV AX,DATA
MOV DS,AX
AGAIN:
MOV GEWEI,0
MOV SHIWEI,0
MOV BAIWEI,0
MOV QIANWEI,0
MOV WANWEI,0
MOV EGG_X,50
MOV EGG_Y,150
MOV S_DIRTIN,4
MOV TEMP_DIR,4
;
MOV AH,6
MOV BH,0
MOV AL,0
XOR CX,CX;异或运算,相异为真,相同为假
MOV DX,184FH
INT 10H ;清屏

MOV AH,0
MOV AL,12H
INT 10H ;设置显示模式为640*480,16色

REINPUT:
MOV AH,2;置光标位置
MOV BH,0
MOV DH,0
MOV DL,0
INT 10H
MOV AH,9
MOV DX,OFFSET C_SPEED
INT 21H;显示数据
MOV SPEED,10
MOV AH,1;键盘输入并回显,al=输入的内容
INT 21H
SUB AL,30H;字符转成数字
CMP AL,1;如果为1
JAE N23;高于等于1转移n23,用于无符号数进行转移,只有大于等于1才会执行
MOV AH,2;置光标位置
MOV BH,0;页号
MOV DH,0;行
MOV DL,16;列
INT 10H
MOV DX,' ';dos2号功能中断,dl=输出字符
INT 21H
JMP REINPUT;因为不是输入1---5,回去循环
N23: CMP AL,5
JBE N24;低于等于时转移
MOV AH,2;置光标位置
MOV BH,0
MOV DH,0
MOV DL,16
INT 10H
MOV DX,' '
INT 21H
JMP REINPUT;跑回开始处
N24:
MUL MUL_RAX;乘法
MOV CL,AL
SHL SPEED,CL ;设置游戏速度,speed左移cl

MOV AH,0
MOV AL,12H
INT 10H;设置显示方式

MOV CX,29;列0-639
MOV DX,29;行1-199
LH1:
MOV AH,0CH
MOV BH,0
MOV AL,0fH;色彩为白色
INT 10H;写象素到屏幕上
INC DX;dx=dx-1
CMP DX,449
JBE LH1;低于等于 从上到下,就是从29行29列一个象素一个象素的往449行,29列走
MOV DX,29
ADD CX,500;列加500 往后写象素,重复,只是列不动而已!
CMP CX,640;比较
JA LV1;大于转移
JB LH1;低于转移
LV1:
MOV DX,29
MOV CX,29
LV2: MOV AH,0CH;同样的道理
MOV BH,0
MOV AL,0FH
INT 10H
INC CX
CMP CX,529
JBE LV2
MOV CX,29
ADD DX,420
CMP DX,480
JA INIT
JB LV2 ;画边框,左上角坐标(29,29)右下角坐标(449,529)

INIT:
MOV S_HEAD_X,350
MOV S_HEAD_Y,150;初始化蛇头的坐标
MOV S_TAIL_X,350
MOV S_TAIL_Y,50;初始化蛇屁股的坐标
MOV DX,S_TAIL_X
MOV CX,S_TAIL_Y;蛇屁股的坐标放进ds,cs
A: MOV AH,0CH
MOV AL,2;象素值
MOV BH,0
INT 10H
INC CX
CMP CX,150
JBE A ;初始蛇的位置

MOV DX,EGG_X;这到jbe bca的代码是一个for内层循环,画一个7*7的方框,此代码膜拜
BCA: MOV CX,EGG_Y
ABC: MOV AH,0CH ;初始蛋的位置
MOV AL,0CH
MOV BH,0
INT 10H
INC CX
CMP CX,156
JBE ABC;低于等于时转到abc,其实再往上经过一轮循环,列坐标是7
INC DX
CMP DX,56
JBE BCA;同上,其实行坐标是7
;结束初始蛋的位置

MOV AH,2;光标位置
MOV BH,0
MOV DH,3;行
MOV DL,68;列
INT 10H
MOV AH,9
MOV DX,OFFSET NGAME
INT 21H
MOV AH,2
MOV BH,0
MOV DH,4
MOV DL,68
INT 10H
MOV AH,9
MOV DX,OFFSET LGAME
INT 21H
MOV AH,2
MOV BH,0
MOV DH,5
MOV DL,68
INT 10H
MOV AH,9
MOV DX,OFFSET SGAME
INT 21H
MOV AH,2
MOV BH,0
MOV DH,6
MOV DL,68
INT 10H
MOV AH,9
MOV DX,OFFSET QGAME
INT 21H ;在右上角显示菜单

MOV AH,2
MOV BH,0
MOV DH,0
MOV DL,0
INT 10H
MOV AH,2
MOV DX,30H;输出0
INT 21H
MOV AH,2
MOV BH,0
MOV DH,0
MOV DL,1
INT 10H
MOV AH,2
MOV DX,30H;输出0
INT 21H
MOV AH,2
MOV BH,0
MOV DH,0
MOV DL,2
INT 10H
MOV AH,2
MOV DX,30H
INT 21H;输出0
MOV AH,2
MOV BH,0
MOV DH,0
MOV DL,3
INT 10H
MOV AH,2
MOV DX,30H
INT 21H;输出0
MOV AH,2
MOV BH,0
MOV DH,0
MOV DL,4
INT 10H
MOV AH,2
MOV DX,30H
INT 21H;输出0

JMP BG

TTTT: JMP RP

BG:
INC X;这个x和y这个40是怎么计算出来的,原来是初始化的蛋蛋坐标,这里可以随便改!
CMP X,400
JBE CONT1;小于等于
MOV X,40
CONT1: INC Y
CMP Y,500
JBE CONT2
MOV Y,40

CONT2:
CMP S_DIRTIN,1;方向上
JZ S_UP
CMP S_DIRTIN,2;方向下
JZ S_DOWN
CMP S_DIRTIN,3;方向左
JZ S_LEFT
CMP S_DIRTIN,4;方向右
JZ S_RIGHT

S_UP:
CMP TEMP_DIR,2;temp_dir是什么意思,暂时还没看出来,暂时认为的是当前方向是右
JNZ QUIT1;如果当前方向不为下,转至quit1
MOV S_DIRTIN,2;
JMP S_DOWN;转到下!
QUIT1:
MOV BX,SPEED ;延迟,speed=100
Y1: MOV CX,10 ;延迟
X1: LOOP X1;无语,极度无语,是不是汇编所有的延迟都是这个屁样子,浪费CPU的时间
DEC BX
JNZ Y1;bx!=0时,跑100*10=1000;强大的原作者,他为什么不直接设置成1000得了难道是想多浪费两条指令的CPU跑100次?

DEC S_HEAD_X
CMP S_HEAD_X,29;行坐标,框框的上行坐标是29
JBE TTTT;低于,等于跑到tttt.碰到边框了就OVER
JMP NEXT;否则接着跑
S_DOWN:
CMP TEMP_DIR,1
JNZ QUIT2
MOV S_DIRTIN,1
JMP S_UP
QUIT2: MOV BX,SPEED ;延迟
Y2: MOV CX,10 ;延迟
X2: LOOP X2
DEC BX
JNZ Y2
INC S_HEAD_X
CMP S_HEAD_X,449
JAE RP
JMP NEXT
S_LEFT:CMP TEMP_DIR,4
JNZ QUIT3
MOV S_DIRTIN,4
JMP S_RIGHT
QUIT3: MOV BX,SPEED ;延迟
Y3: MOV CX,10 ;延迟
X3: LOOP X3
DEC BX
JNZ Y3
DEC S_HEAD_Y
CMP S_HEAD_Y,29
JBE RP
JMP NEXT
S_RIGHT:CMP TEMP_DIR,3
JNZ QUIT4
MOV S_DIRTIN,3
JMP S_LEFT
QUIT4: MOV BX,SPEED ;延迟
Y4: MOV CX,10 ;延迟
X4: LOOP X4
DEC BX
JNZ Y4
INC S_HEAD_Y
CMP S_HEAD_Y,529
JAE RP
JMP NEXT
JMP DDD
RP: JMP RP1
DDD:

NEXT:
MOV AH,0DH;读象素
MOV BH,0
MOV DX,S_HEAD_X;行坐标,
MOV CX,S_HEAD_Y;列坐标
INT 10H
CMP AL,2;AL=象素值,如果前面行坐标的象素等于本身的象素,就是碰到一起哒!
JZ RP
MOV AH,0DH
MOV BH,0
MOV DX,S_HEAD_X
MOV CX,S_HEAD_Y
INT 10H
CMP AL,0CH;如果前面的象素是蛋蛋的象素,下面的代码则转-----------------------------------明天接着看,睡觉去了!
JZ ADDTAIL1
PHEAD:
MOV AH,0CH
MOV AL,2
MOV BH,0
MOV DX,S_HEAD_X;往上写了一个象素,就是蛇往(上下左右)走了一下
MOV CX,S_HEAD_Y
INT 10H

JMP WWW
ADDTAIL1:JMP ADDTAIL
WWW:
;--------------------------------------------------------------
;说实话,这段代码写的真不怎么样,屁股坐标用来判断方向的,其实完全可以用上面的temp_dir来判断方法,然后改变屁股坐标的值
MOV AX,S_TAIL_X
MOV TEMPX,AX
MOV AX,S_TAIL_Y
MOV TEMPY,AX
DEC S_TAIL_X
MOV AH,0DH
MOV BH,0
MOV DX,S_TAIL_X
MOV CX,S_TAIL_Y
INT 10H
CMP AL,2
JZ NEXT1;
INC S_TAIL_X
INC S_TAIL_Y
MOV AH,0DH
MOV BH,0
MOV DX,S_TAIL_X
MOV CX,S_TAIL_Y
INT 10H
CMP AL,2
JZ NEXT1
INC S_TAIL_X;
DEC S_TAIL_Y;
MOV AH,0DH
MOV BH,0
MOV DX,S_TAIL_X
MOV CX,S_TAIL_Y
INT 10H
CMP AL,2
JZ NEXT1
DEC S_TAIL_X
DEC S_TAIL_Y
MOV AH,0DH
MOV BH,0
MOV DX,S_TAIL_X
MOV CX,S_TAIL_Y
INT 10H
JMP NEXT1
;----------------------------------------------------------------------------------

JMP TTT
NEXT1: JMP NEXT2
TTT:

JMP RRR
ADDTAIL:
CALL DISPNUM;设置左上角数字的
MOV AX,EGG_X;EGG_X行坐标,egg_y列坐标
MOV EGG_X_D,AX
ADD EGG_X_D,7;egg_x_d+7,为什么是7而不是6!上面说得很明白了!
MOV AX,EGG_Y;列坐标
MOV EGG_Y_R,AX;
ADD EGG_Y_R,7;列坐标+7
MOV DX,EGG_X
ZYX: MOV CX,EGG_Y
XYZ:
MOV AH,0CH
MOV BH,0
MOV AL,0
INT 10H
INC CX
CMP CX,EGG_Y_R
JB XYZ
INC DX
CMP DX,EGG_X_D
JB ZYX;以上代码是把蛋蛋的象素变成0

REMOVE:
MOV AX,X;
MOV EGG_X,AX
ADD AX,7
MOV EGG_X_D,AX;行坐标+7
MOV AX,Y
MOV EGG_Y,AX
ADD AX,7
MOV EGG_Y_R,AX;列坐标+7

MOV DX,EGG_X
BBA: MOV CX,EGG_Y
ABB: MOV AH,0DH
MOV BH,0
INT 10H
CMP AL,2
JNZ NEXT4;zf=0,转到标号处
ADD X,10;如果EGG_X和EGG_Y上有象素则x和Y加10
ADD Y,10
CMP X,400
JB REMOVE
JA ZZZ
CMP Y,500
JB REMOVE
ZZZ: MOV X,40
MOV Y,40
JMP REMOVE
NEXT4:
INC CX
CMP CX,EGG_Y_R
JB ABB;低于转移
INC DX
CMP DX,EGG_X_D
JB BBA;以上的代码是在后面那个蛋蛋吃掉以后,新建一个,但前提是在7*7的框框里看有没有蛇的象素
MOV AX,X
MOV EGG_X,AX
ADD AX,7
MOV EGG_X_D,AX
MOV AX,Y
MOV EGG_Y,AX
ADD AX,7
MOV EGG_Y_R,AX
MOV DX,EGG_X
HJK: MOV CX,EGG_Y
KJH: MOV AH,0CH
MOV AL,0CH
MOV BH,0
INT 10H
INC CX
CMP CX,EGG_Y_R
JB KJH
INC DX
CMP DX,EGG_X_D
JB HJK;以上代码是画出一个蛋蛋!
MOV AH,0CH
MOV BH,0
MOV AL,2
MOV DX,TEMPX
MOV CX,TEMPY
INT 10H
MOV AX,TEMPX
MOV S_TAIL_X,AX
MOV AX,TEMPY
MOV S_TAIL_Y,AX
JMP PHEAD
RRR:

NEXT2:
MOV AH,0CH
MOV AL,0
MOV BH,0
MOV DX,TEMPX;把屁股变成黑象素,就是没了
MOV CX,TEMPY
INT 10H

MOV AH,S_DIRTIN
MOV TEMP_DIR,AH;TEMP_DIR 当前方向
MOV AH,1
INT 16H;al有字符,zf=0,无字符zf=1
JZ BG1
MOV AH,0 ;取走键盘缓冲区中的内容,以便在以后的循环中INT16的1号功能可以接收字符
INT 16H
CMP AH,SUP
JZ SU
CMP AH,SDOWN
JZ SD
CMP AH,SLEFT
JZ SL
CMP AH,SRIGHT
JZ SR
CMP AH,SESC
JZ PAUSE
JMP BG
SU: MOV S_DIRTIN,1
JMP BG
SD: MOV S_DIRTIN,2
JMP BG
SL: MOV S_DIRTIN,3
JMP BG
SR: MOV S_DIRTIN,4
JMP BG

PAUSE: MOV DX,29
MENUB2:MOV CX,539
MENUB1:MOV AH,0CH
MOV AL,1
MOV BH,0
INT 10H
INC CX
CMP CX,629
JB MENUB1
ADD DX,100
CMP DX,130
JB MENUB2

JMP BBB
BG1:
; mov bx,100
;as:mov cx,100
;bs:loop bs
;
;dec bx
;jnz as
;-开始我一直没弄明白,作者写下面的代码是什么意思,简单就是无用功,后面自己一试,才知道,作者是在浪费cpu的时间,来达到控制速度的目的
;所以,你大可把以下的代码一直到jmp bg之前的代码都注掉,换成我上面注的代码,效果是一样的!
MOV DX,29
MENUB4:MOV CX,539
MENUB3:MOV AH,0CH
MOV AL,0
MOV BH,0
INT 10H
INC CX
CMP CX,629
JB MENUB3;低于,不高于
ADD DX,100
CMP DX,130
JB MENUB4
MOV CX,539
MOV DX,29
MENUA3:MOV AH,0CH
MOV AL,0
MOV BH,0
INT 10H
INC DX
CMP DX,130
JB MENUA3
MOV CX,629
MOV DX,29
MENUA4:MOV AH,0CH
MOV AL,0
MOV BH,0
INT 10H
INC DX
CMP DX,130
JB MENUA4
JMP BG
BBB:

MOV CX,539
MOV DX,29
MENUA1:MOV AH,0CH
MOV AL,1
MOV BH,0
INT 10H
INC DX
CMP DX,130
JB MENUA1
MOV CX,629
MOV DX,29
MENUA2:MOV AH,0CH
MOV AL,1
MOV BH,0
INT 10H
INC DX
CMP DX,130
JB MENUA2
MOV AH,0
INT 16H
CMP AH,SESC
JZ BG1
CMP AH,SKEYN
JZ AGAIN1
CMP AH,SKEYL
JZ LOADGAME
CMP AH,SKEYS
JZ SAVEGAME
CMP AH,SKEYQ
JZ QUIT
JMP PAUSE

JMP CCC
AGAIN1:JMP AGAIN
CCC:

RP1: MOV AH,2
MOV BH,0
MOV DH,14
MOV DL,26
INT 10H
MOV AH,9
MOV DX,OFFSET CHAR
INT 21H;显示那段字符串,意思是gameover
ASK: MOV AH,0
INT 16H
CMP AL,59H
JZ AGAIN1
CMP AL,79H
JZ AGAIN1
CMP AL,4EH
JZ QUIT
CMP AL,6EH
JZ QUIT
JMP ASK
QUIT:
MOV AH,0
MOV AL,3
INT 10H
RET
PROC1 ENDP
DISPNUM PROC NEAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX

INC GEWEI
CMP GEWEI,9
JBE DISP;低于等于转移
MOV GEWEI,0
INC SHIWEI
CMP SHIWEI,9
JBE DISP
MOV SHIWEI,0
INC BAIWEI
CMP BAIWEI,9
JBE DISP
MOV BAIWEI,0
INC QIANWEI
CMP QIANWEI,9
JBE DISP
MOV QIANWEI,0
INC WANWEI
CMP WANWEI,9
JBE DISP
MOV WANWEI,0
DISP: MOV AH,2;00设置光标
MOV BH,0
MOV DH,0
MOV DL,0
INT 10H
MOV AH,2;显示字符, dl=输出字符
MOV DL,WANWEI
ADD DL,30H
INT 21H
MOV AH,2;设置光标
MOV BH,0
MOV DH,0
MOV DL,1
INT 10H
MOV AH,2;输出字符,千位!
MOV DL,QIANWEI
ADD DL,30H
INT 21H
MOV AH,2;设置光标
MOV BH,0
MOV DH,0
MOV DL,2
INT 10H
MOV AH,2;输出字符,百位!
MOV DL,BAIWEI
ADD DL,30H
INT 21H
MOV AH,2;设置光标
MOV BH,0
MOV DH,0
MOV DL,3
INT 10H
MOV AH,2;输出字符,十位
MOV DL,SHIWEI
ADD DL,30H
INT 21H
MOV AH,2
MOV BH,0
MOV DH,0
MOV DL,4
INT 10H
MOV AH,2
MOV DL,GEWEI
ADD DL,30H
INT 21H

POP DX
POP CX
POP BX
POP AX

RET
DISPNUM ENDP

CODE ENDS
END START

抱歉!评论已关闭.