贪吃蛇——汇编综合性实验

完整的实验报告和源码见贪吃蛇——汇编综合性实验(含实验报告+源码)

实现效果

实验原理分析

(1)程序总体设计
贪吃蛇游戏我们并不陌生,简单来说就是一条小蛇通过吃在地图上随机生成的食物而逐步变长,直到蛇头碰到地图边界或自己的蛇身即游戏结束。要实现此项目,我将项目大致拆解成几个部分:创建地图、初始化蛇、用于生成食物的随机数函数、实时更新蛇的移动位置、接受键盘方向键输入、判断游戏结束条件和是否吃到食物、显示游戏结束信息和得分。
除了功能的实现,还要保证程序画面的美观简洁。通过查阅课本《IBM-PC汇编语言程序设计》第10章和网上的知识,我选择了采用BIAO的10h号功能调用,设置显示方式为80*25、16色文本。显存共32KB,占用了地址为B8000H-BFFFFH的内存空间,dl:存放字符 dh:存放颜色 bl:存放列 bh:存放行,来实现在屏幕上的指定行列显示带颜色的字符,从而完成整个游戏的画面。
(2)程序简述和结构
1.程序的数据段定义

data segmentsnake_food dw 0;存储食物的坐标snake_direction dw 0;存储蛇的移动方向snake_body dw 400 dup(0);存储蛇头和蛇身的坐标score dw 0;存储玩家得分str1 db 0ah,0ah,0ah,0ah,0ah,0ah,'$';0ah表换行 str1-str4存储游戏结束的提示信息str2 db '                                                          $'str3 db '---GAME OVER---',0ah,'$'str4 db 'YOUR SCORE IS $'
data ends

2.程序的主要函数

creatMap proc near;创建地图
initSnake proc near;初始化蛇
updateSnake proc near;更新蛇的实时位置
getInput proc near;获取键盘输入
updateDirection proc near;根据键盘的输入更新蛇的移动方向
random proc near;获取随机数,范围1~23
getFoodLocation proc near;获取食物位置
creatFood proc near;生成食物
addBody proc near;吃到食物后增加蛇长,得分+1
printBlock proc near;打印方块
checkSnake proc near;判断游戏结束条件和是否吃到食物
printGameOver proc near;打印游戏结束提示信息
printScore proc near;将得分以十进制形式打印出来

(3)程序各函数的实现及原理分析(完整见实验报告)

流程图

(1)主程序流程图

(2)流程图updateSnake proc near;更新蛇的实时位置

(3)流程图getInput proc near;获取键盘输入

(4)流程图random proc near;获取随机数,范围1~23

(5)流程图addBody proc near;吃到食物后增加蛇长,得分+1

(6)流程图checkSnake proc near;判断游戏结束条件和是否吃到食物

(7)流程图printScore proc near;将得分以十进制形式打印出来

源程序

