基于汇编语言的井字棋游戏程序开发设计

邱丑丑

发布日期: 2019-06-21 12:11:47 浏览量: 58
评分:
star star star star star star star star star star_border
*转载请注明来自write-bug.com

一、游戏背景介绍

1.1 背景介绍

井字棋,英文名叫Tic-Tac-Toe,是一种在3*3格子上进行的连珠游戏,和五子棋比较类似,由于棋盘一般不画边框,格线排成井字故得名。井字棋的具体玩法为在一个3x3的棋盘上,一个玩家用X做棋子,另一个玩家用O做棋子,谁先在棋盘上的一行、一列或对角线上画满三个棋子,即可获胜,如果棋盘下满无人胜出,即为平局。

由于井字棋玩法简单,界面比较简洁,能够快速完成游戏,因此具有较强的娱乐性,基本上每个人都会玩。所以我们将其作为我们设计的项目。

在这个项目中,我们设计为双人对战游戏,并且能够对玩家的落棋进行判断,是否符合井字棋的游戏规则。还有输赢检测机制,能立即检测出来是否有玩家获胜。

1.2 基本功能

由于井字棋只有9个棋子位,所以在我们用一种更简单的表示方法,即直接用1-9个9个数字来表示位置,其索引顺序与键盘上的数字键排列一致,下棋时玩家看着数字键下,较为简便。

当有玩家先在棋盘上的一行、一列或对角线上画满三个棋子时,该玩家获得胜利。

判断胜利的方法就是检测所有的横行和竖列以及对角线是否画满三个棋子。具体实现方法为先检查斜方向是否有三个一样的棋子,有的话对应棋子的玩家胜出,结束游戏。如果没有就继续检查横方向,如果有三个一样的棋子,对应棋子的玩家胜出,结束游戏。没有的话继续检查竖方向,如果有三个一样的棋子,对应棋子的玩家胜出,结束游戏,如果还没有,就代表没有玩家胜出。继续游戏。

当棋盘的格子都被落棋了,但是没有玩家在一行、一列或对角线上画满三个棋子,此时双方打成平手。

在玩家游戏过程中,如果玩家落棋不符合井字棋游戏规则的话,程序会提醒落棋错误,并且要求玩家重新落棋,直到玩家落棋成功。

二、核心算法思想

2.1 设计棋盘的算法

棋盘是整个游戏中的框架,玩家在落子后都会显示一个棋盘目前状态。

先绘制棋盘的上边界,然后调用绘制行的方法来绘制棋盘的内容。每个格子都由多个竖线和空格组成,这就需要不断地打印这些字符来实现,具体方法是绘制一个竖线,在绘制格子里的数字或者棋子,然后再绘制一个竖线,这样一个一个格子就绘制好了。

棋盘一共有九个格子,每行有三个格子,每画完一个格子后,就会跳转到下一个字符,画这个字符所在的格子,并且每绘制三个格子就进行换行,这样9个格子就会组成一个3x3的棋盘。

同时给棋盘里的格子和每个格子的符号以及玩家的两个棋子分配了不同的颜色,这样使得界面比较美观。

2.2 设计棋子并定义玩法的算法

该程序是一个双人游戏,这里我们的玩家有两名,所以我们可以定义棋子为X和O,通过比较指令可以规定他们依次落棋,落棋次数最多为9次,玩家落棋后即可把相应格子的数字改为玩家的棋子并涂上颜色,在游戏界面中还会提示玩家选择的格子。

2.3 检测有效数字的算法

在游戏过程中,玩家要落的必须是数字1-9,而不能是其他的字符,并且已经落棋的格子不能再落棋。首先玩家选择要从键盘上敲的字符,我们把玩家输入的字符放到寄存器中,同时进行检查数字是否有效。

通过比较指令完成对有效数字的判断。如果大于等于1并且小于等于9,则玩家输入的字符有效,如果小于1或大于9或者是其他的字符,则提醒玩家这不是一个有效数字,需要重新选择落子的位置,直到所下的棋子为有效数字。

最后一步是检查所下的是有效数字是否重复占用,玩家不能在自己以及对手之前落棋的位置进行重复落棋,必须保证不会下重复的棋子。当玩家进行重复落棋时,程序会提醒玩家该位置已经有棋子,需重新选择落棋位置,直到所选位置是新的。

2.4 检测有玩家胜利的算法

