Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
415 views
in Technique[技术] by (71.8m points)

dos - Difficulty completing the snake game with assembly language

I was able to create a game with assembly language and using the star, which ends like a snake game when it hits the wall, but I want to add another thing to it and that the game ends when the star hits itself. And I have a problem solving part, I wanted you to help.

gotoxy macro x,y
     mov dl,x
     mov dh,y
     mov bh,0
     mov ah,2
     int 10h
endm 

printchar macro n
     mov dl,n
     mov ah,2
     int 21h
endm 

printstring macro n
     lea dx,n
     mov ah,9
     int 21h
endm

.model small
.stack 64
.data
    x db 40
    y db 12
    deltax db 0
    deltay db -1 
    msg1 DB "GAME OVER !!!$"
.code
main:            
     mov ax,@data
     mov ds,ax
     gotoxy x,y     
     printchar '*'

     mov ah,7
     int 21h
l1:  
     gotoxy x,y
     mov al,x
     add al,deltax
     mov x,al       
     mov al,y
     add al,deltay
     mov y,al       
     
     gotoxy x,y     
     printchar '*'

     mov ah,0bh     
     int 21h
     cmp al,0     
     je l2          
     mov ah,0
     int 16h        
     cmp al,'w'     
     je L_W
     cmp al,'s'
     je L_S
     cmp al,'a' 
     je L_A
     cmp al,'d'     
     je l_D 
     jmp l2
L_W:                
     mov deltax,0
     mov deltay,-1
     jmp L2
L_S:
     mov deltax,0
     mov deltay,1
     jmp L2
L_A:
     mov deltax,-1
     mov deltay,0
     jmp L2
L_D:
     mov deltax,1
     mov deltay,0
     
L2:     
     cmp y,0      
     je LEND
     cmp y,23
     je LEND
     cmp x,0
     je LEND
     cmp x,79
     je LEND
     jmp l1

LEND:    
     gotoxy 35,12      
     printstring msg1
     mov ah,7
     int 21h
     
     mov ah,4ch
     int 21h
end main

picture from run in emu8086

question from:https://stackoverflow.com/questions/65625775/difficulty-completing-the-snake-game-with-assembly-language

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
printchar macro n
  mov dl,n
  mov ah,2
  int 21h
endm

Your printchar macro uses the DOS.PrintChar function 02h. For the purpose of your snake game, it's not useful and could sometimes be harmful that this DOS function also emits a carriage return / linefeed. You should use the BIOS.WriteCharacter function 0Ah instead.

printchar macro n
  mov cx, 1
  mov bh, 0
  mov al, n
  mov ah, 0Ah  ; BIOS.WriteCharacter
  int 10h
endm

Colliding with a star

To detect a collision all it takes is reading from the video memory using BIOS.ReadCharacterAndAttribute function 08h. You do this right between going to the next position (gotoxy) and displaying another star (printchar).

gotoxy x,y

mov bh, 0
mov ah, 08h   ; BIOS.ReadCharacterAndAttribute
int 10h       ; -> AX
cmp ax, 0720h ; Is this position unoccupied? (0720h means a WhiteOnBlack space character)
jne LEND      ; No

printchar '*'

Crashing into the border

If you would draw the rectangle (0,0) - (79,23), you would not have to verify exceeding the coordinates at label L2 because the above collision detection would also take care of that.

Next is a quick solution to draw a white rectangle:

mov dx, 174Fh  ; (79,23)
xor cx, cx     ; (0,0)
mov bh, 77h    ; WhiteOnWhite
mov ax, 0600h  ; BIOS.ClearWindow
int 10h
mov dx, 164Eh  ; (78,22)
mov cx, 0101h  ; (1,1)
mov bh, 07h    ; WhiteOnBlack
mov ax, 0600h  ; BIOS.ClearWindow
int 10h

One final tip

Be consistent about retrieving a key from the user. Your program mixes the DOS function 07h and the Keyboard BIOS function 00h. I would suggest you use the Keyboard BIOS function all the time.


[edit]
Your completed code with corrections and even more improvements.
Please note that I have increased the size for the stack. 64 bytes is a bit small and can easily get you into trouble with certain BIOS and/or DOS system calls.

gotoxy macro x, y
  mov dl, x
  mov dh, y
  mov bh, 0
  mov ah, 02h     ; BIOS.SetCursor
  int 10h
endm 
    
printchar macro n
  mov cx, 1
  mov bh, 0
  mov al, n
  mov ah, 0Ah     ; BIOS.WriteCharacter
  int 10h
endm
    
printstring macro n
  lea dx, n
  mov ah, 09h     ; DOS.PrintString
  int 21h
endm
    
.model small
.stack 512
.data
  x     db 40
  y     db 12
  delta dw 0FF00h ; deltax = 0  deltay = -1 
  msg1  db "GAME OVER !!!$"
.code
main:            
  mov ax, @data
  mov ds, ax

  mov dx, 174Fh   ; (79,23)
  xor cx, cx      ; (0,0)
  mov bh, 77h     ; WhiteOnWhite
  mov ax, 0600h   ; BIOS.ClearWindow
  int 10h
  mov dx, 164Eh   ; (78,22)
  mov cx, 0101h   ; (1,1)
  mov bh, 07h     ; WhiteOnBlack
  mov ax, 0600h   ; BIOS.ClearWindow
  int 10h

  gotoxy x, y
  printchar '*'
    
  mov ah, 00h     ; BIOS.GetKey
  int 16h         ; -> AX

Again:  
  mov ax, delta
  add x, al
  add y, ah
  gotoxy x, y

  mov bh, 0
  mov ah, 08h     ; BIOS.ReadCharacterAndAttribute
  int 10h         ; -> AX
  cmp ax, 0720h   ; Is this position unoccupied?
  jne Done        ; No

  printchar '*'
    
  mov ah, 01h     ; BIOS.TestKey
  int 16h         ; -> AX ZF
  jz  Again       ; No key available
  mov ah, 00h     ; BIOS.GetKey
  int 16h         ; -> AX
  mov bx, 0FF00h  ; deltax = 0  deltay = -1
  cmp al, 'w'     ; Up
  je  SetDelta
  mov bx, 0100h   ; deltax = 0  deltay = 1
  cmp al, 's'     ; Down
  je  SetDelta
  mov bx, 00FFh   ; deltax = -1  deltay = 0
  cmp al, 'a'     ; Left
  je  SetDelta
  mov bx, 0001h   ; deltax = 1  deltay = 0
  cmp al, 'd'     ; Right
  jne Again
SetDelta:
  mov delta, bx
  jmp Again
    
Done:    
  gotoxy 35, 12
  printstring msg1
  mov ah, 00h     ; BIOS.GetKey
  int 16h         ; -> AX
  mov ax ,4C00h   ; DOS.Terminate
  int 21h
end main

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...