;creatMap proc near;创建地图
;initSnake proc near;初始化蛇
;updateSnake proc near;更新蛇的实时位置
;getInput proc near;获取键盘输入
;updateDirection proc near;根据键盘的输入更新蛇的移动方向
;random proc near;获取随机数,范围1~24
;getFoodLocation proc near;获取食物位置
;creatFood proc near;生成食物
;addBody proc near;吃到食物后增加蛇长,得分+1
;printBlock proc near;打印方块
;checkSnake proc near;判断游戏结束条件和是否吃到食物
;printGameOver proc near;打印游戏结束提示信息
;printScore proc near;将得分以十进制形式打印出来
data segmentsnake_food dw 0;存储食物的坐标snake_direction dw 0;存储蛇的移动方向snake_body dw 400 dup(0);存储蛇头和蛇身的坐标score dw 0;存储玩家得分str1 db 0ah,0ah,0ah,0ah,0ah,0ah,'$';0ah表换行 str1-str4存储游戏结束的提示信息str2 db '                                                          $'str3 db '---GAME OVER---',0ah,'$'str4 db 'YOUR SCORE IS $'
data endsstack segmentdw 20 dup(0)
stack endscode segmentassume cs:code,ds:data,ss:stack
start:mov ax, datamov ds, axmov ax, stackmov ss, axmov sp, 20mov ax, 0b800h;80*25显存首地址mov es, axmov ax, 3h;设置显示方式80*25 16色文本int 10hcall creatMap;创建地图call initSnake;初始化蛇call creatFood;创建食物game:;开始游戏 call updateDirection;根据键盘的输入更新蛇的移动方向;延迟函数,保证键盘输入可以及时响应,同时控制蛇移动速度mov cx, 10h;两层循坏的cx值来控制延迟时长,数值越大,延迟越长for1:push cxmov cx, 0f80hfor2:push cxcall getInput;获取键盘输入pop cxloop for2pop cxloop for1;call getInput      jmp gamegameOver:;游戏结束call printGameOver;打印游戏结束提示信息call printScore;将得分以十进制形式打印出来mov ax, 4c00hint 21h
printGameOver proc near;打印游戏结束提示信息lea dx, str1mov ah, 9int 21hlea dx, str2mov ah, 9int 21h lea dx, str3mov ah, 9int 21hlea dx, str2mov ah, 9int 21h lea dx, str4mov ah, 9int 21h ret
printGameOver endpupdateDirection proc near;根据键盘的输入更新蛇的移动方向mov ax, ds:[2];存储方向mov di, sisub di, 2;ds:[di]存储蛇头坐标cmp ax, 4800hje upcmp ax, 5000hje downcmp ax, 4b00hje leftcmp ax, 4d00hje rightup:mov ax, ds:[di]sub ah, 1jmp checkSnakedown:mov ax, ds:[di]add ah, 1jmp checkSnakeleft:mov ax, ds:[di]sub al, 1jmp checkSnakeright:mov ax, ds:[di]add al, 1;mov ds:[di], axjmp checkSnakeret
updateDirection endp        checkSnake proc near;判断游戏结束条件和是否吃到食物push ax;蛇头坐标;判断蛇头是否碰到地图边界cmp ah, 0je gameOvercmp ah, 24je gameOvercmp al, 0je gameOvercmp al, 24je gameOver;判断蛇头是否碰到蛇身mov cx, sisub cx, 6mov di, 4s0: mov bx, ds:[di]cmp bx, axje gameOveradd di, 2sub cx, 1loop s0pop ax;判断蛇头是否吃到食物mov bx, ds:[0]cmp ax, bxje addBodyjmp updateSnakeret
checkSnake endp    updateSnake proc near;更新蛇的实时位置mov cx, sisub cx, 6mov di, 4push axmov dl, ' ';字符mov dh, 0h;颜色,设与屏幕颜色相同,达到蛇移动的效果mov bx, ds:[di]call printBlocks5: mov dx, ds:[di+2]mov ds:[di], dx;依次更新蛇块的坐标add di, 2sub cx, 1loop s5mov dl, ' ';字符mov dh, 70h;颜色mov bx, ds:[di];蛇头向前移动一个单位call printBlockpop axmov ds:[di], axmov dl, ' ';字符mov dh, 40h;颜色mov bx, ds:[di];蛇头变色call printBlockret
updateSnake endp    addBody proc near;吃到食物后增加蛇长,得分+1inc score;吃到食物,得分+1mov dl, ' ';字符mov dh, 70h;颜色mov bx, ds:[di];原来的蛇头用蛇身颜色覆盖call printBlockmov ax, ds:[0]mov ds:[si], ax;将吃到食物坐标加到蛇数组,即蛇长+1mov dl, ' ';字符mov dh, 40h;颜色mov bx, ds:[si];蛇头变色call printBlockadd si, 2  call creatFood;jmp updateEndret
addBody endp    getInput proc near;获取键盘输入mov al, 0mov ah, 1;取键盘缓冲区状态int 16hcmp ah, 1;zf=1缓冲区无按键等待je getInputEndmov al, 0mov ah, 0;从键盘读字符int 16hmov cx, ax;键盘值在ax;判断输入cmp cx, 4800h;方向键上je goUpcmp cx, 5000h;方向键下je goDowncmp cx, 4b00h;方向键左je goLeftcmp cx, 4d00h;方向键右je goRightjmp getInputEnd;保证蛇不能往回走 比如蛇在往上走 不能按方向键下goUp:mov ax, ds:[2]cmp ax, 5000hje getInputEndjmp fxgoDown:mov ax, ds:[2]cmp ax, 4800hje getInputEndjmp fxgoLeft:mov ax, ds:[2]cmp ax, 4d00hje getInputEndjmp fxgoRight:mov ax, ds:[2]cmp ax, 4b00hje getInputEndjmp fxfx:;更改方向标志mov ds:[2], cxgetInputEnd:ret;结束
getInput endpinitSnake proc near;初始化蛇mov si, 4 ;保存数据段偏移量mov cx, 4;初始蛇长度mov ax, 0A04hs:;初始化蛇mov ds:[si], axadd si, 2inc alloop smov ax, 4d00h;向右mov ds:[2], ax;初始化方向mov cx, sisub cx, 6mov di, 4s1: mov ax, ds:[di]mov dl, ' ';字符mov dh, 70h;颜色mov bl, al;列mov bh, ah;行call printBlockadd di, 2sub cx, 1loop s1mov dl, ' 'mov dh, 40hmov ax, ds:[di]mov bl, almov bh, ahcall printBlockret
initSnake endp    creatMap proc near;创建地图mov dl, ' ';字符mov dh, 30h;颜色mov bl, 0;列mov bh, 0;行mov cx, 25;地图长度row:push cxpush bxcall printBlock;上边界pop bxpush bxadd bh, 24call printBlock;下边界pop bxinc bl;列加1pop cxloop rowmov bl, 0mov bh, 0mov cx, 25;地图宽度col:push cxpush bxcall printBlock;左边界pop bxpush bxadd bl, 24call printBlock;右边界pop bxinc bh;行加1pop cxloop colret
creatMap endpprintBlock proc near;打印方块mov al, 80mul bh;行乘以80mov bh, 0add bl, bl;add ax, bx;加上列即为偏移量push simov si, axadd si, simov es:[si], dlmov es:[si+1], dhmov es:[si+2], dlmov es:[si+3], dhpop siret
printBlock endpcreatFood proc near;生成食物call getFoodLocationmov dl, ' 'mov dh, 70hmov bx, ds:[0]call printBlockret
creatFood endpgetFoodLocation proc near;获取食物位置f1: call randommov ds:[0], alcall randommov ds:[1], almov cx, sisub cx, 4mov di, 4s11: mov ax, ds:[di]cmp ax, ds:[0]je f1add di, 2sub cx, 1loop s11ret
getFoodLocation endp    random proc near;获取随机数,范围1~23xor al,almov ax, 0h; 间隔定时器out 43h,al; 将0送到43h端口in al, 40h; 将40h端口的数据送至almov bl, 23   ;除8 得到范围为0-22div bl mov al, ahmov ah, 0inc al     ; 加1 得到范围为1-23ret;MOV AX, 23   ;产生从1到AX之间的随机数;MOV DX, 41H ;用端口41H、45H、49H、4DH、51H、55H、59H、5DH都可以;OUT DX, AX  ;有这句话后,就可以产生从1到AX之间的随机数了;IN AL, DX   ;产生的随机数AL;ret
random endpprintScore proc near;将得分以十进制形式打印出来mov ax, score;存放需要以十进制数显示的数push axpush bxpush cxpush dxmov bx,10mov cx,0yazhan:mov dx,0div bx;ax每次除以10,商就保存在axpush dx;余数压栈inc cx;cx计入栈个数cmp ax,0;当商不为0时,继续循环jz chuzhanjmp yazhanchuzhan:pop dx;余数分别出栈add dl,30h;变为对应的ASCII值后输出mov ah,2            int 21hloop chuzhanpop dxpop cxpop bxpop axret
printScore endpcode endsend start

