You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

汇编开发贪吃蛇游戏:苹果随机消失重现功能实现遇阻求助

汇编贪吃蛇:苹果随机消失重现身陷困境

我是汇编语言初学者,正在开发一款贪吃蛇游戏,目前卡在苹果随机消失并在其他位置重新出现的功能实现环节,打算用时间来实现随机性。

我已编写了让苹果随机出现一次的proc:

proc apple
    mov ax, 40h
    mov es, ax
    mov ax, [es:6ch]
    and ax, 0000001111111110b
    mov di,ax
    mov ax, 0b800h
    mov es, ax
    
    mov al, '@'
    mov ah, 154
    mov [es:di], ax
    ret 
    endp apple

在数据段中我定义了:

app dw 0
star dw (12*80+40)*2 ;the place of the snake

从这一步开始我就卡壳了,以下是目前的完整代码:

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

app dw        ;place of the apple
star dw (12*80+40)*2  ;place of the *
st_am dw      ;nevermind this

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

proc apple
    mov ax, 40h
    mov es, ax
    mov ax, [es:6ch]
    and ax, 0000001111111110b
    mov di,ax
    mov ax, 0b800h
    mov es, ax
    
    mov al, '@'
    mov ah, 154
    mov [es:di], ax
    ret 
    endp apple
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
    call apple
    
    

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

问题拆解与解决方案

核心问题

当前的apple proc仅实现了单次随机生成,未记录苹果位置、未处理旧苹果清除逻辑,且随机数未限制在屏幕有效区域,也没有蛇吃苹果的触发判断。

1. 完善数据段变量

确保app正确存储苹果位置,补全初始化:

app dw 0          ; 存储苹果的显存偏移地址
star dw (12*80+40)*2  ; 蛇头初始位置
saveal db ' '     ; 存储按键输入

2. 重写apple proc,实现完整逻辑

修改后支持清除旧苹果、生成合法随机位置、避免与蛇头重叠:

proc apple
    ; 清除旧苹果(如果已存在)
    mov ax, 0b800h
    mov es, ax
    mov di, [app]
    cmp di, 0
    jz generate_new  ; 首次生成直接跳过清除
    mov al, ' '
    mov ah, 0
    mov [es:di], ax

generate_new:
    ; 从BIOS系统计时器获取随机数
    mov ax, 40h
    mov es, ax
    mov ax, [es:6Ch]
    ; 限制随机数在屏幕显存范围内(25行*80列*2字节=4000字节)
    mov dx, 0
    mov bx, 4000
    div bx
    and dx, 0FFFEh  ; 确保是偶数,对应显存字符的起始偏移
    mov di, dx

    ; 避免苹果生成在蛇头位置
    cmp di, [star]
    jz generate_new

    ; 绘制新苹果并记录位置
    mov ax, 0b800h
    mov es, ax
    mov al, '@'
    mov ah, 154
    mov [es:di], ax
    mov [app], di
    ret
endp apple

3. 添加吃苹果触发逻辑

在每个蛇移动proc末尾,添加蛇头位置更新和吃苹果判断,以up为例:

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
    ; 更新蛇头位置到数据段
    mov [star], si
    ; 检查是否吃到苹果
    cmp si, [app]
    jnz not_move_up
    ; 吃到苹果,生成新苹果
    call apple
not_move_up:
  ret
endp up

同理,给down、left、right proc添加相同的蛇头更新和吃苹果判断代码。

4. 优化输入循环(可选)

当前阻塞式输入会导致蛇必须按键才移动,改用非阻塞输入让蛇可以持续移动:

yesOrno:
    ; 非阻塞读取按键
    mov ah, 6h
    mov dl, 0FFh
    int 21h
    jz no_key_press  ; 无按键时直接循环(可添加默认移动逻辑)

    mov [saveal], al
    cmp [saveal], 'w'
    jz w
    cmp [saveal], 'a'
    jz a
    cmp [saveal], 's'
    jz s
    cmp [saveal], 'd'
    jz d
    cmp [saveal], 'q'
    jmp exit

no_key_press:
    ; 这里可添加默认移动逻辑,比如调用上次的移动proc
    jmp yesOrno

w:
    call up
    jmp yesOrno
s:
    call down
    jmp yesOrno 
a:
    call left
    jmp yesOrno
d:
    call right
    jmp yesOrno

内容的提问来源于stack exchange,提问作者yarden

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 08:06:03