详细设计:

3.俄罗斯方块详细设计:下图所示,左下角为主程序的调用情况,左边上侧和右侧为俄罗斯方块相关数据在teris段中的存储情况

下图所示,左侧为俄罗斯方块具体子程序,右侧为俄罗斯方块程序运行流程图。

主程序中所调用的to_play_teris较为复杂,具体代码如下:

;功能:运行俄罗斯方块
;参数:无
;返回:无
to_play_teris:
push ax
push dsbegin_play_teris:
;生成一个俄罗斯方块
call make_a_teris;检测是否已到达最顶部,若是,则游戏结束
mov ax,0100h
call try_to_move
cmp al,2ah
je to_game_over_teris;显示当前俄罗斯方块
call show_this_teris
;当前俄罗斯方块下落,直到不能下落
call teris_drop
;当前俄罗斯方块落定后,检测并消除可以消除的行
call check_and_dispel_action
jmp begin_play_teristo_game_over_teris:
;俄罗斯方块状态置位1
mov ax,teris
mov ds,ax
mov word ptr ds:[2],1pop ds
pop ax
ret

子程序revolve_teris和reset_lower_left_quarter,配合实现俄罗斯方块的旋转。旋转的思路为:以俄罗斯方块的行的最大值、列的最小值为坐标的块单元为中心,此块单元也就是俄罗斯方块的左下角单元。以此单元为中心顺时针旋转90度。

首先介绍reset_lower_left_quarter,其功能为重置俄罗斯方块的左下角坐标,实现方法为,寻找teris段中四个方块坐标值中的行的最大值、列的最小值,得到的便是左下角坐标,用该值去更改teris段中左下角坐标数据,完成重置旋转后的新的俄罗斯方块的左下角坐标。

revolve_teris程序的实现方法为:俄罗斯方块中每个块的坐标值减去俄罗斯方块左下角的坐标值,对得到的坐标值取绝对值,交换行与列值,然后加上俄罗斯方块左下角的坐标值,就是该块顺势针旋转90度后的坐标值,原理图如下:

具体代码如下:

 ;功能:旋转当前俄罗斯方块;参数:无;返回:无revolve_teris:push axpush dspush cxpush bxpush dxpush simov ax,terismov ds,axpush ds:[4]push ds:[6]push ds:[8]push ds:[10]mov si,4mov cx,4revolue_check:mov ax,terismov ds,axmov ax,ds:[12]cmp word ptr ds:[si],axjnb greater_than;行、列值小于左下角坐标时mov dx,ds:[si]sub ah,dhsub dl,almov al,dl;坐标差值的绝对值旋转mov dl,ahmov ah,almov al,dladd ax,ds:[12]mov word ptr ds:[si],axmov ax,ds:[si]call get_offset_by_column_valuecmp byte ptr ds:[bx],2ahje give_up_revolvejmp to_loop_revolue_check;行、列值大于或等于左下角坐标时greater_than:mov dx,ds:[si]sub dx,axmov ax,dxmov dl,ahmov ah,almov al,dladd ax,ds:[12]mov word ptr ds:[si],axmov ax,ds:[si]call get_offset_by_column_valuecmp byte ptr ds:[bx],2ahje give_up_revolvejmp to_loop_revolue_checkto_loop_revolue_check:add si,2loop revolue_checkjmp revolve_succeedgive_up_revolve:mov ax,terismov ds,axpop ds:[10]pop ds:[8]pop ds:[6]pop ds:[4]jmp revolve_teris_endrevolve_succeed:pop axpop axpop axpop axjmp revolve_teris_endrevolve_teris_end:call reset_lower_left_quarterpop sipop dxpop bxpop cxpop dspop axret;功能:重置左下角坐标;参数:无;返回:无reset_lower_left_quarter:push axpush dspush bxpush cxmov ax,terismov ds,axmov bx,4mov ax,ds:[bx]add bx,2mov cx,3look_for_lower_left_quarter:look_for_col:cmp ds:[bx],aljnb look_for_rowmov al,ds:[bx]look_for_row:cmp ds:[bx+1],ahjna go_on_look_formov ah,ds:[bx+1]go_on_look_for:add bx,2loop look_for_lower_left_quarterreset_lower_left_quarter_end:mov ds:[12],axpop cxpop bxpop dspop axret