调试与优化

(1)延时函数出现的问题及解决
当贪吃蛇的基本结构和功能完成后,测试时我发现一个问题:蛇移动的速度过快。这是由于cpu在执行每条指令的速度较快,此时就需要做一个延时函数来控制蛇的移动速度。思路一是设置多层空循环来延时;思路二是利用BIAO的15h号调用
思路一,由于执行每条指令都需要一定时间,利用了执行多次空循环来实现延时。经过多次测试,得出在外层循环cx=10h,内层循环cx=0f80h时蛇的移动速度较为合适,并且双层循环内部call getInput可以保证输入方向键和响应不会有延时,具体实现如下:

;延迟函数,保证键盘输入可以及时响应,同时控制蛇移动速度mov cx, 10h;两层循坏的cx值来控制延迟时长,数值越大,延迟越长for1:push cxmov cx, 0f80hfor2:push cxcall getInput;获取键盘输入pop cxloop for2pop cxloop for1

思路二利用了BIAO的15h中断,这个思路是在网上看到的,查阅了课本,没有查到ah=86h调用了什么参数或实现了什么功能,并不清楚这个思路延时的原理是什么,同时如果单纯地做个子程序用来延时再在主程序中调用,会出现输入方向键和响应有延时的情况,所以没有采用这种思路,具体实现如下:

    mov ah,86hmov cx,0x1Emov dx,0x8480;举例说明:假如延时2s, 2s=2000000us, 2000000=0x1E8480
