我的蛇游戏几乎接近顺利运行。只有这一个错误,如果我犯了一个“错误”,我的蛇就会死掉。转。例如,当我的蛇向右走时,我按下然后向左,它就死了。然而,当我按下然后向右按,它就会存在。我检查部件打印位置的方法取决于前一页上读取的前一个字符。例如,如果在上一页上读取的前一个字符是'>',则它将读取其左侧的字符,然后在备用页面上打印读取的字符。这是我的代码:
.model small
.data
mode db 03h
startPosX db 39
startPosY db 12
myChar db 14
wdir db 119, 48h, 87
sdir db 115, 50h, 83
adir db 97, 4bh, 65
ddir db 100, 4dh, 68
curColor db 12h
cycle db 0
startPrompt db 'Press any key to start the game n___n', '$'
index dw 0
recycleTime EQU 100
maxX dw 80
maxY dw 25
food db 01h
prevkey db ?
input db ?
xpos db ?
ypos db ?
foodPosX db ?
foodPosY db ?
cloneXpos db ?
cloneYpos db ?
snakeLength db 5
partCount db 1
curPage db 0
altPage db 1
cloneAltPage db ?
boolCopied db 0
upChar db '^'
downChar db 'v'
leftChar db '<'
rightChar db '>'
promptRetry db 'Want to play again?', '$'
choices db 'Yes No', '$'
promptTY db 'Thank you for playing! n___n', '$'
arrowSelect db 16
mychoice db 'y'
.stack 100h
.code
loadPage macro page
mov al, page
mov ah, 05h
int 10h
endm
setCursorPos macro x, y, page
mov dh, y
mov dl, x
mov bh, page
mov ah, 02h
int 10h
endm
printChar macro char, color, page
mov al, char
mov bh, page
mov bl, color
xor cx, cx
mov cx, 1
mov ah, 09h
int 10h
endm
loadPrompts proc
call clearScreen
call clearRegisters
setCursorPos 30, 12, curPage
lea dx, promptRetry
mov ah, 09h
int 21h
setCursorPos 34, 13, curPage
lea dx, choices
mov ah, 09h
int 21h
ret
loadPrompts endp
printArrow proc
setCursorPos xpos, ypos, curPage
printChar arrowSelect, 0fh, curPage
ret
printArrow endp
loadTYPrompt proc
call clearscreen
call clearRegisters
mov xpos, 26
setCursorPos xpos, 12, curPage
lea dx, promptTY
mov ah, 09h
int 21h
mov ah, 00h
int 16h
call clearScreen
mov ax, 4c00h
int 21h
ret
loadTYPrompt endp
copy macro dest, source
mov cl, source
mov dest, cl
endm
gameover proc
call clearScreen
call loadPrompts
setCursorPos 32, 13, curPage
printChar arrowSelect, 0fh, curPage
choose:
mov ah, 00h
int 16h
mov input, al
cmp al, 'a'
je chooseYes
cmp al, 'd'
je chooseNo
jmp done
chooseYes:
mov mychoice, 'y'
mov xpos, 32
mov ypos, 13
jmp done
chooseNo:
mov mychoice, 'n'
mov xpos, 42
mov ypos, 13
done:
call clearScreen
call loadPrompts
call printArrow
cmp input, 13
jne choose
cmp mychoice, 'y'
je playagain
call loadTYPrompt
playagain:
call clearRegisters
mov snakeLength, 5
mov partCount, 1
loadPage altPage
copy cloneAltPage, altPage
copy altPage, curPage
copy curPage, cloneAltPage
mov boolCopied, 0
mov input, 'd'
mov prevkey, 'd'
ret
gameover endp
random macro maxCoor
mov ah, 00h
int 1ah
mov ax, dx
xor dx, dx
mov cx, maxCoor
div cx
endm
scanChar proc
mov ah, 08h
int 10h
ret
scanChar endp
keystroke proc
mov ah, 01h
int 16h
jz nopress
mov ah, 00h
int 16h
cmp al, 00h
jne wsadInput
mov input, ah
jmp nopress
wsadInput:
mov input, al
nopress:
ret
keystroke endp
spawnfood proc
cmp cycle, 0
jne setFood
setFoodPos:
random maxX
mov foodPosX, dl
random maxY
mov foodPosY, dl
setFood:
setCursorPos foodPosX, foodPosY, curPage
mov ah, 08h
int 10h
cmp ah, 12h
je setFoodPos
spawn:
printChar food, 0fh, curPage
ret
spawnfood endp
waitAmillisec proc
mov cx, 1h
mov dx, 0f4h
mov ah, 86h
int 15h
inc cycle
cmp cycle, recycleTime
jle proceed
mov cycle, 0
proceed:
ret
waitAmillisec endp
clearRegisters proc
xor ax, ax
xor bx, bx
xor cx, cx
xor dx, dx
ret
clearRegisters endp
clearScreen proc
mov ax, 0600h
mov bh, 07h
xor cx, cx
mov dx, 184fh
int 10h
ret
clearScreen endp
initgraphics proc
mov al,mode
mov ah,00
int 10h
ret
initgraphics endp
closegraphics proc
mov ax, 0003h
int 10h
ret
closegraphics endp
main proc
mov ax, @data
mov ds, ax
call initgraphics
mov cx, 3200h
mov ah, 01h
int 10h
setCursorPos 22, 12, curPage
lea dx, startPrompt
mov ah, 09h
int 21h
mov ah, 00h
int 16h
mov input, 'd'
mov prevkey, 'd'
call clearScreen
gameStart:
setCursorPos startPosX, startPosY, curPage
mov xpos, dl
mov ypos, dh
start:
printChar myChar, curColor, curPage
inc xpos
setCursorPos xpos, ypos, curPage
inc partCount
mov cl, partCount
cmp cl, snakeLength
jle start
dec xpos
mov partCount, 1
readchar:
call keystroke
mov index, 0
call clearRegisters
cmpDir:
mov bx, index
mov al, input
cmp al, [ddir+bx]
je moveright
cmp al, [wdir+bx]
je moveup
cmp al, [sdir+bx]
je movedown
cmp al, [adir+bx]
je moveleft
inc index
cmp index, 3
jl cmpDir
mov index, 0
copy input, prevkey
jmp cmpDir
moveup:
cmp prevkey, 's'
je movedown
mov prevkey, 'w'
copy mychar, upChar
cmp ypos, 0
jne up
mov ypos, 24
copy cloneYPos, snakeLength
jmp keepmoving
up:
dec ypos
jmp keepmoving
movedown:
cmp prevkey, 'w'
je moveup
mov prevkey, 's'
copy mychar, downChar
cmp ypos, 24
jne down
mov ypos, 0
copy cloneYPos, snakeLength
jmp keepmoving
down:
inc ypos
jmp keepmoving
moveleft:
cmp prevkey, 'd'
je moveright
mov prevkey, 'a'
copy mychar, leftChar
cmp xpos, 0
jne left
mov xpos, 79
mov cl, snakeLength
copy cloneXPos, xpos
sub cloneXPos, cl
jmp keepmoving
left:
dec xpos
jmp keepmoving
moveright:
cmp prevkey, 'a'
je moveleft
mov prevkey, 'd'
copy mychar, rightChar
cmp xpos, 79
jne right
mov xpos, 0
copy cloneXPos, snakeLength
jmp keepmoving
right:
inc xpos
keepmoving:
call spawnfood
setCursorPos xpos, ypos, altPage
call scanChar
cmp ah, curColor
jne notDeads
call gameOver
jmp gameStart
notDeads:
printChar myChar, curColor, altPage
mov cl, xpos
cmp cl, foodPosX
jne copyHeadPos
mov cl, ypos
cmp cl, foodPosY
jne copyHeadPos
add snakeLength, 2
mov cycle, 0
copyHeadPos:
cmp boolCopied, 0
jne keeplooking
copy cloneXPos, xpos
copy cloneYPos, ypos
mov boolCopied, 1
keepLooking:
mov cl, partCount
printbody:
cmp cl, snakeLength
je move
call scanChar
cmp al, rightChar
je checkForRightPart
cmp al, upChar
je checkForUpPart
cmp al, downChar
je checkForDownPart
cmp al, leftChar
je checkForLeftPart
checkForUpPart:
cmp ypos, 24
jne goUp
mov ypos, 0
jmp checkPrevChar
goUp:
inc ypos
jmp checkPrevChar
checkForDownPart:
cmp ypos, 0
jne goDown
mov ypos, 24
jmp checkPrevChar
goDown:
dec ypos
jmp checkPrevChar
checkForLeftPart:
cmp xpos, 79
jne goLeft
mov xpos, 0
jmp checkPrevChar
goLeft:
inc xpos
jmp checkPrevChar
checkForRightPart:
cmp xpos, 0
jne goRight
mov xpos, 79
jmp checkPrevChar
goRight:
dec xpos
checkPrevChar:
setCursorPos xpos, ypos, curPage
mov ah, 08h
int 10h
inc partCount
mov cl, partCount
cmp cl, snakeLength
jg move
cmp al, rightChar
je printRight
cmp al, upChar
je printUp
cmp al, downChar
je printDown
cmp al, leftChar
je printLeft
jmp move
printUp:
inc ypos
jmp moveup
printDown:
dec ypos
jmp movedown
printLeft:
inc xpos
jmp moveleft
printRight:
dec xpos
jmp moveRight
move:
call clearScreen
call spawnfood
copy xpos, cloneXPos
copy ypos, cloneYPos
loadPage altPage
copy cloneAltPage, altPage
copy altPage, curPage
copy curPage, cloneAltPage
mov partCount, 1
mov boolCopied, 0
call waitamillisec
jmp readchar
mov ax, 4c00h
int 21h
main endp
end main
非常感谢你的帮助n ___ n
编辑:
我在查找代码中的错误时做了一些试错过程,结果发现......导致错误的是这些行中的某些内容(箭头指向):
move(insert direction here):
cmp prevkey, 'a' <-
je moveleft <-
当我尝试它时,蛇已经正常移动O.O我没有想到那些是导致这个bug的线条。顺便说一句,这些线路的作用是检查按下的按键是否会使蛇与当前正在行进的方向相反。 (就像我向左走的时候左边的蛇一样)。
无论如何,对那些帮助我找到错误的人......非常感谢你; ___;
我想现在唯一的问题是检查用户是否输入了一条键,使得蛇朝着与当前行进方向相反的方向行进(就像蛇向左走,用户按下& #39;对&#39;密钥)。
答案 0 :(得分:1)
在处理 ddir 时,您可能在BX中使用了错误的值 要么明确地清楚BH
cmpDir:
mov bl, index
mov bh, 0
mov al, input
cmp al, [ddir+bx]
je moveright
...或将 index 定义为单词变量。
index dw 0
...
cmpDir:
mov bx, index
mov al, input
cmp al, [ddir+bx]
je moveright
EXTRA
击键例程仅返回输入变量中的ASCII码。那么为什么在第二次迭代中通过 cmpDir 将index = 1时的scancode进行比较?
答案 1 :(得分:1)
我解决了你的问题。蛇万岁!
以两种不同的方式达到四个标签 moveup , moveown , moveleft 和 moveright 中的每一个在你的程序中。首先,当用户按下一个键,其次是由于你的内部逻辑实际绘制了蛇。您在预设标签上的检查只需在第一种情况下执行。只需添加四个额外标签并调整四个跳跃。我只会针对向上方向展示它。
...
moveup:
cmp prevkey, 's'
je movedown
mov prevkey, 'w'
moveup_draw:
copy mychar, upChar
...
并在程序中进一步下载
...
jmp move
printUp:
inc ypos
jmp moveup_draw
...
我运行了你的程序并应用了这些更改并且蛇工作得非常漂亮。
ps当用户按下“a”,“d”或CR以外的键时, GameOver 例程确实存在缺陷。选择箭头出现在错误的位置。确保 xpos 和 ypos 具有根据 mychoice 的当前设置的值。
...
cmp al, 'd'
je chooseNo
; Here is something missing!
jmp done