子程序make_a_teris功能为生成俄罗斯方块,将每个小块坐标存储到teris:[4]开始的四个字单元中,每个俄罗斯方块设定均有四个小块。每中形态俄罗斯方块均可以由下图中的五种旋转变化而来。具体如下图所示:

具体代码如下:

;功能:生成一个俄罗斯方块,将每个小块坐标存储到teris:[4]开始的四个字单元中,每个俄罗斯方块均有四个小块
;参数:无(根据teris:[0]字单元中的俄罗斯方块个数)
;返回:
make_a_teris:
push ax
push ds
push bx
push dxmov ax,teris
mov ds,ax
mov bx,4
mov word ptr ds:[bx],0139h
mov word ptr ds:[bx+2],013ahmov ax,ds:[0]
mov dl,5
div dl
mov al,ah
mov ah,0cmp ax,0
jne block_1
mov word ptr ds:[bx+4],013bh
mov word ptr ds:[bx+6],013ch
mov word ptr ds:[bx+8],0139h
jmp near ptr make_a_teris_endblock_1:
cmp ax,1
jne block_2
mov word ptr ds:[bx+4],013bh
mov word ptr ds:[bx+6],023bh
mov word ptr ds:[bx+8],0239h
jmp near ptr make_a_teris_endblock_2:
cmp ax,2
jne block_3
mov word ptr ds:[bx+4],013bh
mov word ptr ds:[bx+6],023ah
mov word ptr ds:[bx+8],0239h
jmp near ptr make_a_teris_endblock_3:
cmp ax,3
jne block_4
mov word ptr ds:[bx+4],013bh
mov word ptr ds:[bx+6],0239h
mov word ptr ds:[bx+8],0239h
jmp near ptr make_a_teris_endblock_4:
mov word ptr ds:[bx+4],023ah
mov word ptr ds:[bx+6],0239h
mov word ptr ds:[bx+8],0239h
jmp near ptr make_a_teris_endmake_a_teris_end:
inc word ptr ds:[0]pop dx
pop bx
pop ds
pop ax
ret

子程序try_to_move功能为:尝试向指定方向移动,检测在该方向上下一位置是否已被占用,若已被占用则表示无法再向下一位置移动。其实现方式为:根据参数(ax)=在某一方向移动时坐标需要偏移的量;(ax)=0100h表示下移,(ax)=00ffh表示左移,(ax)=0001h表示右移,对teris中四个方块的行列值向指定方向移动一个单元,若有任何一个方块行列值更改后的位置已被占用,就表示该位置已被占用。程序返回:(al)=2ah表示该位置已被占用。具体代码如下:

;功能:尝试向指定方向移动,检测在该方向上下一位置是否已被占用
;参数:(ax)=在某一方向移动时坐标需要偏移的量;(ax)=0100h表示下移,(ax)=00ffh表示左移,(ax)=0001h表示右移;
;返回:(al)=2ah表示该位置已被占用
try_to_move:
push ds
push bx
push cx
push dxcall clean_this_terismov dx,teris
mov ds,dxis_down_move:
cmp ax,0100h
jne is_left_move
jmp to_tryis_left_move:
cmp ax,00ffh
jne is_right_move
jmp to_tryis_right_move:
cmp ax,0001h
jne try_to_move_endto_try:
mov dx,ax
mov bx,4
mov cx,4
begin_to_try:
mov ax,dx
add al,ds:[bx]
add ah,ds:[bx+1]
call get_value_by_column_value
cmp al,2ah
je try_to_move_endadd bx,2
loop begin_to_trytry_to_move_end:
call show_this_teris
pop dx
pop cx
pop bx
pop ds
ret

子程序teris_drop功能为俄罗斯方块下落一行,其实现为:延时一秒后,根据teris段中四个块的坐标检测当前俄罗斯方块下一行是否已经被占用,若是则表示此俄罗斯方块已经无法再向下移动,程序退出,去生成一个新的俄罗斯方块。若当前俄罗斯方块下一行没有被占用,则清除此俄罗斯方块在其屏幕上的显示,将teris段中四个块的坐标行值加一,然后显示行值被更改后的俄罗斯方块。此后又回到延时一秒处,如此向下循环。具体代码如下:

 ;功能:俄罗斯方块下落;参数:无;返回:无teris_drop:push axpush dspush bxpush cxdrop_start:call delayed_one_secondmov ax,0100hcall try_to_movecmp al,2ahje teris_drop_end;清空正在下落的俄罗斯方块上一秒时的位置call clean_this_teris;整个俄罗斯方块坐标数据向下移一格mov ax,terismov ds,axmov bx,4mov cx,5to_drop_teris:add word ptr ds:[bx],0100hadd bx,2loop to_drop_teris;显示坐标更改后的俄罗斯方块call show_this_terisjmp drop_startteris_drop_end:pop cxpop bxpop dspop axret