int 15h

(2)打印游戏结束信息出现的问题及解决
我想在屏幕的右上方打印游戏结束的信息和游戏得分,开始我的思路是先改变光标的位置到指定行列,再打印字符串。于是我查阅课本,发现BIAO的10h中断,ah=2时可以设置光标位置,bh=页号,dh/dl=行/列,但测试时我发现了问题:每一次蛇头碰到地图边界时游戏并不会结束,而是会重新刷新重启游戏。后来我查阅网上信息,发现问题可能出现在页号上,每一次刷新就跳转到新页号重启游戏。
我于是直接利用DOS的21h中断,ah=9来打印多个换行和空格来定位到指定行列,再输出游戏结束的字符串,再利用十进制输出来打印得分,具体实现如下:

printGameOver proc near;打印游戏结束提示信息lea dx, str1mov ah, 9int 21hlea dx, str2mov ah, 9int 21h lea dx, str3mov ah, 9int 21hlea dx, str2mov ah, 9int 21h lea dx, str4mov ah, 9int 21h ret
printGameOver endp

(3)每一关提速优化
为了提高游戏的趣味性和难度,在每次吃到食物后蛇就会提速。要实现这个功能就要实现能够设置一定时间的延时函数,并保证每次蛇长+1后延时函数以一定的规律递减从而实现蛇的提速,我的思路是每次吃到食物后改变循环的次数,由于外层循坏的的值改变一点就会使得蛇速变化过大,不好控制,故选择每次减少内层循环的个数来实现每一关卡的蛇的提速。

体会

完整的实验报告和源码见贪吃蛇——汇编综合性实验(含实验报告+源码)

