汇编语言贪吃蛇、俄罗斯方块双任务设计实现详解(一)——整体系统设计

题目要求:

1.系统划分:将显示器的屏幕划分成大小相等的左右两个显示窗口,并画出每个显示窗口的边框,窗口大小适中。若左窗口贪吃蛇游戏正在进行时,切换到右窗口执行俄罗斯方块,则贪吃蛇游戏暂停,以后每按一次Tab键切换至旁边显示窗口,从被中断前的地方继续执行。当某个显示窗口被选中时,则光标在该窗口底部闪烁,键盘输入对当前窗口有效。整个系统按ESC键退出,返回DOS操作系统界面。

2.贪吃蛇:在左边显示窗口,能够运行简单的贪吃蛇游戏,即采用键盘按键控制贪吃蛇前进方向,以”W、S、A、D”键分别为上下左右方向控制按键,以贪吃蛇碰触窗口边框或自身为游戏终止条件,游戏终止后显示结束信息并只响应“R”键,以“R”键为游戏重新开始。若游戏进行当中无键按下,则贪吃蛇保持当前方向不变直至撞墙。

 3.俄罗斯方块:以“↑”键旋转物块形状,以“←”、“→”键控制物块左右移动,以“↓”控制物块加速。以“Enter”键为俄罗斯方块游戏重新开始。由小方块组成的不同形状的板块陆续从屏幕上方落下来,玩家通过调整板块的位置和方向,使它们在屏幕底部拼出完整的一条或几条。这些完整的横条会随即消失,给新落下来的板块腾出空间,与此同时,玩家得到分数奖励。没有被消除掉的方块不断堆积起来,一旦堆到屏幕顶端,玩家便告输,游戏结束,显示结束信息,并只响应“Enter”键

需求分析:

1.窗口划分:将80x25的显示窗口划分为左右两个40x25的两个窗口,两个窗口四面皆有一个单位宽的边框。边框单元采用绿色“*”来显示(其16进制数据为022ah,02为绿色,“*”的ascii码16进制为2ah),将其他非窗口边框位置置为空(0000h)。

2.键盘中断:编写自己的键盘中断例程,接收键盘中断扫描码,在扫描码等于ESC键、Tab键、W键、A键、S键、D键、↑键、↓键、←键、→键、Enter键的扫描码时,分别做出相应的动作。在按下其他按键时,不作任何响应。在任何时刻按下ESC键时,退出程序,返回到命令行。按下Tab键时从一个程序切换到另一个程序。W、A、S、D、R键只响应贪吃蛇程序。↑、↓、←、→、Enter键只响应俄罗斯方块程序。

3.任务切换:在按下Tab键后,响应左右两个程序之间相互切换。程序一开始运行左侧的贪吃蛇游戏,左侧窗口右下角边框为闪烁光标,按下Tab键后,贪吃蛇暂停移动。左侧窗口右下角边框变回“*”,使右侧窗口右下角边框变为闪烁光标,示意要运行右侧程序。然后保存按下Tab键之前运行贪吃蛇时的所有寄存器的值和堆栈中的值,去执行右侧俄罗斯方块程序。在俄罗斯方块下落过程中,此时按下Tab键,俄罗斯方块停止下落,右侧窗口右下角边框变回“*”, 左侧窗口右下角边框变为闪烁光标示意要运行左侧程序。然后保存按下Tab键之前运行俄罗斯方块时的所有寄存器的值和堆栈中的值,恢复之前保存的贪吃蛇的所有寄存器的值和堆栈中的值,去接着中断之前的地方执行,显示为贪吃蛇从暂停的地方继续前进。此后按下Tab键后,要做的事均为切换右下角光标,保存一个程序数据,然后恢复另一个程序数据,接着执行被恢复的程序。

4.贪吃蛇:设定每次初始时贪吃蛇由三个单元组成,一个为蛇尾,一个为蛇身,一个为蛇头,默认向右移动。键盘按下W、S、A、D键后,贪吃蛇分别向上、下、左、右转弯,然后默认保持方向移动。但当按键方向与蛇行进方向相反时,不做响应,例如向右移动时,按下A键时不做响应。在蛇吃到一个食物后,得分加10分,以食物作为新的蛇头继续移动,直到撞墙或撞到自己本身后游戏结束。游戏结束后清除左边窗口,显示游戏得分和结束提示信息,此时只能按R键让贪吃蛇重新开始,在贪吃蛇移动过程中也可以按R键来重新开始贪吃蛇游戏。

5.俄罗斯方块:设定所有方块均由四个小块组合而成,可组成五种形式的俄罗斯方块,其他形式均可由这五种形式旋转得来。游戏一开始,在顶部中间位置生成一个俄罗斯方块,然后默认每隔一秒向下移动一行。直到无法向下移动时(其下一行有其他方块或是底部边框),该俄罗斯方块在此位置保留。然后在顶部重新生成一个新的俄罗斯方块,开始下落,如此循环……,直到新生成的俄罗斯方块不能下落(下一行已有其他方块),表示俄罗斯方块已经积累到了顶端,则表示游戏结束。此时清空右边屏幕,显示俄罗斯方块的游戏得分和游戏结束提示信息。此时只响应Enter键来重新开始俄罗斯方块游戏。