子程序check_and_dispel_action功能为从最底部检测俄罗斯方块的每一行,查看是否有一行全为“*”,若没有则表示当前俄罗斯方块落定后,没有可以消除的行,接着去执行make_a_teris生成一个新的俄罗斯方块,向下执行。若有某一行全为“*”,则需要消除本行,实现方法为,将本行以上的所有行向下移动一行,顶部一行置位空,实现了消除此行,然后再去从最底部检测消除后并下落后新的窗口是否有一行全为“*”。具体代码如下:

        ;功能:俄罗斯方块检测并消除动作;参数:无;返回:无check_and_dispel_action:push axpush dspush cxmov ax,terismov ds,axbegin_to_check:mov ah,23mov cx,23check_all_effective_row:call get_asterisk_num_in_a_rowcmp al,38jne is_equals_zero;若当前行全为*,则分数加38,消除这一行,从底部重新开始检测add word ptr ds:[14],38call dispel_action;消除完一行后,从最底部重新扫描检测jmp begin_to_check;若当前行*的个数为0,则终止扫描is_equals_zero:cmp al,0jne to_check_all_effective_rowjmp check_and_dispel_action_end;若当前行*的个数为大于零小于38,则去准备扫描其上面的一行to_check_all_effective_row:dec ahloop check_all_effective_rowcheck_and_dispel_action_end:pop cxpop dspop axret;功能:俄罗斯方块某一行的消除动作;参数:(ah)=需要消除的那一行的行数;返回:无dispel_action:push axpush dspush bxpush cxpush dxmov cl,ahdec clmov ch,0to_dispel:call get_asterisk_num_in_a_rowcmp al,0je dispel_action_endmov al,41push cxmov cx,38;消除一行dispel_a_row:dec ahcall get_offset_by_column_valuemov dx,ds:[bx]inc ahcall get_offset_by_column_valuemov ds:[bx],dxinc alloop dispel_a_rowpop cxdec ahloop to_dispeldispel_action_end:pop dxpop cxpop bxpop dspop axret;功能:得到俄罗斯方块区域某一行*的个数;参数:(ah)=行数(取值:0-24);返回:(al)=该行中*的个数get_asterisk_num_in_a_row:push dspush bxpush cxmov al,29hcall get_offset_by_column_valuemov cx,38mov al,0is_asterisk_check:cmp byte ptr ds:[bx],2ahjne to_is_asterisk_checkinc alto_is_asterisk_check:add bx,2loop is_asterisk_checkpop cxpop bxpop dsret

如下图,通过按→键使该方块一直向右移动,直到撞到边框后,按右键再无响应,此时按↓键使方块加速下落,到达底部后,无法再下落,且没有可以消除的行,则去生成新的俄罗斯方块来下落:

如下两张图:蓝色俄罗斯方块掉落到底部时,消除最底下的两行:

在上图中的绿色方块下落时按下↑键实现该方块的旋转,如下图:

上一篇:汇编语言贪吃蛇、俄罗斯方块双任务设计实现详解(二)——贪吃蛇详细设计

下一篇:汇编语言贪吃蛇、俄罗斯方块双任务设计实现详解(四)——双任务调度与键盘中断(完结)

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