贪吃蛇——汇编综合性实验(含实验报告+源码)相关推荐

  1. c++贪吃蛇_细致的C语言写贪吃蛇教程+详细思路-适合新手附源码

    在有用C写贪吃蛇的一个想法之后,上网查了几个教程,觉得不是很能看懂.恩...或者说不是一下子就能看出来思路+具体怎么实现.所以,我花了早自习的时间想了想如何用最简单的方法实现,晚上大约两个小时写了出来 ...

  2. 贪吃蛇大战 java小游戏百度云源码

    第一次实践做了贪吃蛇,感觉还不错分享一下吧 https://pan.baidu.com/s/1TylyNo3t9M_6R7To6I29hg 提取码:8488

  3. c语言写贪吃蛇什么水平_细致的C语言写贪吃蛇教程+详细思路-适合新手附源码...

    #史上最详细的C语言贪吃蛇教程 #前言 在有用C写贪吃蛇的一个想法之后,上网查了几个教程,觉得不是很能看懂.恩...或者说不是一下子就能看出来思路+具体怎么实现.所以,我花了早自习的时间想了想如何用最 ...

  4. Python游戏开发,Python实现贪吃蛇小游戏与吃豆豆 附带源码

    开发工具 Python版本: 3.6.4 相关模块: pygame模块: 以及一些Python自带的模块. 环境搭建 安装Python并添加到环境变量,pip安装需要的相关模块即可. 原理简介 贪吃蛇 ...

  5. scratch(图形化编程工具)做一个贪吃蛇的游戏(包含视频讲解+源码)!

    用scratch做一个贪吃蛇游戏! 下边上视频讲解: 代码部分,开始按钮: 开始界面文字动画: 结束页面文字动画: 蛇头代码: 蛇身代码: 食物代码: 好了,今天的教程就分享到这里吧. 本篇文章完整代 ...

  6. java防穿墙技术_Java贪吃蛇(穿身穿墙宝物)源码

    这几天学校内实训,搞什么贪吃蛇游戏.对于GUI编程我表示很无语,没办法,也得照做! 其实基本功能的源码并非我写出来的,只是在前人的基础上做了二次开发,增加了学校要求的实现吃宝物然后可以借助宝物实现&q ...

  7. c++ 贪吃蛇的精英进阶之路 附源码

    15PB预科班的结业考试项目,仅仅学了1个月做出来的 详解 前言 一.都包含哪些功能 二.使用步骤 1.首先就要想程序的流程和怎么拆分成对象 废话不多说直接上码 前言 作业:用c++ 写一个贪吃蛇的项 ...

  8. 【课程设计|MFC】人民币大小写转换(含课程报告+源码)

    目录 简介 目 录 一.课程设计目的 二.课程设计内容与要求 三.开发环境简介 四.小组成员分工 五.系统需求分析 六.系统设计 七.系统实现及测试 八.课程设计心得体会 项目地址 结语 简介 Hel ...

  9. 基于java计算机组成原理虚拟仿真实验系统计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署

    基于java计算机组成原理虚拟仿真实验系统计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署 基于java计算机组成原理虚拟仿真实验系统计算机毕业设计源码+系统+lw文档+mysql数据库 ...

最新文章

  1. 从空军机长到大厂程序员,关系数据库之父传奇
  2. python处理大量excel数据-python往excel写入大量数据
  3. (转)MySQL 服务器内存使用
  4. docker,containerd,runc,docker-shim之间的关系
  5. php中如何调用datepicker,如何使用datepicker,ajax,php,mysql在两个日期之间生成报告?...
  6. 中篇 | 多轮对话机器之话题意图识别
  7. cocos2dx游戏开发简单入门视频教程 (cocos2d-x)- 第5天
  8. PHP问题 —— failed to open stream: HTTP request faile
  9. 几种常用网页返回顶部的代码
  10. 用51单片机怎么玩SG90舵机?
  11. 计算机软硬件配置在哪里查,如何查看电脑硬件配置信息?
  12. linux去重复程序,linux常用命令合集
  13. Springboot,Mybatis根据实体类自动建表
  14. PTA题目:7-9 抢红包 (25分)
  15. PostgreSQL 连接(JOIN)
  16. Zxing系列之设置二维码图片背景透明教程
  17. anywhere 随起随用本地服务器
  18. 关于Could not find QtWebEngineProcess.exe 进程已结束,退出代码 -1073740791 (0xC0000409) 问题
  19. 访问时发生了共享冲突是什么意思_【CUDA 基础】5.1 CUDA共享内存概述
  20. JS控制EXCEL的一些方法

热门文章

  1. 定时清理linux 服务器日志 crontab
  2. 最新五合一收款码在线生成网站源码修改版
  3. 2017 续办上海居住证和积分办理流程
  4. SCI与EI收录的外文期刊(计算机类)
  5. k8s之存储、SC、STS、DS篇(一些常见的存储方案)
  6. 【老王的脑科学谬论】从“遗忘”这件事聊一聊大分子编码说和老王谬论
  7. freeswitch设置最大呼叫时长
  8. 中台战略与中台效应!!
  9. 简单Excel微型数据库
  10. 爱奇艺怎么转换格式?用电脑把qsv格式转换成mp4的方法