难以用汇编语言完成贪吃蛇游戏
Difficulty completing the snake game with assembly language
我能够用汇编语言创建一个游戏并使用星星,它像蛇游戏一样在撞墙时结束,但我想添加另一件事,当星星撞到时游戏结束本身。我有一个解决问题的部分,我希望你能帮忙。
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
printchar macro n
mov dl,n
mov ah,2
int 21h
endm
您的 printchar 宏使用 DOS.PrintChar 函数 02h。对于贪吃蛇游戏而言,此 DOS 函数还发出回车 return / 换行没有用,有时可能有害。您应该改用 BIOS.WriteCharacter 函数 0Ah。
printchar macro n
mov cx, 1
mov bh, 0
mov al, n
mov ah, 0Ah ; BIOS.WriteCharacter
int 10h
endm
与星星相撞
要检测碰撞,只需使用 BIOS.ReadCharacterAndAttribute 函数 08h 从视频内存中读取数据即可。您可以在转到下一个位置 (gotoxy) 和显示另一颗星 (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 '*'
闯入边境
如果要绘制矩形 (0,0) - (79,23),则不必验证超出标签 L2 处的坐标,因为上述碰撞检测也会处理的。
接下来是绘制白色矩形的快速解决方案:
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
最后一个提示
在从用户那里检索密钥时保持一致。您的程序混合了 DOS 功能 07h 和键盘 BIOS 功能 00h。我建议你一直使用Keyboard BIOS功能。
[编辑]
您完成的代码,其中包含更正和更多改进。
请注意,我已经增加了堆栈的大小。 64 字节有点小,很容易让您在使用某些 BIOS and/or DOS 系统调用时遇到麻烦。
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
我能够用汇编语言创建一个游戏并使用星星,它像蛇游戏一样在撞墙时结束,但我想添加另一件事,当星星撞到时游戏结束本身。我有一个解决问题的部分,我希望你能帮忙。
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
printchar macro n mov dl,n mov ah,2 int 21h endm
您的 printchar 宏使用 DOS.PrintChar 函数 02h。对于贪吃蛇游戏而言,此 DOS 函数还发出回车 return / 换行没有用,有时可能有害。您应该改用 BIOS.WriteCharacter 函数 0Ah。
printchar macro n
mov cx, 1
mov bh, 0
mov al, n
mov ah, 0Ah ; BIOS.WriteCharacter
int 10h
endm
与星星相撞
要检测碰撞,只需使用 BIOS.ReadCharacterAndAttribute 函数 08h 从视频内存中读取数据即可。您可以在转到下一个位置 (gotoxy) 和显示另一颗星 (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 '*'
闯入边境
如果要绘制矩形 (0,0) - (79,23),则不必验证超出标签 L2 处的坐标,因为上述碰撞检测也会处理的。
接下来是绘制白色矩形的快速解决方案:
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
最后一个提示
在从用户那里检索密钥时保持一致。您的程序混合了 DOS 功能 07h 和键盘 BIOS 功能 00h。我建议你一直使用Keyboard BIOS功能。
[编辑]
您完成的代码,其中包含更正和更多改进。
请注意,我已经增加了堆栈的大小。 64 字节有点小,很容易让您在使用某些 BIOS and/or DOS 系统调用时遇到麻烦。
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