汇编语言贪吃蛇、俄罗斯方块双任务设计实现详解(三)——俄罗斯方块详细设计相关推荐

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

    题目要求: 1.系统划分:将显示器的屏幕划分成大小相等的左右两个显示窗口,并画出每个显示窗口的边框,窗口大小适中.若左窗口贪吃蛇游戏正在进行时,切换到右窗口执行俄罗斯方块,则贪吃蛇游戏暂停,以后每按一 ...

  2. 汇编语言贪吃蛇、俄罗斯方块双任务设计实现详解(二)——贪吃蛇详细设计

    详细设计: 2.贪吃蛇详细设计: 如下图所示左下角为主程序对贪吃蛇相关子程序的调用,程序中init_left_window子程序功能为将左侧窗口非边框部分置为空.左边上侧和右侧是贪吃蛇段中,贪吃蛇程序 ...

  3. C\C++真桌面贪吃蛇,桌面操控,有音乐音效“详解”

    C\C++真桌面贪吃蛇,桌面操控,有音乐音效"详解" 1. 桌面图标贪吃蛇!采用HOOK技术HOOK桌面,可以以桌面为焦点运行贪吃蛇.有背景音乐和音效,采用管道技术,实现音乐音效混 ...

  4. c语言课程设计贪吃蛇报告,贪吃蛇C语言课程设计报告.doc

    贪吃蛇C语言课程设计报告 贪吃蛇游戏设计 姓名: 张力 学号: 完成日期: 月 日 一.设计目的 贪吃蛇游戏程序功能的实现主要是建立在二维数组和图形界面的应用上,通过编写游戏程序能够熟悉掌握相关数组和 ...

  5. C++/QT 贪吃蛇小游戏 界面设计

    C++/QT 贪吃蛇小游戏 界面设计 前言:本文所写的贪吃蛇是笔者初学QT练手的小项目,做出来的界面较为粗糙.由于很久没有接触C++,程序中类封装的不是很规范.写这篇文章,权当是记录生活了,手动狗头. ...

  6. 手机快充芯片及其技术标准和设计原理详解

    手机快充芯片及其技术标准和设计原理详解 智能手机对于宽带无线通信.图像处理等多方面的需求导致实际耗电呈指数增长.未来5G通信带宽将比4G增加10倍,4K/8K等高清视频技术逐渐应用,CPU.GPU等运 ...

  7. 16位汇编语言第二讲系统调用原理,以及各个寄存器详解

    16位汇编语言第二讲系统调用原理,以及各个寄存器详解 昨天已将简单的写了一下汇编代码,并且执行了第一个显示到屏幕的helloworld 问题? helloworld怎么显示出来了. 一丶显卡,显存的概 ...

  8. FPGA串口(UART)通信协议制定与设计思路详解示例

    串口(UART)通信协议制定与设计思路详解 1 概述 本文用于描述规定的串口通信协议,以及传输内容. 2 项目关于串口的要求 a) 支持BIT自检,1路UART上报BIT信息: b) 1路UART接口 ...

  9. pcb设计单点接地示意图_PCB设计接地详解

    PCB设计接地详解 来源:华强电子网 作者:华仔 浏览:432 时间:2016-08-10 14:18 标签: 摘要: 模拟地/数字地以及模拟电源/数字电源只不过是相对的概念.提出这些概念的主要原因是 ...

最新文章

  1. Windows安装MongoDB
  2. C_Free引用链接库
  3. iOS-英雄联盟人物展示
  4. centos6.5编译安装zabbix2.4及微信企业号告警
  5. 驱动依赖_自噬依赖的分泌因子的产生促进致癌RAS驱动的侵袭
  6. 114.二叉树展开为链表
  7. 模型预测控制(MPC)解析(五):基于状态估计的预测控制
  8. 在 Flutter 中创建一个动画屏幕
  9. 心得 ~ 使用 zlib库 解压缩 zip文件
  10. iOS 开发AVFoundation系统原生二维码扫描实现
  11. c++高级编程学习笔记4
  12. ClickHouse中文官方文档
  13. 防火墙安全策略防火墙安全区域的划分
  14. 微信小程序样式 WXSS
  15. 信号量——P、V操作、临界资源、临界区、进程同步
  16. 云桌面可通过以下三种终端设备连接使用的
  17. 移动IP的作用及意义
  18. 猿来小课Linux教程分享Shell脚本问题大全
  19. 初识物联网开发-硬件开发板选择
  20. 【渝粤题库】国家开放大学2021春2679煤矿地质题目

热门文章

  1. 网页后缀php,网页后缀php有什么含义
  2. 使用alist连接百度网盘和阿里云盘挂载到本地磁盘
  3. startActivityForResult、setResult、onActivityResult用法精炼详解
  4. Generative Adversarial Nets 论文翻译
  5. 什么是 CSRF 攻击?
  6. 有限元刚度矩阵的一维变带宽存储用C++实现(一)
  7. 荟聚新动能 数创新经济 2022全国工业App和信息消费大赛在湖南株洲举行
  8. N1文法「第1-第5」
  9. C/C++解析硬盘分区信息
  10. 微信小程序实现跟odoo的交互 使用xmlrpc和jsonrpc 持续更新中。。。