汇编开发贪吃蛇游戏:苹果随机消失重现功能实现遇阻求助
汇编贪吃蛇:苹果随机消失重现身陷困境
我是汇编语言初学者,正在开发一款贪吃蛇游戏,目前卡在苹果随机消失并在其他位置重新出现的功能实现环节,打算用时间来实现随机性。
我已编写了让苹果随机出现一次的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
相关产品推荐
相关产品推荐