在游戏过程中,由于某个玩家在棋盘一个方向连成三个棋子便可以判定其胜利,所以需要有算法去检测三子连线。我们需要从不同方向去考虑,横方向,纵方向,斜方向,这就涉及三种检测算法。

首先进行斜方向检测。先获取斜方向上第一个和第二个棋子,进行比较,如果不一样,就进行反斜方向的检测,如果一样,继续获取该方向上第三个棋子,继续进行比较,如果还是一样的话,说明再该方向上有玩家胜出。反斜方向的检测机制与斜方向的相同。

如果斜方向没有三个一样的,则进行横方向的检测,首先是第一行的检测,获取该行的第一个棋子和第二个棋子进行比较,如果不一样进行下一行检测,一样的话就获取该行第三个棋子,进行比较,如果一样,说明在该方向上有玩家胜出,不一样的话进行下一行检测。第二行的检测方法与第一行相同。第三行检测如果不一样,就说明没有玩家胜出。

如果横方向没有三个一样的,就进行竖方向检测。首先是第一列的检测,获取该列的第一个棋子和第二个棋子进行比较,如果不一样进行下一列检测,一样的话就获取该列第三个棋子,进行比较,如果一样,说明在该方向上有玩家胜出,不一样的话进行下一列检测。第二列的检测方法与第一列相同。第三列检测如果不一样,就说明没有玩家胜出。

如果棋子已经下满,并且通过三个方向的检测,并没有玩家胜出,此时游戏平局。

2.5 界面设计

玩家每落一次棋,就更新一次棋盘。并且在游戏过程中有语句提示,一开始会有欢迎语句和规则介绍语句,之后随着玩家每落一次棋,程序都会显示当前玩家是谁,落棋的位置,当游戏结束时,会有胜利提示语句,平局会有双方打平提示语句。

三、核心算法流程图

核心算法主要分为判断落棋是否有效,判断输赢。

本程序是通过玩家输入棋盘上相应的位置数字来进行落棋,当玩家输入一个字符,判断是否是在1-9的数字,并且对应位置没有落过棋,最后根据玩家所代表的符号(X或O)来进行落棋。

当玩家落好一次棋后,程序就会从三个方向进行输赢判断。先进行斜方向判断,然乎进行横方向判断,最后进行竖方向判断,只要满足其中一种就代表有玩家获胜,还需判断出当前玩家是哪个,哪个玩家就获胜,另一个玩家就输了。

主方法的基本思路就是:首先判断玩家输入的字符是否有效,若不是则重新选择落子位置直到是有效位置,若是,则该玩家落子,程序进行输赢判断,如果有一方胜出,则游戏结束,如果没有,则临一玩家进行落棋。双方最多总共落九次,九次之后还没有玩家胜出的话,打成平局,游戏结束。如图所示。

四、开发中遇到的问题

4.1 汇编语言定义变量问题

在学习c语言和c++语言时,习惯了首先声明变量,而汇编语言中无需变量的声明,因为汇编语言是直接对具体的内存单元操作,而每个单元有16进制的地址码,因此所有变量都可人为地由该地址码表示。但是汇编语言提供了EQU伪指令,可以将特定的内存空间标记为特定的名称,这就为变量定义提供了可能。而使用EQU伪指令的好处就是将抽象的物理内存分化为具体的变量名,避免了内存冲突,同时又增加了程序可读性。

4.2 系统功能调用中遇到的问题

系统功能调用——由DOS提供的一组实现特殊功能的子程序供程序员在编写自己的程序时调用,以减轻编程的工作量。分两种,DOS系统功能调用和BIOS终端调用。汇编语言中DOS系统功能调用有很多,涉及屏幕显示、文件管理、I/O管理等等,每个子程序都有一个功能号,所有的功能调用的格式都是一致的。调用的步骤大致如下:

  • 系统功能号送到寄存器AH中;

  • 入口参数送到指定的寄存器中;

  • 用INT 21H指令执行功能调用;

  • 根据出口参数分析功能调用执行情况。

4.3 给字符上色问题

既然是游戏,那么我们就要考虑其美观性,给棋盘上色能使游戏更加美观,给棋子涂上颜色更加提高了分辨感,那么问题就在于如何给棋盘和棋子上色。这里用INT 10H 指令执行功能调用,把11送到bl寄存器中,而11所对应的二进制数1011为淡青色,这样棋盘的边框就涂上了淡青色;把14送到bl寄存器中,而14所对应的二进制数1110为黄色,这样数字就涂上了黄色;同理玩家1的棋子x涂成淡绿色,玩家2的棋子o涂成淡红色。优化游戏界面如图所示。

