TASM 组装阵列很时髦而且不工作

问题描述

基本上......

我正在尝试在 TASM 程序集中制作蛇游戏。目前,主要问题是蛇游戏的数组(400 个字节的单元格数组)非常时髦。

示例: 当我稍后尝试将它放在 DATASEG 中(就像是定义的最后一个变量之一)并且我尝试在游戏开始时绘制数组时,它会加载,好像某些随机单元格的值不同于 0(它们不应该)。另一个问题是,当我更改 1 个随机单元格的值以生成一个苹果时,它有时会绘制 2 个苹果,这意味着出现问题...

这就是我定义数组的方式:GameArray db 400 dup(0) 这就是我如何移动数组:mov bx,offset GameArray

此外,计时器似乎不起作用。我现在在代码中所拥有的只是功能和尝试查看计时器是否有效:

`.286
IDEAL
model small
stack 100h
DATASEG
    GameArray db 400 dup(0) ;20x20 array for the snake game. need to be first variable for some reason,or cell values are jumbled up. wierd...
    ApplePresent db 0 ;incase 2 or more cells with applevalue,disregard the later cells and make them empty squares
    seconds db 99 ;variable for timer to check in how many miliseconds there is change.
    One db 1 ;used as number '1' as word so bx which array is moved to will have no problems.
    AppleValue db 255 ;used as number '256' as word so bx which array is moved to will have no problems.
    Zero db 0 ;used as number '0' as word so bx which array is moved to will have no problems.
    PointGained db 0 ;Boolean var to check if point was gained in the movement. if so,snake will be grown.
    NumCell dw 0 ;NumCell represents the cell in the array which the snake's head will be going to.
    score db 0 ;keeps score of the game.
    xArr dw 10 ;x coordinate of head (value 5 at start) at start of game. (x of array)
    yArr dw 9 ;y coordinate of head (value 5 at start) at start of game. (y of array)
    SnakeHead db 5 ;SnakeHead value will  be copied to element of array snake head will go to.
    xDraw dw ? ;x coordinate for drawing screen
    yDraw dw ? ;y coordinate for drawing screen
    xDrawlim dw ? ;x coordinate for drawing screen limit of Box
    yDrawlim dw ? ;y coordinate for drawing screen limit of Box
    Direction db 1 ;1 = right,2 = up,3 = left,4 = down. gets value from last click of WASD keys
    Clock equ es:6ch ;looks at clock memory segment.
CODESEG
proc ApplesFix ;FUnction to fix if there are 2 or more cells with value of 255 in them. if so,reset the value of the array cell to 0.
    pusha
    mov bx,offset GameArray
    mov ax,400
ApplesFixLoop:
    mov cl,[AppleValue]
    cmp [bx],cl
    je IncrementApplePresent
    inc bx
    dec ax
    jnz ApplesFixLoop
    jmp EndFix
IncrementApplePresent:
    inc [ApplePresent]
    cmp [ApplePresent],1
    jg FixCell
    inc bx
    dec ax
    jnz ApplesFixLoop
    jmp EndFix
FixCell:
    mov cl,[Zero]
    mov [bx],cl
    inc bx
    dec ax
    jnz ApplesFixLoop
EndFix:
    popa
    ret
endp ApplesFix
proc RandApple
    pusha ;pushes all registers. never knew the command so only using it Now.
    push [Numcell]
RandGen:
    mov [NumCell],0
    mov ax,40h
    mov es,ax
    mov cx,10
    mov bx,0
random_loop_apple:
    mov ax,[Clock] 
    mov ah,[byte cs:bx]
    xor al,ah 
    and al,11111111b 
    xor ah,ah
    mov [NumCell],ax
    add [NumCell],11
    loop random_loop_apple
    mov bx,offset GameArray
    add bx,[NumCell]
    mov cl,[Zero]
    cmp [bx],cl
    je GenerateApple
    jmp RandGen
GenerateApple:
    mov cl,[AppleValue]
    mov [bx],cl
    pop [Numcell]
    popa
    ret
endp RandApple
proc KeyPress ;function which gets key press from WASD and will change var 'Direction' according to it.
    push ax
    mov ah,1d
    int 21h
Wait_for_Data:
    cmp al,87;'W'
    je MovingUp
    cmp al,65;'A'
    je MovingLeft
    cmp al,83;'S'
    je MovingDown
    cmp al,68;'D'
    je MovingRight
    jmp Wait_for_Data
MovingUp:
    mov [Direction],2d
    jmp EndKeyPress
MovingLeft:
    mov [Direction],3d
    jmp EndKeyPress
MovingDown:
    mov [Direction],4d
    jmp EndKeyPress
MovingRight:
    mov [Direction],1d
    jmp EndKeyPress
EndKeyPress:
    pop ax
    ret
endp KeyPress
proc MoveHead ;Head value will be copied into the array cell which snake moves to.
    pusha
    mov bx,[SnakeHead]
    mov [bx],cl
    popa
    ret
endp MoveHead
proc DirectionSnake ;proc for changing x,y values of array to kNow which square head value will be copied to.
    cmp [Direction],1d
    je MoveRight
    cmp [Direction],2d
    je MoveUp
    cmp [Direction],3d
    je MoveLeft
    cmp [Direction],4d
    je MoveDown
MoveRight:
    add [xArr],1d
    cmp [xArr],19d
    jg OtherSideRight
    jmp EndDirectionSnake
MoveUp:
    sub [yArr],1d
    cmp [yArr],0d
    jb OtherSideUp ;function for making snake head appear at the highest layer if snake goes down out of boundaries. (same with labels of same name,just for different function)
    jmp EndDirectionSnake
MoveLeft:
    sub [xArr],1d 
    cmp [xArr],0d
    jb OtherSideLeft
    jmp EndDirectionSnake
MoveDown:
    add [yArr],19d
    jg OtherSideDown
    jmp EndDirectionSnake
OtherSideRight:
    mov [xArr],0d
    jmp EndDirectionSnake
OtherSideUp:
    mov [yArr],19d
    jmp EndDirectionSnake
OtherSideLeft:
    mov [xArr],19d
    jmp EndDirectionSnake
OtherSideDown:
    mov [yArr],0d
EndDirectionSnake:
    ret
endp DirectionSnake
proc findHeadXY ;find xy coordinate of the cell in array which head will be going to
    push ax ;preserving value of ax by pushing him into stack and popping him at the end of function.
    mov ax,[xArr]
    mov [NumCell],ax ;NumCell represents the cell in the array which the snake's head will be going to.
    mov ax,[yArr]
FindarrayCelly: ;label for loop of finding the array cell's y value that snake head is going to be copied into.
    add [NumCell],20d
    sub ax,1d
    jnz FindarrayCelly
    pop ax
    ret
endp findHeadXY
proc MoveAction ;function will find whats inside the cell snake head will be going to and see if snake eats apple and moves,regular movement or lose.
    push bx
    push cx
    mov bx,[NumCell] ;goes to the cell which the snake head will be moving to.
    mov cl,cl
    je SnakeEatsApple
    mov cl,cl
    je SnakeMoves
    jmp GameLost
SnakeEatsApple:
    add [score],1d ;if apple is eaten score is increased by 1.
    mov [PointGained],1d ;sets boolean to 1 meaning 'True',snake will lengthen
    cmp [score],255d
    je GameWon
    call MoveHead
SnakeMoves:
    call MoveHead
GameLost:
    mov ax,0c00h ;replicating exit interrupt.
    int 21h
GameWon:
    mov ax,0c00h ;replicating exit interrupt.
    int 21h
EndMoveAction:
    pop cx
    pop bx
    ret
endp MoveAction
proc BlackSquare ;when array element has value which is 0,draw white square
    push cx
    push dx
    mov cx,[xDraw]
    mov dx,[yDraw]
    mov al,15d   
    loopBoxB:
    mov bh,0h
    mov ah,0ch
    int 10h
    inc cx
    cmp cx,[xDrawlim]
    jne loopBoxB
    mov cx,[xDraw]
    inc dx
    cmp dx,[yDrawlim]
    jne loopBoxB
    pop dx
    pop cx
    ret
endp BlackSquare
proc SnakeSquare ;when array element has value which is not 0 or 256,draw green square (green color)
    push cx
    push dx
    mov cx,2d ;al assigned different value for different color    
    loopBoxS:
    mov bh,[xDrawlim]
    jne loopBoxS
    mov cx,[yDrawlim]
    jne loopBoxS
    pop dx
    pop cx
    ret
endp SnakeSquare
proc AppleSquare ;when array element has value which is 256,draw yellow square
    push cx
    push dx
    mov cx,14d  ;al assigned different value for different color    
    loopBoxA:
    mov bh,[xDrawlim]
    jne loopBoxA
    mov cx,[yDrawlim]
    jne loopBoxA
    pop dx
    pop cx
    ret
endp AppleSquare
proc DrawScreen ;draws screen according to value in array elements.
    pusha
    mov bx,0d
    mov [xDraw],121d ;starting values for painting screen
    mov [ydraw],101d
    mov [xDrawlim],130d
    mov [yDrawlim],110d
CheckElementValue:
    mov cl,cl
    je CallBlackSquare ;goes to label to call function BlackSquare
    mov cl,cl ;cx is copying AppleValue since comparing memory (var) to memory (array which is copied in bx) is illegal.
    je CallAppleSquare ;goes to label to call function AppleSquare
    jmp CallSnakeSquare ;goes to label to call function SnakeSquare
CallBlackSquare:
    call BlackSquare
    add [xDraw],10d
    add [xDrawlim],10d
    inc ax
    cmp ax,400d
    je EndDrawingScreen
    add bx,1
    cmp [xDrawlim],330d
    je DropLine
    jmp CheckElementValue
MidJumP:
    jmp CheckElementValue
CallAppleSquare:
    call AppleSquare
    add [xDraw],330d
    je DropLine
    jmp CheckElementValue
CallSnakeSquare:
    call SnakeSquare
    add [xDraw],1 
    cmp [xDrawlim],330d
    je DropLine
    jmp CheckElementValue
DropLine:
    add [yDraw],10d
    add [yDrawlim],10d
    mov [xDraw],121d
    mov [xDrawlim],130d
    cmp [yDrawlim],310d
    jne MidJumP
EndDrawingScreen:
    popa
    ret
endp DrawScreen
proc CycleChange ;the procedure reduces all cells in array which value is greater than 0 by 1,so tail of the snake will get erased after new head is formed.
    pusha
    mov bx,400d
CheckArray:
    cmp [word ptr bx],0 ;checks current element of array looked at and checks if equal to 0. need to add that will not reduce value if its 256 as well.
    jne DecreaseCellValue
    add bx,1d
    dec ax
    jz EndCycleChange
DecreaseCellValue:
    mov cl,[One]
    sub [bx],cl
    add bx,1d
    dec ax
    jmp CheckArray
EndCycleChange:
    popa
    ret
endp CycleChange
proc ResetArray ;restore all array values to 0.
    pusha
    mov bx,400d
ResetArrayL:
    mov cl,[Zero]
    mov [byte ptr bx],cl
    inc bx
    dec ax
    jnz ResetArrayL
    popa
    ret
endp ResetArray
start:
    mov ax,@data
    mov ds,ax
GameStart:
    mov bx,210
    push cx
    mov cx,[word ptr SnakeHead]
GenerateSnake: ;puts snake of length 5 in the array.
    mov [word ptr bx],cx
    inc bx
    loop GenerateSnake
GenerateStartingApple:
    call RandApple ;Puts apple randomly in cell of array before starting the game.
    call ApplesFix
    mov ax,012h
    int 10h ;640 x 480 16 colors. graphic mode interrupt.
secstart: 
    call DrawScreen
    mov ah,02ch        ; Get current second         
    int 021h
    mov bh,dh          ; Store current second   
readloop:
    mov ah,02ch      ; Get new time. Seconds are stored in dh
    int 021h
    sub dh,1       ; Subtract 1 from new second. Giving 1 Secs for input.
GoBackCheck: ;if no key has been pressed,until second is over input from keyboard will be checked.
    cmp bh,dh                    
    je SecondPassed     ; Exit when DH is finally equal to BH.
    mov ah,06h          ; Function 06h of INT 021 will directly read from the Stdin/Stdout
    mov dl,0ffh           ; Move 0ff into the DL register to read from the keyboard
    int 21h              
    jz GoBackCheck           ; If the zero flag of the FLAGS register is set,no key was pressed.
    call KeyPress
    jmp GoBackCheck
SecondPassed: ;here snake moves and checks if you lost/won game.
    call findHeadXY
    call MoveHead
GoBack:
    jmp secstart
exit:
    mov ax,0c00h
    int 21h
END start`

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)