assembly 如何使一个伪随机的东西在屏幕上一个接一个地出现?

5sxhfpxr  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(104)

我正在为学校制作蛇游戏,我需要使用伪随机来创建苹果。我们有一本书,但我不理解它的解释方式。我希望有人能用最简单的方式向我解释。
书中说我们需要使用的方法是基于定时器的,我们需要使用地址0040:006Ch。
顺便说一下,我使用汇编,我很确定我被认为是真正的初学者&我使用的是DosBox。
现在我的代码只移动一个带有wasd的'*',我设置了边界。

IDEAL
MODEL small
STACK 100h
DATASEG
; --------------------------
; Your variables here
; --------------------------
    saveal db ' '

CODESEG
proc black
body:
    mov [es:si], ax
    add si, 2
    cmp si, 25*80*2
    jnz body
  ret
endp black

proc up
    
    mov di, 80*2
    cmp si, di
    jb not_move_up
    
    mov ah, 0
    mov al, ' '
    mov [es:si], ax
    sub si, 80*2
    mov ah, 156
    mov al, '*'
    mov [es:si], ax
not_move_up:
  ret
endp up

proc down

    mov di, (24*80*2)-1
    cmp si, di
    jg not_move_down
    
    mov ah, 0
    mov al, ' '
    mov [es:si], ax
    add si, 80*2
    mov ah, 156
    mov al, '*'
    mov [es:si], ax
not_move_down:
  ret
endp down
proc left

    mov dx, 0
    mov bx, si
    mov ax, si
    mov si, 80*2
    div si
    mov si, bx
    cmp dx,0
    jz not_move_left
    
    mov ah, 0
    mov al, ' '
    mov [es:si], ax
    sub si, 2
    mov ah, 156
    mov al, '*'
    mov [es:si], ax
not_move_left:
  ret
endp left
proc right

    mov dx, 0
    mov bx, si
    mov ax, si
    mov si, 80*2
    div si
    mov si, bx
    cmp dx,158
    jz not_move_right

    mov ah, 0
    mov al, ' '
    mov [es:si], ax
    add si, 2
    mov ah, 156
    mov al, '*'
    mov [es:si], ax
not_move_right:
  ret
endp right
start:
    mov ax, @data
    mov ds, ax
; --------------------------
; Your code here
; --------------------------
    mov ax, 0b800h
    mov es, ax
    
    mov si,0
    mov al, ' '
    mov ah, 0
    call black
    mov si, (12*80+40)*2
    mov al, '*'
    mov ah, 156
    mov [es:si], ax
    
yesOrno:
    mov ah, 1h
    int 21h
    
    mov [byte ptr saveal], al
    cmp [byte ptr saveal], 'w'
    jz w
    cmp [byte ptr saveal], 'a'
    jz a
    cmp [byte ptr saveal], 's'
    jz s
    cmp [byte ptr saveal], 'd'
    jz d
    cmp [byte ptr saveal], 'q'
    jmp exit
    
w:
    call up
    jmp yesOrno
s:
    call down
    jmp yesOrno 
a:
    call left
    jmp yesOrno
d:
    call right
    jmp yesOrno
    
exit:
    mov ax, 4c00h
    int 21h
END start

字符串

6uxekuva

6uxekuva1#

在书中它说我们需要使用的方法是基于定时器的,并且我们需要使用地址0040:006 Ch
BIOS.TimerTick在线性地址0000046 Ch是一个32位变量,在24小时内单调递增,之后重置为0(在午夜)。每秒大约有18个增量。为了在你的蛇游戏中显示苹果(* 真正的初学者级别 *),使用这个计时器作为随机性的来源是可以的。但是请阅读@PeterCordes的评论。
程序如下:

  • 你获取计时器的dword,然后将其除以playfield的宽度,在你的例子中是80。这将产生范围[0,79]内的余数,这将是苹果的X坐标。
  • 接下来你重复这个操作,但是使用游戏场的高度,在你的例子中是25。这将产生一个范围[0,24]内的余数,这将是苹果的Y坐标。
; IN () OUT (ax) MOD (cx,dx)
  push ds
  xor  cx, cx
  mov  ds, cx
  mov  ax, [046Ch]  ; DX:AX is [0,1573040]
  mov  dx, [046Eh]
  mov  cl, 80
  div  cx           ; -> AX is quotient [0,19663], DX is remainder [0,79]
  push dx           ; (1)
  ; don't care if it got incremented in the mean time
  mov  ax, [046Ch]  ; DX:AX is [0,1573040]
  mov  dx, [046Eh]
  mov  cl, 25 
  div  cx           ; -> AX is quotient [0,62921], DX is remainder [0,24]
  pop  ax           ; (1)
  mov  ah, dl
  pop  ds
  ret

字符串
有关创建贪吃蛇游戏的更多详细信息,请参阅The quintessential Snake Game. How to keep track of the snake?,特别是查找使用另一种随机数生成方法NewFood 子例程。

相关问题