转弯错误造成蛇模(装配)

时间:2015-04-03 05:10:05

标签: assembly masm32

我的蛇游戏几乎接近顺利运行。只有这一个错误,如果我犯了一个“错误”,我的蛇就会死掉。转。例如,当我的蛇向右走时,我按下然后向左,它就死了。然而,当我按下然后向右按,它就会存在。我检查部件打印位置的方法取决于前一页上读取的前一个字符。例如,如果在上一页上读取的前一个字符是'>',则它将读取其左侧的字符,然后在备用页面上打印读取的字符。这是我的代码:

.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;密钥)。

2 个答案:

答案 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