四国军棋游戏毕业设计Word格式.docx
《四国军棋游戏毕业设计Word格式.docx》由会员分享,可在线阅读,更多相关《四国军棋游戏毕业设计Word格式.docx(21页珍藏版)》请在冰豆网上搜索。
usewindowsGDI+graphicsdeviceinterfacetoachievetheinterface.ThisgameusestheC/Sstructuredesign,asaserverononeoftheplayers,otherplayersconnecttotheserverasaclient.ThegamehasfinallyrealizedtheLANcreategames,jointhegameandcollaborativegame,youcanachievetherequirementsofonlinegamingintheLAN.
Keywords:
Siguojunqigame;
Onlinegaming;
Socket;
GDI+
1引言
1.1问题概述
1.1.1问题的来源
四国军棋游戏是一款非常好玩的游戏,它能够锤炼人的记忆、思维、判断和心理。
随着互联网的普及,网上军棋更是成为男女老少都喜爱的一款休闲游戏。
目前就有QQ四国军棋、联众四国军棋等。
虽然很容易就能网上对战,但是对于处于校园网的我们来说,网络确实不好,经常出现掉线的问题,因此就想到做一个局域网使用的四国国军棋,以满足诸位棋友的需求。
1.1.2目的和意义
对Socket网络编程和gdi+图形设备接口进行分析、探索和实践。
通过gdi+编程,提供友好的用户操作界面,通过Socket编程,使用TCP和UDP协议,实现局域网内的数据传递,实现了多人协同游戏的目的。
以此亦可了解C/S结构程序的基本实现方式。
1.1.3国内外研究现状
C/S结构
,即Client/Server(客户机/服务器)结构,是大家熟知的软件系统体系结构,通过将任务合理分配到Client端和Server端,降低了系统的通讯开销。
客户端和服务器端的程序不同,用户的程序主要在客户端,服务器端主要提供数据管理、数据共享、数据及系统维护和并发控制等,客户端程序主要完成用户的具体的业务。
C/S结构如图1-1所示。
局域网游戏也大多采用此结构进行设计,即以一台机子作为服务器,其他机子作为客户机,客户机连接到服务器,之后就可以在局域网中进行数据交换。
图1-1C/S结构
1.2问题剖析
1.2.1主要问题
在开发局域网游戏时,首先要解决局域网中的通信。
包含了如何在局域网中找到服务器?
如何连接到服务器?
如何进行数据交换?
在解决以上问题的基础上,根据不同的游戏编写不同的游戏逻辑处理类,在该逻辑处理类中实现了对应的游戏逻辑,如实例中的军棋,则实现相互之间的对弈等功能。
此外还需解决游戏界面的显示,如军棋中的棋子显示,按钮定位等。
1.2.2难点和关键
1、局域网中有多个服务器时,如何查找并区分出来。
2、客户端程序负责处理游戏的显示和操作界面,客户端具有简单的逻辑处理功能,同时负责接收发送与服务器端交互的数据包。
3、服务器程序负责处理服务器端逻辑、游戏逻辑以及客户端之间的网络信息传递,同时服务器端还要承担客户端数据的接收、转发工作。
1.2.3思路和方法
关于解决客户端如何在局域网中找到服务器,可以让服务器在局域网中发送广播,将自己的IP地址等信息发送出去,客户端就可通过接收广播消息,寻找到服务器的位置,同时还可根据IP地址将不同的服务器区分出来。
以此可连接到不同的服务器,继而进行服务器与客户端之间的通信。
游戏界面的显示可以通过使用gdi+图形设备接口,根据一个二维数组标识棋盘的状态,根据二维数组,使用gdi+画出棋子。
2可行性分析和需求分析
2.1可行性分析
2.1.1技术可行性分析
本程序的开发基于C/S模式,包含客户机和服务器两部分,前者主要负责简单的逻辑处理和前台界面的显示,后者主要负责游戏逻辑判断及数据交互。
网络通信可使用TCP/IP协议,采用Socket套接字编程技术;
界面显示可使用GDI+图形设备接口画出界面。
1、TCP/IP协议
TCP/IP协议(TransmissionControlProtocol/InternetProtocol,传输控制协议/网际协议)是Internet中计算机进行通信的标准,其命名起源于该组协议中最重要的两个协议TCP和IP。
任何关于Internet协议的讨论必须由TCP/IP开始,它也是其他所有协议的基础。
TCP/IP协议是Internet网络的共同语言,主机之间必须利用TCP/IP互通信息。
TCP/IP实际上就是在物理网上的一组完整的协议。
其核心部分是传输层协议(TCP/UDP)、网络层(IP)和物理接口层,这三层通常在操作系统内核中实现。
TCP/UDP层提供了传输层服务,而IP协议提供了网络层服务。
TCP/IP协议是一个四层协议,其结构如图2-1所示。
图2-1TCP/IP协议体系结构图
2、WindowsSOCKET编程
WindowsSocket(简称 WinSock)是在Win32平台上访问基层网络协议的接口。
在不同的Win32平台上,WindowsSocket以不同的方式存在着,作为网络编程接口而不是协议存在。
WindowsSockets编程的基本模式,要通过互联网进行通信,你至少需要一对套接字,其中一个运行于客户端,我们称之为ClientSocket,另一个运行于服务器端,我们称之为ServerSocket。
使用Socket进行网络通信一般有两种方式:
基于面向连接的流方式和基于无连接的数据报方式。
面向连接的的流方式调用过程如图2-2所示。
图2-2面向连接的流方式调用过程
3、GDI+图形设备接口
GDI+是WindowsXP中的一个子系统,它主要负责在显示屏幕和打印设备输出有关信息,它是一组通过C++类实现的应用程序编程接口。
顾名思义,GDI+是以前版本GDI的继承者,出于兼容性考虑,WindowsXP仍然支持以前版本的GDI,但是在开发新应用程序的时候,开发人员为了满足图形输出需要应该使用GDI+,因为GDI+对以前的Windows版本中GDI进行了优化,并添加了许多新的功能。
作为图形设备接口的GDI+使得应用程序开发人员在输出屏幕和打印机信息的时候无需考虑具体显示设备的细节,他们只需调用GDI+库输出的类的一些方法即可完成图形操作,真正的绘图工作由这些方法交给特定的设备驱动程序来完成,GDI+使得图形硬件和应用程序相互隔离.从而使开发人员编写设备无关的应用程序变得非常容易。
从上述分析可以看出开发次程序,在技术上是可行的。
2.1.2经济可行性分析
由于本程序所要求的硬件(计算机及相关硬件)和软件环境(vs2008),市场上都容易购买到或从相关网站下载,而据不完全调查统计本专业电脑拥有率是接近100%,系统成本主要集中在程序的开发与维护上,对编程者不会造成过重的经济负担。
由于学校中校园网的存在,运行成本几乎可以忽略不计。
而一旦本程序投入使用,可使同学们免受校园网与外网连接时网速过慢,经常掉线的问题。
让我们可以尽情感受四国军棋的魅力。
与微小的开发成本比较,能获得好的游戏体验,获得好的心情自然是值得的,所以从经济方面来说,开发此程序是可行的。
2.1.3操作可行性分析
本程序实现了可视化界面,界面友好,操作简单,布局简洁。
本程序游戏规则和拥有较高人气的QQ四国军棋相同,只要玩过QQ四国军棋的很容易就可以上手。
在游戏操作上,只需轻点鼠标即可完成所有操作,对使用本程序的人员的计算机专业知识几乎没有要求,只需接触过计算机的人员,均能很快的熟悉本程序的操作。
2.1.4时间可行性分析
本程序的设计与完成大概分为四个阶段:
第一阶段,做需求分析,这个阶段大概花费1周时间,主要对系统要实现的功能进行分析判断,并决定实现每个基本功能所要采用的语言;
第二阶段,掌握所需技术,这个阶段大概花费2周时间,主要对本程序所采用的语言进行一些初步的了解,并查阅相关资料,对相关的算法和函数有初步的了解、认识、掌握;
第三个阶段,这个阶段是整个系统所费时间最长的阶段,大概需要4周时间,主要实现系统软件程序的编码、调试、测试,完成一个初级的版本;
第四个阶段,修改完善程序,大概需要3周时间。
因此从时间方面上讲开发此系统是可行的。
2.1.5结论
经过对本程序实现的技术、经济、操作、时间的可行性进行分析。
可得出结论:
本系统是可以实现的。
2.2需求分析
1)作为一款局域网游戏,首先应该具备的基本功能就是能够在局域网间连接;
要求能够实现,局域网中的机子能够创建游戏,即作为服务器,也能够加入游戏,即作为客户机连接到已创建游戏的服务器上。
2)四国军棋是一款多人协作游戏,因此应该要实现多人协同游戏的能力,即各客户机上能够进行数据同步。
3)为了方便,要求能够保存最近的一次游戏布局,要求游戏界面能够简洁些,游戏操作能够方便简单些。
4)想要有好的游戏体验,响应速度要求比较快,不会出现长时间等待现象,同时应具有良好的稳定性、可靠性和健壮性,可以控制一些不确定因素。
5)需实现四国军棋的游戏规则,本游戏将游戏规则定为和QQ四国军棋一样。
3总体设计
3.1总体设计的框架
图3-1总体框架图
3.2模块功能概述
1、入口程序及全局变量:
程序的入口函数WinMain
,还有定义一些结构体和全局变量,主要功能是程序循环和结束条件的判断及保存一些全局使用的变量。
2、创建窗口类:
对windows创建窗口的API进行简单的封装,实现程序基本窗口的创建。
3、网络通信类:
对Socket发送UDP广播消息
、接收UDP广播消息、发送TCP消息
、接收TCP消息进行简单的封装;
实现局域网中的数据交换。
4、大厅窗口消息处理类:
主要是大厅界面的实现,还有根据用户在大厅的不同操作启动相应的线程。
5、游戏窗口消息处理类:
主要是游戏界面的实现,还有根据用户的不同操作做出不同的响应。
6、线程处理类:
线程处理函数都集中在这里,可以根据不同功能,在启动线程时,调用不同的线程处理函数。
7、游戏逻辑处理类:
包含了棋子的定位,棋子能否启动的判断,棋子命中,选中与取消棋子的判断等相关功能的处理。
8、服务端网络消息处理类:
处理从客户端接收到的消息,主要功能是判断吃子逻辑,并根据不同的结果返回不同的消息。
9、客户端网络消息处理类:
处理从服务端接收到的消息,主要功能是根据吃子结果,对棋盘进行相应的处理。
3.3关键算法
3.3.1双缓冲技术绘图
在图形图象处理编程过程中,当数据量很大时,绘图需要很长的时间,还会引起严重的闪烁现象。
为了解决这个问题,我们可以采用双缓冲技术。
它的基本原理是,在内存中创建一个与要绘制的屏幕一样大小的内存画布,先在此内存画布中绘出所有的图形,然后将此内存画布一次性拷贝到屏幕上,使用这个方法可以有效的解决屏幕闪烁的现象。
下面是使用GDI+图形接口的实现步骤。
1、首先是创建内存画布,Bitmap*CacheImage=newBitmap(1024,708),大小应该与要绘制的屏幕区域大小相同;
2、创建好内存画布后,就可以在上面绘图,如
CacheGraphics->
Clear(Color(0,0,0));
//清楚画布
DrawImage(bg,0,0,1024,708);
//画到内存画布上
3、将要绘制的图都画到内存画布上后,就可以将其拷贝到屏幕上了,
Graphic.DrawImage(CacheImage,0,0);
//画到屏幕上
4、还要禁止windows的窗口背景重置消息WM_ERASEBKGND,只需在此消息处理时直接返回false就可以了。
3.3.2工兵寻路
1、要判断工兵是否可以到达指定位置,就类似于迷宫寻路问题,可采用多种算法,如深度优先搜索算法、广度优先搜索算法等。
我这里采用的是深度优先搜索算法
,其基本算法是
1)选取图中某一顶点Vi为出发点,访问并标记该顶点;
2)以Vi为当前顶点,依次搜索Vi的每个邻接点Vj,若Vj未被访问过,则访问和标记邻接点Vj,若Vj已被访问过,则搜索Vi的下一个邻接点;
3)以Vj为当前顶点,重复步骤2),直到图中和Vi有路径相通的顶点都被访问为止;
4)若图中尚有顶点未被访问过(非连通的情况下),则可任取图中的一个未被访问的顶点作为出发点,重复上述过程,直至图中所有顶点都被访问。
2、判断是否可走是用一个17×
17的二维数组来标识,其中用1来表示在棋盘外,用0来表示非铁路,用2来表示铁路,二维数组定义如下
intRailWayFlag[17][17]={
{1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1},
{1,1,1,1,1,1,2,2,2,2,2,1,1,1,1,1,1},
{1,1,1,1,1,1,2,0,0,0,2,1,1,1,1,1,1},
{1,1,1,1,1,2,2,2,2,2,2,2,1,1,1,1,1},
{0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2},
{0,2,0,0,0,2,2,1,2,1,2,2,2,0,0,0,2},
{0,2,0,0,0,2,2,2,2,2,2,2,2,0,0,0,2},
};
结合上面两点,使用递归方法,写出代码如下
boolGame:
:
GongbingMove(CHESSPOSfrom,CHESSPOSto,intway[][17])
{
if(from==to)//如果找到,返回真
returntrue;
if(way[from.i][from.j]!
=2)//如果不是铁路,返回假
returnfalse;
way[from.i][from.j]=3;
//设置为已找过
//继续向上下左右搜索
returnGongbingMove(CHESSPOS(from.i+1,from.j),to,way)||GongbingMove(CHESSPOS(from.i,from.j+1),to,way)
||GongbingMove(CHESSPOS(from.i-1,from.j),to,way)||GongbingMove(CHESSPOS(from.i,from.j-1),to,way);
}
//向上搜索
if(GongbingMove(CHESSPOS(from.i+1,from.j),to,RailWayFlag))
returntrue;
if(GongbingMove(CHESSPOS(from.i,from.j+1),to,RailWayFlag))//向右
if(GongbingMove(CHESSPOS(from.i-1,from.j),to,RailWayFlag))//向下
if(GongbingMove(CHESSPOS(from.i,from.j-1),to,RailWayFlag))//向左
returnfalse;
3.3.3棋盘坐标转换
如图3-2所示,四国军棋上共有四个座位可以坐下。
因为自己的棋始终是显示在下方的,所以实际上各个座位上相同棋盘坐标表示的并不是同一个棋子,如座位1的棋盘坐标(10,10)上的棋子,在座位2上的相同棋子坐标应该是(6,10)。
这就需要根据玩家所在的不同座位,对棋盘坐标进行一定的转换。
在本程序中实现坐标转换的方法是根据当前座位和接收到的座位分多次旋转90度。
旋转次数的计算方法是,将座位1、座位2、座位3、座位4分别设置一个座位标记,分别为1、2、3、4。
将接收到的座位标记减去当前座位标记,如果得到的值大于0,即是旋转次数,如果得到的值小于0,则将此值加上4,即可得到旋转次数。
例如座位2上的坐标要转换为座位4上的坐标,需旋转4减2,即2次;
座位4上的坐标要转换成座位2上的坐标,需旋转2减4加4,即也是2次。
图3-2桌子位置示意图
4详细设计
4.1模块结构
1、主模块,包含WinMain函数、CCreateWindow类。
2、网络消息处理模块,包含Socket类、Logic类、ServerNetMsg、ClientNetMsg。
3、大厅界面模块,包含HallMsgProcessing类。
4、大厅处理模块,包含HallMsgProcessing类、Threads类。
5、游戏界面模块,包含GameMsgProcessing类。
6、游戏处理模块,包含GameMsgProcessing类、Game类。
4.2模块详述
4.2.1主模块
WinMain是windows窗口程序的入口函数,即windows窗口程序是从这里开始执行的。
它的一般作用是注册并创建窗口,循环获取消息并发送到消息处理函数中,还有决定程序的结束条件。
CCreateWindow类中提供了创建和销毁窗口的接口;
也对基本窗口参数的设置进行了封装,有设置获取窗口的长和宽,设置和获取窗口的属性和扩展属性;
重载
了()运算符,用来获取窗口句柄,也有接口用来获取整个程序实例的句柄;
还对外提供了是整个窗口客户区失效
的接口。
程序刚开始的时候,先判断是否已有实例运行,如果有的话就结束程序,否则就注册窗口类,然后进入一个循环,以一个变量标识程序是否继续执行,若变量为假,则结束程序,若为真,根据当前所处位置创建大厅窗口或游戏窗口并处理窗口消息。
如图4-1所示
图4-1主模块流程图
4.2.2大厅界面模块
大厅桌子是根据一个map
来画的,这个map中保存了当前的局域网中的服务器ip等信息,据此可以画出桌子。
程序先判断map是否为空,不为空时则画出桌子,并指向map的下一个记录。
如图4-2所示
图4-2大厅界面模块流程图
4.2.3大厅处理模块
在大厅窗口创建时,我们启动一个用来接收广播消息的线程
,用来确定网络上的主机数量和位置。
因为在程序中是将按钮的位置固定死的,所以很容易就可以计算出按钮和座位所在的坐标,根据鼠标点击窗口中的坐标,可以得出是否命中按钮或座位。
在命中创建按钮时,要做的工作是结束接收广播消息线程,自己创建游戏后就不需再接收局域网中的广播消息了;
启动发送广播消息线程,我们应该告诉局域网中的用户我们创建了游戏;
启动服务线程,用来接收客户机的连接;
这里我们把服务线程独立了出来,所以本机即是服务器又是客户机,所以本机还要作为客户机连接到服务线程;
启动客户机接收线程,用来接收服务器线程发送的消息;
当然最后还需关闭大厅窗口并启动游戏窗口。
在命中座位位置时,这时我们只作为客户机连接到服务器,所以不需要向局域网广播消息,也不需要启动服务线程。
当同样的,我们不需在接收局域网中的广播消息了,所以还是需要关闭接收广播消息的线程。
接下来我们要根据命中的座位位置找出应该连接哪个服务器,找到之后就可以连接上服务器。
当然,还有必不可少的事情要做,那就是启动客户机接收线程、关闭大厅窗口和启动游戏窗口。
如图4-3所示
图4-3大厅处理模块流程图
4.2.4游戏界面模块
在此模块中,按钮和棋盘是使用固定位置的,很简单,就不再详述了。
主要是棋子的画法比较复杂,我使用的方法是用一个17×
17的二维数组标识,用数字40至32,分别表示司令至工兵,41表示地雷,31表示炸弹,30表示军棋。
根据这个二维数组就可以知道哪个棋子在棋盘的哪个位置。
知道了棋子在棋盘的位置后,确定棋子在窗口中的位置,因为棋盘的位置是固定的,所以我们可以得到棋盘上、下、左、右和中间部分第一个位置在窗口中的坐标。
各部分中的上下左右间隔是差不多的,所以亦可据此得到其他棋盘位置在窗口中的坐标。
画棋子的流程是先找到棋子在棋盘中的位置,判断属于棋盘的哪一部分,将其转换为相应部分的相对位置,根据该部分首位置的窗口坐标,计算出棋子在窗口中的坐标,对棋子图片进行相应的翻转,最后画出棋子。
如图4-4所示
图4-4游戏界面模块流程图
4.2.5游戏处理模块
在游戏界面模块的介绍中,我们知道棋子在窗口中坐标的计算方法,据此我们就可以完成棋子命中功能。
首先获取到鼠标点击的窗口坐标,根据窗口坐标判断出点击位置是棋盘的上、下、左、右或者中间部分;
找到在棋盘哪一部分后,将坐标与找到部分上棋子的坐标进行比较,如果符合,则命中,否则未命中。
棋子命中问题解决后还需解决棋子选中问题,方法是用一个变量保存选中的棋子,当鼠标点击时,判断是否命中棋子,若没有则将变量清除,若有则判断命中的是不是自己的棋子,如果不是则将变