DOS下的贪吃蛇游戏

          这是我学BIOS阶段用X86汇编写的贪吃蛇游戏,虽然现在不做BIOS了,还是无比怀念那段学习岁月。

       和大家共享,代码如下,有点长,呵呵

        特点:在DOS下和windows系统下都可以运行,得到10分,会升级,升级时蜂鸣器会响。

;===========================================================[]
; Function :snake
; Designer :zzobin
; Create Date :2009.3.13
;-----------------------------------------------------------[]
;----------------------| Program Start |---------------------
.model SMALL
.386
;DATA SEGMENT   USE16
.data
;BODY DB '-O#'         ;3个
 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 
      LEVEL       DB    1
      DIRECTION   DB    72
      FOOD        DB    10,10
      SCOINFO     DB    'SCORE:$'
      SCORE       DB    0H
      SCOCHAR     DB    4 DUP('0')
                  DB    '$'          
      PAUSEINFO   DB    'Pagedown to PAUSE$'
      EXITINFO    DB    'Esc to EXIT $'
      ;CTRINFO     DB    'Change Direction$'
      ;CTRINFO2    DB    'with Dirction Key$'
      CTRINFO     DB    'Move ',18H,0,19H,0,1AH,0,1BH,'$'
      CTRINFO2    DB    'to Change Direction$'
      LEVELINFO   DB    'level:$'
      NEXTLEVEL   DB    'SUCCEED TO NEXT LEVEL!$'
      N     DW 12000 ;屏幕刷新速度
      TEN2  DW   10
     
MUS_FREG  DW 262,262,294,262,349
          DW 330,262,262,294,262
          DW 392,349,262,262,523
          DW 440,349,262,262,466
          DW 466,440,262,392,349,-1
        
MUS_TIME  DW 50,50,100,100,100
          DW 100,100,50,50,100,100
          DW 100,100,100,50,50,100
          DW 100,100,100,100,100,50
          DW 50,100,100,100,100,100
;DATA ENDS
         
;STACK SEGMENT STACK
; DB 100 DUP(?)
;STACK  ENDS
.code
;-------------------------------------------------------------------------------
;(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 
 
;-------------------------------------------------------------------------------

;CODE SEGMENT   USE16
 ;ASSUME CS:CODE,DS:DATA,SS:STACK          
 ORG    100H
.STARTUP
      ;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,  60
      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,  60
      INT   10H
      ;显示EXITINFO
      MOV AH,9
      MOV DX,OFFSET EXITINFO
      INT 21H
     
      CALL SHOWLEVEL
      ;-------------------------------------------
      ;MOV   CX,300000
;L1:   PUSH  CX
 
      .repeat
      CALL  DELAY
 
      CALL  MOVESTEP
      
      CALL  SHOWBODY
      
      
      ;POP   CX
      
      ;LOOP  L1
      
      .until 0
      
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
CLEARS 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,40H;1FH ;红色
      MOV   CX,1
      INT   10H
      POP   CX
 
      ADD   SI,2
      ADD   DI,1
      LOOP  SL1
      RET
SHOWBODY 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
DELAY 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
      
      ;;;蜂鸣器
      in   al,61h
      or   al,3
      out  61h,al
      mov  al,0b6h;控制字
      out  43h,al
      mov  ax,1500
      out  42h,al
      mov  al,ah
      out  42h,al
      call delay1
      in   al,61h
      and  al,0fch
      out  61h,al
      ;;;
      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],       '*'
      ;MOV   BYTE PTR [DI+1],     '#'
      MOV   BYTE PTR [DI+1],      'O'
      MOV   DI,OFFSET SCORE
      INC   BYTE PTR [DI]
      CALL  SHOWINFO
     
      MOV   AL, SCORE;变速
      .IF AL==10
      MOV  AH, 3
      MOV  LENG, AH
      MOV  EBX, "O*-"
      MOV  DWORD PTR BODY, EBX
    
      ;清屏
      MOV   AH,6
      MOV   AL,0
      MOV   BH,10H
      MOV   CX,0
      MOV   DL,59
      MOV   DH,24
      INT   10H
     
      MOV   AH,02H
      MOV   BH,0
      MOV   DH, 10
      MOV   DL, 22
      INT   10H
      MOV AH,9
      MOV DX,OFFSET NEXTLEVEL
      INT 21H

      ;升级播放音乐
          PUSH DS
          SUB AX,AX
          PUSH AX
          LEA SI,MUS_FREG
          LEA BP,DS:MUS_TIME
FREG :    MOV DI,[SI]
          CMP DI,-1
          JE END_MUS
          MOV DX,DS:[BP]
          MOV BX,1400
         
         
          PUSH AX
          PUSH BX
          PUSH CX
          PUSH DX
          PUSH DI
          MOV AL,0B6H
          OUT 43H,AL
          MOV DX,12H
          MOV AX,533H*896
          DIV DI
          OUT 42H,AL
          MOV AL,AH
          OUT 42H,AL
          IN AL,61H
          MOV AH,AL
          OR AL,3
          OUT 61H,AL
 
WAIT1:    MOV CX,8FF0H
DELAY0:   LOOP DELAY0
          DEC BX
          JNZ WAIT1
          MOV AL,AH
          OUT 61H,AL
          POP DI
          POP DX
          POP CX
          POP BX
          POP AX 
         
          ADD SI,2
          ADD BP,2
          JMP FREG
END_MUS:
     
      CALL delay1
      CALL delay1
      CALL delay1
      ;清屏
      MOV   AH,6
      MOV   AL,0
      MOV   BH,10H
      MOV   CX,0
      MOV   DL,59
      MOV   DH,24
      INT   10H
     
     
      XOR  AH, AH
      MOV  SCORE, AH
      CALL SHOWINFO
     
      MOV  BX, 12000
      SUB  BX, 2000
      .IF  BX < 5000
          MOV BX, 4000   
      .endif
      MOV  N, BX
     
      INC  LEVEL
      MOV  AH,LEVEL
      .IF AH == 5
       MOV  LEVEL, AH
      .endif
      CALL SHOWLEVEL
      .endif
      CALL SHOWLEVEL
      
      ;根据方向修改增长后的头部坐标 ,此时 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
MOVESTEP 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
GETCHAR 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   AL,'*'
      MOV   BH,0
      MOV   BL,1FH
      MOV   CX,1
      INT   10H  
      RET
GENFOOD 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
SHOWINFO ENDP

;SHOW LEVEL
SHOWLEVEL  PROC  NEAR
      ;设置LEVELINFO光标位置
      MOV   AH,02H
      MOV   BH,0
      MOV   DH,  14
      MOV   DL,  67
      INT   10H
      MOV   AH,9
      MOV   DX,OFFSET LEVELINFO
      INT   21H
     
      MOV    DI,OFFSET LEVEL
      MOV    AL, [DI]
      ADD    AL, 30H
      MOV    DL, AL
      MOV    AH, 02H
      INT    21H
      RET

SHOWLEVEL endp
;================================================
;Fountion:delay for a moment
;Input:None
;Output:None
;-----------------------------------------------------------
delay1 proc
  pusha
  mov ax,0100h
  @1:
  mov cx,0ffffh
  @2:
  dec cx
  jne @2
  dec ax
  jne @1
  popa
  ret
delay1   endp     
.EXIT
END 

      运行效果图如下:

                     


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值