assembly - 转错了蛇就死了(组装)

标签 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,我不认为这些是导致错误的线路。顺便说一句,这些线的作用是检查按下的键是否会使蛇与当前行进的方向相反。 (就像当蛇向右走时我按向左)。

无论如何,对于那些帮助我找到错误的人...非常感谢;___;

我想现在唯一的问题是检查用户是否输入了一个键,该键将使蛇朝着与其当前行进方向相反的方向行驶(就像蛇是否向左行驶并且用户按下了“右”键) .

最佳答案

我解决了你的问题。蛇万岁!

四个标签中的每一个都可以通过两种不同的方式到达 moveupmovedownmoveleftmoveright在你的程序中。首先,当用户按下按键时,其次,由于您的内部逻辑,实际绘制了蛇。您在前面提到的标签处进行的检查仅需要在第一种情况下执行。只需添加四个额外标签并调整四个跳跃即可。我将仅显示向上方向。

   ...
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 例程确实存在缺陷。选择箭头出现在错误的位置。确保xposypos具有符合mychoice当前设置的值。

...
cmp al, 'd'
je chooseNo
             ; Here is something missing!
jmp done

关于assembly - 转错了蛇就死了(组装),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29426546/

相关文章:

c++ - 如何在 Linux 中反汇编二进制可执行文件以获取汇编代码?

c - 遍历数组 MIPS 程序集

c - 是否严格要求汇编才能使 "lowest"成为操作系统的一部分?

assembly 新手请求帮助 : signed integer division + "truncating to an integer"

c - 通过 EBP 从调用函数获取本地变量

assembly - NASM:发出非标量(链接时间)值的 MSW

assembly - 8086 中的除法 MASM 中的组装

assembly - MASM中有转义字符吗?

winapi - 使用 WIN32 函数在 MASM 中输出 Hello World

assembly - 无法解析的外部符号_WinMainCRTStartup