4.4 寄存器问题

代码中大量充斥着各种寄存器,通过查阅资料了解一些寄存器的功能,以数据寄存器为例:数据寄存器可分为8位的寄存器,作为通用寄存器,可存储算术逻辑运算的操作数和运算结果。

AX,Accumulator,通累加器,用累加器进行的操作可能需要更少时间。可用于乘、 除、输入/输出等操作,使用频率很高;
BX,Base,基址寄存器,虽然属于数据寄存器,但它经常用作地址寄存器。
CX,Count,计数寄存器,经常用作一个循环的计数,在循环语句中,默认CX的内容为循环次数。在位操作中,当移多位时,要用CX的低8位CL来指明移位的位数。
DX,Data,数据寄存器,在进行乘、除运算时,它可作为默认的操作数参与运算,但在I/O指令中,DX用于表示I/O的端口地址。

5.5 对简化主方法编写的问题

这里设计了一些子方法,子方法对程序结构化的作用是其可简化主方法的编写,使得程序主干的编写思路清晰化,而一些复杂的算法与功能则放在一层层的子方法中实现。在井字棋代码中我们设计了打印字符串,画棋盘,玩家落棋顺序,判断胜利等子方法,这些方法通常比较复杂,在执行主方法的时候可直接调用这些子方法。

五、心得体会

首先,在汇编语言这方面是零基础,刚入手的前两天简直是寸步难行。参考一些教材书又很难看懂,什么ax,bx,cx啊,看着就心烦。但是,借鉴之前学习c语言的方法,又对比了两者之间的相同思想,最后在脑海中形成了一些思维框架。我和我搭档的同学互相研究这门语言并且交换心得,感觉有了很大进步。在编写过程中用到了很多基础知识,但是在程序运行时总会出现一些问题,由于汇编基础比较薄弱,所以有时会打错了程序代码,误解了知识点,不了解程序结构等,但是通过查阅资料,请教老师并和同学讨论,最终解决了所有问题,也成功的运行出了结果。通过本次课程设计,不仅加深了我对汇编程序设计的认识,也提高了改写程序代码和动手操作的能力,还有编程的基本习惯和开发系统时应注意的流程,同时也对各种指令有了进一步的理解。并且我发现一个好的汇编程序不仅要正确可行,还要有健壮性,当用户输入非法的数据,使运行环境改变时,程序能恰当地作出反应或进行处理,不会产生莫名奇怪的输出结果。因为完成设计的时间较短,并且对汇编语言知识比较生疏,设计之中难免有一些错误和不妥之处,同时也需要改进,所以真诚的希望尊敬的老师批评指正。

在接触这门课程后,感到汇编语言并不是很容易就可以弄懂的。相比较以前学过的高级语言如C、C++等,电脑等于在迁就人的思维方式,但学汇编,人却必须要去迁就电脑的思维方式,要设身处地地用电脑的角度去思考问题,这就是我们学习汇编语言时遇到的最大的障碍。 另外,在C语言中不到10个语句构成的程序,用汇编语言却要好几十行甚至上百行。这不得不让我们对汇编产生一种恐惧感。事实上,这是完全不必要的。一旦对它的原理掌握后,编写程序就容易多了。另外,学习汇编语言能让我们更加了解计算机内部的组织结构,对我们计算机专业的学生来说,学习汇编也是提升综合能力的关键环节。

汇编的学习不仅仅是学习其语法,而更多的是学习计算机基本的体系结构。其中遇到很多新的概念,名字。如寄存器、中断、寻址方式等。这些概念在刚接触汇编这门课的时候难以理解,但在之后的学习中通过老师的讲解,自己亲手编程的方式也就渐渐清晰明了。在学习汇编语言时,指令的功能是学习和掌握的重点,要准确有效并合理的使用这些指令,必须了解一些使用的规则。现对汇编语言编程时的规则进行总结,归纳起来有三点:1、要求指令操作数的寻址方式;2、指令对标志位的影响和标志位对指令的影响;3、指令的执行时间,对可完成同样功能的指令,要选用执行时间短的指令。

上传的附件 cloud_download 井字棋程序开发设计.zip ( 217.70kb, 0次下载 )
error_outline 下载需要8点积分

发送私信

精品资源尽在此

45
文章数
0
评论数
最近文章
eject