详细设计:
2.贪吃蛇详细设计:
如下图所示左下角为主程序对贪吃蛇相关子程序的调用,程序中init_left_window子程序功能为将左侧窗口非边框部分置为空。左边上侧和右侧是贪吃蛇段中,贪吃蛇程序需要的相关数据在snake段中的存储情况:
如下图所示,右侧为贪吃蛇程序整体流程图,左侧为贪吃蛇具体子程序。
设置贪吃蛇初始时在第13行,距离左侧边框一个空单元,因为蛇默认向右移动,故蛇头、身尾均为红色“*”,将第一个食物固定在同一行的第20列。
贪吃蛇每个节点的设计借鉴链表的思想,借用用本节点的字符颜色属性指向下一节点在本节点的哪个方向。因为在显示一个“*”时,要用两个字节,一个字节存储该字节的ascii码,另一个字节存储显示时的颜色属性。此颜色属性也代表下一节点在本节点的哪个方向。
下一节点方向为向上时颜色属性字节为0001b=01h,显示为蓝色,向下时为0010b=02h,显示为绿色,向左时为0011b=03h,显示为浅蓝色,向右时为0100b=04h,显示为红色。
初始化贪吃蛇代码如下:
;初始化蛇
init_snake:
push ax
push ds
push es
push bx
;初始化蛇尾
mov ax,snake
mov es,ax
mov ax,0b800h+78h
mov ds,ax
mov word ptr ds:[4],042ah
mov word ptr es:[0],ds
mov word ptr es:[2],4
mov word ptr ds:[6],042ah
;初始化蛇头
mov word ptr ds:[8],042ah
mov word ptr es:[4],ds
mov word ptr es:[6],8
mov word ptr es:[8],0
mov word ptr es:[10],0
;初始化食物
mov ax,0b878h
mov ds,ax
mov bx,40
mov word ptr ds:[bx],042ah
mov word ptr es:[12],ds
mov word ptr es:[14],bx
pop bx
pop es
pop ds
pop ax
ret
如下图所示,左半边屏幕为贪吃蛇初始化完成后向右移动了一格的状态,中间的一个单独*号代表食物。
设计具体细节如下图所示,比较大的块代表蛇头,贪吃蛇每次变换方向,其颜色都会做出响应改变。
如下图所示为贪吃蛇移动到将要吃食物的位置了:
下图所示为贪吃蛇吃完食物后蛇身长度加一,且按下W键后,蛇向上转弯,已转弯部分变为蓝色,代表下一单元在本单元的上方,上侧的单独一个红色“*”为新食物。
贪吃蛇撞上自身或墙后,清屏,然后显示游戏结束、得分、重新新开始的提示操作: (snake_game_over_info子程序)
贪吃蛇移动子程序代码如下:大致思路为每间隔一秒,贪吃蛇根据蛇头颜色所代表的方向向指定位置移动一下,若下一位置为“*”,则判断该“*”的行列坐标值是否等于存储在snake段中的食物坐标,若等于则发生吃食物动作,若不等于则代表蛇撞到了墙,贪吃蛇游戏结束。
;功能:蛇移动
;参数:无
;返回:无
snake_move:
push ax
push es
push ds
push si
push cx
push bx
mov ax,snake
mov es,ax
;蛇开始移动
snake_start:
;延时一秒
call delayed_one_second
;游戏结束检测
mov ax,es:[4]
mov ds,ax
mov si,es:[6]
mov dx,ds:[si]
call gnsubts
mov cx,ds:[si]
cmp cl,2ah
jne go_on_move
;判断是不是食物
mov ax,es:[12]
mov bx,ds
cmp ax,bx
jne snake_move_end
mov ax,es:[14]
cmp ax,si
jne snake_move_end
;贪吃蛇得分加10
add word ptr es:[8],10
;食物作为蛇头
mov ds:[si],dx
mov es:[4],ds
mov es:[6],si
;扫描并得到新食物位置
call scan_food
mov word ptr ds:[bx],042ah
mov word ptr es:[12],ds
mov word ptr es:[14],bx
jmp near ptr snake_start
;新蛇头置位
go_on_move:
mov word ptr ds:[si],dx
;存储新蛇头
mov es:[4],ds
mov es:[6],si
;存储新蛇尾
mov ax,es:[0]
mov ds,ax
mov si,es:[2]
push ds
push si
call gnsubts
mov es:[0],ds
mov es:[2],si
;旧蛇尾置零
pop si
pop ds
mov word ptr ds:[si],0
jmp near ptr snake_start
snake_move_end:
mov word ptr es:[10],1
pop bx
pop cx
pop si
pop ds
pop es
pop ax
ret
贪吃蛇移动细节如下图所示:其中·第一行表示三个单元的蛇向右移动一个单元的动作细节,节先清空旧蛇尾,再置位新蛇头,将新的蛇头、蛇尾坐标更新到snake段中蛇头蛇尾坐标存储单元处。第二行代表有三个单元的蛇下一单元时食物时的情况,其吃食物的动作为,清空旧蛇尾,将新食物作为新蛇头。
子程序delayed_one_second功能为延时一秒,即让贪吃蛇的某一状态保持一秒后再移动,其实现为,读取当前时钟信息,时钟中断大概18次为一秒,故在本程序中让时钟中断18次后退出,便就实现了延时一秒。具体代码如下:
;功能:程序延时1秒
;参数:无
;返回:无
delayed_one_second:
push ax
push ds
push si
push cx
mov ax,0
mov ds,ax
mov si,46ch
lodsw
add ax,18
mov cx,ax
_delayed_one_second:
mov si,46ch
lodsw
cmp ax,cx
jnb _delayed_over
jmp _delayed_one_second
_delayed_over:
pop cx
pop si
pop ds
pop ax
ret
子程序gnsubts为根据指定蛇单元的ds、si得到下一个蛇单元的ds、si(get_next_snake_unit_by_this_snake),即根据指定蛇单元的ds、si得到该单元的字符属性,根据字符属性可以得到下一节点方向,然后就可以知道下一节点的ds、si。其代码如下:
;根据指定蛇单元的ds、si得到下一个蛇单元的ds、si(get_next_snake_unit_by_this_snake)
;参数:ds:[si]指向当前蛇单元
;返回:ds:[si]指向下一蛇单元
gnsubts:
push ax
push dx
;从本单元读取下一单元方向
mov dx,ds:[si]
;下一单元方向为上时
direct_is_up:
cmp dh,1
jne direct_is_down
mov ax,ds
sub ax,0ah
mov ds,ax
;下一单元方向为下时
direct_is_down:
cmp dh,2
jne direct_is_left
mov ax,ds
add ax,0ah
mov ds,ax
;下一单元方向为左时
direct_is_left:
cmp dh,3
jne direct_is_right
sub si,2
;下一单元方向为右时
direct_is_right:
cmp dh,4
jne gnsubts_end
add si,2
gnsubts_end:
pop dx
pop ax
ret
子程序scan_food为扫描食物程序,即将贪吃蛇窗口以十字交叉划分为4个小矩形窗口,每调用一次,依次从这四个矩形窗口中扫描,若第一的矩形的第一个单元为“*”时,去查看第二个矩形的第二个单元是否是“*”,依次循环从这四个矩形空间中找到不是“*”的单元,将此单元作为食物,将其地址ds、si存储到snake段的食物地址空间,并将此单元置为新食物,显示在屏幕上。其代码如下:
;扫描并得到新食物位置
;参数:无
;返回:ds:[bx]指向新食物的位置
scan_food:
push ax
push cx
push es
mov ax,0b800h+0ah
mov ds,ax
mov ax,snake
mov es,ax
mov bx,8
mov ax,es:[bx]
mov bl,4
div bl
;每行扫描
mov cx,11
every_row:
push cx
;每列扫描
mov cx,19
every_col:
cmp ah,0
je area_0
cmp ah,1
je area_1
cmp ah,2
je area_2
cmp ah,3
je area_3
;第零区块
area_0:
mov bx,2
mov ax,ds:[bx]
cmp al,2ah
je go_loop
pop cx
jmp scan_food_end
;第一区块
area_1:
mov bx,40
mov ax,ds:[bx]
cmp al,2ah
je go_loop
pop cx
jmp scan_food_end
;第二区块
area_2:
mov bx,2
mov ax,ds
add ax,82h
mov ds,ax
mov ax,ds:[bx]
cmp al,2ah
je go_loop
pop cx
jmp scan_food_end
;第三区块
area_3:
mov bx,40
mov ax,ds
add ax,82h
mov ds,ax
mov ax,ds:[bx]
cmp al,2ah
je go_loop
pop cx
jmp scan_food_end
go_loop:
add bx,2
loop every_col
mov ax,ds
add ax,0ah
mov ds,ax
pop cx
loop every_row
scan_food_end:
pop es
pop cx
pop ax
ret
上一篇: 汇编语言贪吃蛇、俄罗斯方块双任务设计实现详解(一)——整体系统设计
后续内容请见:汇编语言贪吃蛇、俄罗斯方块双任务设计实现详解(三)——俄罗斯方块详细设计
完整代码:https://download.csdn.net/download/gduyt_gduyt/10924302