在下落过程中的任意时刻,可按下←键、→键、↓键来使俄罗斯方块向左、向右、向下加速移动,直到无法向左、向右、向下移动(俄罗斯最左侧、最右侧、下一行已经有其他方块或边框),若无法左移、右移或下移时,还强制按左键、右键、下键,则不响应此时的按键移动。

在下落过程中的任意时刻,可按↑键来旋转此俄罗斯方块。旋转时,以该俄罗斯方块的最左下角单元为中心,顺时针旋转90度。此最左下角单元的行列坐标取该俄罗斯方块行的最大值、列的最小值。但当该方块旋转后的下一状态中,只要有一个单元已被占用,则表示该方块在此位置已无法旋转,此时按↓键无任何响应。

在任何一个俄罗斯方块到达无法再向下移动位置时,开始从最底部扫描整个俄罗斯方块屏幕,查看是否有一行已被“*”占满,若有,则将该行消除,得分加38(每行38个“*”),然后从最顶部重新扫描。消除动作实质为,将该行的上面一行代替此行,向上重复,用上面一行代替本行,实现消除后该行以上的所有方块向下下落一行。

概要设计:

如上图所示右侧图为整个系统的结构框图,左侧为存储程序相关的“数据段”部分。

详细设计: 

1.窗口划分及初始化详细设计

将窗口划分为两个等大的窗口,显示结果为,第一行和和第25行全部为绿色“*”,其他行均为第1、40、41、80列为绿色“*”。其他位置全为空。将左侧窗口右下角边框置为闪烁光标。

其中要想8086汇编在命令行或doxBox显示内容,则需要从段地址为0b800h、段内偏移地址为0000h处开始存放需要显示的具体内容,可以存放4000个字符内容,标准命令行为80行x25列,即可以看见的有2000个字符,每个字符占两个字节,第一个字节为该字符的ASCII码16进制数据,第二个字节为字符显示时的颜色属性,包括背景色、是否下划线、前景字符颜色、是否闪烁。

其中显示窗口为80*25规格每行占用内存80*2=160 byte=0a0h byte,第一行从段地址为0b800h开始向后偏移存储那么第二行可以从段地址为0b80ah开始段地址取值范围:0b800h~ 0b800h+24*0ah,偏移地址取值范围:0~159;

 窗口划分与初始化代码如下:

;功能:初始化左边窗口
;参数:无
;返回:无
init_left_window:
push ax
push ds
push cx
push bx

mov ax,0b80ah
mov ds,ax

;清空左边窗口
mov cx,23
empty_left_window:
mov bx,2
call empty_a_row_in_half_screen
mov ax,ds
add ax,0ah
mov ds,ax
loop empty_left_window
	
;左窗口底角显示闪烁光标
mov bx,78
mov ax,825fh
call setting_designated_unit

pop bx
pop cx
pop ds
pop ax	
ret

;功能:将某一窗口底角单元设置为指定显示形式
;参数:(bx)为该单元在这一行的偏移地址,(ax)为要显示的内容
;返回:无
setting_designated_unit:
push dx
push ds
	
mov dx,0b8f0h
mov ds,dx
mov ds:[bx],ax

pop ds
pop dx
ret
	
;功能:初始化右边窗口
;参数:无
;返回:无
init_right_window:
push ax
push ds
push cx
push bx

mov ax,0b80ah
mov ds,ax

;清空右边窗口
mov cx,23
empty_right_window:
mov bx,82
call empty_a_row_in_half_screen
mov ax,ds
add ax,0ah
mov ds,ax
loop empty_right_window
	
pop bx
pop cx
pop ds
pop ax
ret
	
;功能:将某半边屏幕某一行清空
;参数:ds:[bx]指向该半边屏幕某一行的最左边(非最左边边框)
;返回:无
empty_a_row_in_half_screen:
push cx

mov cx,38
_earihs:
mov word ptr ds:[bx],0
add bx,2
loop _earihs

pop cx
ret
	
;功能:显示所有边框
;参数:无
;返回:无
show_all_frames:
push ax
push ds
push bx
push cx
	
mov ax,0b800h
mov ds,ax

mov bx,0
	
;显示横向边框
mov ax,2
show_top_and_bottom_frame:
push cx
mov cx,80
show_a_frame:
mov ah,2
mov al,2ah
mov ds:[bx],ax
add bx,2
loop show_a_frame

mov ax,0b8e6h
mov ds,ax
pop cx
loop show_top_and_bottom_frame

;显示纵向边框
mov ax,0b80ah
mov ds,ax
mov cx,23
show_lengthwise_frame:
push cx
mov bx,0

;显示某一行最左边边框
mov ax,022ah
mov ds:[bx],ax
add bx,78

;显示某一行中间两列边框
mov word ptr ds:[bx],022ah
add bx,2
mov word ptr ds:[bx],022ah
add bx,78

;显示某一行最右边边框
mov ax,022ah
mov ds:[bx],ax
add bx,2

pop cx
mov ax,ds
add ax,0ah
mov ds,ax
loop show_lengthwise_frame
	
pop cx
pop bx
pop ds
pop ax
ret

后续内容请见:汇编语言贪吃蛇、俄罗斯方块双任务设计实现详解(二)——贪吃蛇详细设计

完整代码:https://download.csdn.net/download/gduyt_gduyt/10924302

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值