论文五子棋游戏设计与实现Word格式.docx
- 文档编号:20481691
- 上传时间:2023-01-23
- 格式:DOCX
- 页数:22
- 大小:109.46KB
论文五子棋游戏设计与实现Word格式.docx
《论文五子棋游戏设计与实现Word格式.docx》由会员分享,可在线阅读,更多相关《论文五子棋游戏设计与实现Word格式.docx(22页珍藏版)》请在冰豆网上搜索。
第一章 绪论
1.1 五子棋介绍
五子棋是起源于中国古代的传统黑白棋种之一。
现代五子棋日文称之为“連珠”,英译为“Renju”,英文称之为“Gobang”或“FIR”(FiveinaRow的缩写),亦有“连五子”、“五子连”、“串珠”、“五目”、“五目碰”、“五格”等多种称谓。
五子棋不仅能增强思维能力,提高智力,而且富含哲理,有助于修身养性。
五子棋既有现代休闲的明显特征“短、平、快”,又有古典哲学的高深学问“阴阳易理”;
它既有简单易学的特性,为人民群众所喜闻乐见,又有深奥的技巧和高水平的国际性比赛;
它的棋文化源渊流长,具有东方的神秘和西方的直观;
既有“场”的概念,亦有“点”的连接。
它是中西文化的交流点,是古今哲理的结晶。
1.2 开发背景
当前网络上流传的五子棋游戏功能并不尽善尽美,其中最主要的问题就是人机对战和网络对战不能够一起实现,所以我决定开发[1]一个既能够人机对战,又能够进行网络对战的五子棋系统。
1.3 开发环境
1.3.1 开发环境
●Intel®
Pentium®
42.0GHz,1G内存
●Microsoft®
Windows™7
VisualC++6.0
第二章 软件架构
一人游戏类
二人游戏类
软件的总体架构如图2.1:
游戏类指针
棋盘类
主界面
用户
图2.1软件架构
考虑到整个的下棋过程(无论对方是电脑抑或其他网络玩家)可以分为:
己方落子、等待对方落子、对方落子、设置己方棋盘数据这一系列过程,因此一人游戏类、二人游戏类和棋盘类之间的关系参考了AbstractFactory(抽象工厂)模式,以实现对两个不同模块进行一般化的控制。
2.1 棋盘类
整个架构的核心部分,类名为CTable。
封装了棋盘的各种可能用到的功能,如保存棋盘数据、初始化、判断胜负等。
用户操作主界面,主界面与CTable进行交互来完成对游戏的操作。
2.2 游戏模式类
用来管理人机对弈/网络对弈两种游戏模式,类名为CGame。
CGame是一个抽象类,经由它派生出一人游戏类COneGame和网络游戏类CTwoGame,如图2.2
抽象类CGame
CTwoGame
COneGame
图2.2CGame类派生关系
这样,CTable类就可以通过一个CGame类的指针,在游戏初始化的时候根据具体游戏模式的要求实例化COneGame或CTwoGame类的对象;
然后利用多态性,使用CGame类提供的公有接口就可以完成不同游戏模式下的不同功能了。
第三章 棋盘类——CTable
3.1 主要成员变量说明
3.1.1 网络连接标志——m_bConnected
用来表示当前网络连接的情况,在网络对弈游戏模式下客户端连接服务器的时候用来判断是否连接成功;
事实上,它也是区分当前游戏模式的唯一标志。
3.1.2 棋盘等待标志——m_bWait与m_bOldWait
由于在玩家落子后需要等待对方落子,m_bWait标志就用来标识棋盘的等待状态。
当m_bWait为TRUE时,是不允许玩家落子的。
在网络对弈模式下,玩家之间需要互相发送诸如悔棋、和棋这一类的请求消息,在发送请求后等待对方回应时,也是不允许落子的,所以需要将m_bWait标志置为TRUE。
在收到对方回应后,需要恢复原有的棋盘等待状态,所以需要另外一个变量在发送请求之前保存棋盘的等待状态做恢复之用,也就是m_bOldWait。
等待标志的设置,由成员函数SetWait和RestoreWait完成。
3.1.3 网络套接字——m_sock和m_conn
在网络对弈游戏模式下,需要用到这两个套接字对象。
其中m_sock对象用于做服务器时的监听之用,m_conn用于网络连接的传输。
3.1.4 棋盘数据——m_data
这是一个15*15的二位数组,用来保存当前棋盘的落子数据。
其中对于每个成员来说,0表示落黑子,1表示落白子,-1表示无子。
3.1.5 游戏模式指针——m_pGame
这个CGame类的对象指针是CTable类的核心内容。
它所指向的对象实体决定了CTable在执行一件事情时候的不同行为,具体的内容请参见“游戏模式”一节。
3.2 主要成员函数说明
3.2.1 套接字的回调处理——Accept、Connect、Receive
本程序的套接字派生自MFC的CAsyncSocket类[6],CTable的这三个成员函数就分别提供了对套接字[7]回调事件OnAccept、OnConnect、OnReceive的实际处理,其中尤以Receive成员函数重要,它之中包含了对所有网络消息(参见“消息机制”一节)的分发处理。
3.2.2 清空棋盘——Clear
在每一局游戏开始的时候都需要调用这个函数将棋盘清空,也就是棋盘的初始化工作。
在这个函数中,主要发生了这么几件事情:
●将m_data中每一个落子位都置为无子状态(-1)。
●按照传入的参数设置棋盘等待标志m_bWait,以供先、后手的不同情况之用。
●使用delete将m_pGame指针所指向的原有游戏模式对象从堆上删除。
3.2.3 绘制棋子——Draw
这无疑是很重要的一个函数,它根据参数给定的坐标和颜色绘制棋子。
绘制的详细过程如下:
●将给定的棋盘坐标换算为绘图的像素坐标。
●根据坐标绘制棋子位图。
●如果先前曾下过棋子,则利用R2_NOTXORPEN将上一个绘制棋子上的最后落子指示矩形擦除。
●在刚绘制完成的棋子四周绘制最后落子指示矩形。
3.2.4 左键消息——OnLButtonUp
作为棋盘唯一响应的左键消息,也需要做不少的工作:
●如果棋盘等待标志m_bWait为TRUE,则直接发出警告声音并返回,即禁止落子。
●如果点击时的鼠标坐标在合法坐标(0,0)~(14,14)之外,亦禁止落子。
●如果走的步数大于1步,方才允许悔棋。
●进行胜利判断,如胜利则修改UI状态并增加胜利数的统计。
●如未胜利,则向对方发送已经落子的消息。
●落子完毕,将m_bWait标志置为TRUE,开始等待对方回应。
3.2.5 绘制棋盘——OnPaint
每当WM_PAINT消息触发时,都需要对棋盘进行重绘。
OnPaint作为响应绘制消息的消息处理函数使用了双缓冲技术,减少了多次绘图可能导致的图像闪烁问题。
这个函数主要完成了以下工作:
●装载棋盘位图并进行绘制。
●根据棋盘数据绘制棋子。
●绘制最后落子指示矩形。
3.2.6 对方落子完毕——Over
在对方落子之后,仍然需要做一些判断工作,这些工作与OnLButtonUp中的类似,在此不再赘述。
3.2.7 设置游戏模式——SetGameMode
这个函数通过传入的游戏模式参数对m_pGame指针进行了初始化,代码如下:
voidCTable:
:
SetGameMode(intnGameMode)
{
if(1==nGameMode)
m_pGame=newCOneGame(this);
else
m_pGame=newCTwoGame(this);
m_pGame->
Init();
}
这之后,就可以利用OO的继承和多态特点[8]来使m_pGame指针使用相同的调用来完成不同的工作了,事实上,COneGame:
Init和CTwoGame:
Init都是不同的。
3.2.8 胜负的判断——Win
这是游戏中一个极其重要的算法,用来判断当前棋盘的形势是哪一方获胜。
其详细内容请参见“主要算法”一节。
第四章 游戏模式类——CGame
这个类负责对游戏模式进行管理,以及在不同的游戏模式下对不同的用户行为进行不同的响应。
由于并不需要CGame本身进行响应,所以将其设计为了一个纯虚类[9],它的定义如下:
classCGame
protected:
CTable*m_pTable;
public:
//落子步骤
list<
STEP>
m_StepList;
//构造函数
CGame(CTable*pTable):
m_pTable(pTable){}
//析构函数
virtual~CGame();
//初始化工作,不同的游戏方式初始化也不一样
virtualvoidInit()=0;
//处理胜利后的情况,CTwoGame需要改写此函数完成善后工作
virtualvoidWin(constSTEP&
stepSend);
//发送己方落子
virtualvoidSendStep(constSTEP&
stepSend)=0;
//接收对方消息
virtualvoidReceiveMsg(MSGSTRUCT*pMsg)=0;
//发送悔棋请求
virtualvoidBack()=0;
};
4.1 主要成员变量说明
4.1.1 棋盘指针——m_pTable
由于在游戏中需要对棋盘以及棋盘的父窗口——主对话框进行操作及UI状态设置,故为CGame类设置了这个成员。
当对主对话框进行操作时,可以使用m_pTable->
GetParent()得到它的窗口指针。
4.1.2 落子步骤——m_StepList
一个好的棋类程序必须要考虑到的功能就是它的悔棋功能,所以需要为游戏类设置一个落子步骤的列表。
由于人机对弈和网络对弈中都需要这个功能,故将这个成员直接设置到基类CGame中。
另外,考虑到使用的简便性,这个成员使用了C++标准模板库(StandardTemplateLibrary,STL)中的std:
list,而不是MFC的CList。
4.2 主要成员函数说明
4.2.1 悔棋操作——Back
在不同的游戏模式下,悔棋的行为是不一样的。
●人机对弈模式下,计算机是完全允许玩家悔棋的,但是出于对程序负荷的考虑(此原因请参见“几点补充说明”一节),只允许玩家悔当前的两步棋(计算机一步,玩家一步)。
●双人网络对弈模式下,悔棋的过程为:
首先由玩家向对方发送悔棋请求(悔棋消息),然后由对方决定是否允许玩家悔棋,在玩家得到对方的响应消息(允许或者拒绝)之后,才进行悔棋与否的操作。
4.2.2 初始化操作——Init
对于不同的游戏模式而言,也就有不同的初始化方式。
对于人机对弈模式而言,初始化操作包括以下几个步骤:
●设置网络连接状态m_bConnected为FALSE。
●设置主界面计算机玩家的姓名。
●初始化所有的获胜组合。
●如果是计算机先走,则占据天元(棋盘正中央)的位置。
网络对弈的初始化工作暂为空,以供以后扩展之用。
4.2.3 接收来自对方的消息——ReceiveMsg
这个成员函数由CTable棋盘类的Receive成员函数调用,用于接收来自对方的消息。
对于人机对弈游戏模式来说,所能接收到的就仅仅是本地模拟的落子消息MSG_PUTSTEP;
对于网络对弈游戏模式来说,这个成员函数则负责从套接字读取对方发过来的数据,然后将这些数据解释为自定义的消息结构,并回到CTable:
Receive来进行处理。
4.2.4 发送落子消息——SendStep
在玩家落子结束后,要向对方发送自己落子的消息。
对于不同的游戏模式,发送的目标也不同:
●对于人机对弈游戏模式,将直接把落子的信息(坐标、颜色)发送给COneGame类相应的计算函数。
●对于网络对弈游戏模式,将把落子消息发送给套接字,并由套接字转发给对方。
4.2.5 胜利后的处理——Win
这个成员函数主要针对CTwoGame网络对弈模式。
在玩家赢得棋局后,这个函数仍然会调用SendStep将玩家所下的制胜落子步骤发送给对方玩家,然后对方的游戏端经由CTable:
Win来判定自己失败。
第五章 消息机制
Windows系统拥有自己的消息机制,在不同事件发生的时候,系统也可以提供不同的响应方式[11]。
五子棋程序也模仿Windows系统实现了自己的消息机制,主要为网络对弈服务,以响应多种多样的网络消息。
5.1 消息机制的架构
当继承自CAsyncSocket的套接字类CFiveSocket收到消息时,会触发CFiveSocket:
OnReceive事件[12],在这个事件中调用CTable:
Receive,CTable:
Receive开始按照自定义的消息格式接收套接字发送的数据,并对不同的消息类型进行分发处理。
CFiveSocket
网络数据
CTable:
Receive
分发处理
CFiveSocket:
OnReceive
调用
图5.1自定义的消息机制
如图5.1所示,当CTable获得了来自网络的消息之后,就可以使用一个switch结构来进行消息的分发了。
5.2 各种消息说明
网络间传递的消息,都遵循以下一个结构体的形式:
//摘自Messages.h
typedefstruct_tagMsgStruct{
//消息ID
UINTuMsg;
//落子信息
intx;
inty;
intcolor;
//消息内容
TCHARszMsg[128];
}MSGSTRUCT;
随着uMsg表示消息ID,x、y表示落子的坐标,color表示落子的颜色,szMsg随着uMsg的不同而有不同的含义。
5.2.1 落子消息——MSG_PUTSTEP
表明对方落下了一个棋子,其中x、y和color成员有效,szMsg成员无效。
在人机对弈游戏模式下,亦会模拟发送此消息以达到程序模块一般化的效果。
5.2.2 悔棋消息——MSG_BACK
表明对方请求悔棋,除uMsg成员外其余成员皆无效。
接到这个消息后,会弹出MessageBox询问是否接受对方的请求(如图5.2所示),并根据玩家的选择回返MSG_AGREEBACK或MSG_REFUSEBACK消息。
另外,在发送这个消息之后,主界面上的某些元素将不再响应用户的操作。
图5.2请求悔棋
5.2.3 同意悔棋消息——MSG_AGREEBACK
表明对方接受了玩家的悔棋请求,除uMsg成员外其余成员皆无效。
接到这个消息后,将进行正常的悔棋操作。
5.2.4 拒绝悔棋消息——MSG_REFUSEBACK
表明对方拒绝了玩家的悔棋请求(如图5.3所示),除uMsg成员外其余成员皆无效。
接到这个消息后,整个界面将恢复发送悔棋请求前的状态。
图5.3拒绝悔棋
5.2.5 和棋消息——MSG_DRAW
表明对方请求和棋,除uMsg成员外其余成员皆无效。
接到这个消息后,会弹出MessageBox询问是否接受对方的请求(如图5.4所示),并根据玩家的选择回返MSG_AGREEDRAW或MSG_REFUSEDRAW消息。
图5.4请求和棋
5.2.6 同意和棋消息——MSG_AGREEDRAW
表明对方接受了玩家的和棋请求(如图5.5所示),除uMsg成员外其余成员皆无效。
接到这个消息后,双方和棋。
图5.5同意和棋
5.2.7 拒绝和棋消息——MSG_REFUSEDRAW
表明对方拒绝了玩家的和棋请求(如图5.6所示),除uMsg成员外其余成员皆无效。
接到这个消息后,整个界面将恢复发送和棋请求前的状态。
图5.6拒绝和棋
5.2.8 认输消息——MSG_GIVEUP
表明对方已经投子认输(如图5.7所示),除uMsg成员外其余成员皆无效。
接到这个消息后,整个界面将转换为胜利后的状态。
图5.7认输
5.2.9 聊天消息——MSG_CHAT
表明对方发送了一条聊天信息,szMsg表示对方的信息,其余成员无效。
接到这个信息后,会将对方聊天的内容显示在主对话框的聊天记录窗口内。
5.2.10 对方信息消息——MSG_INFORMATION
用来获取对方玩家的姓名,szMsg表示对方的姓名,其余成员无效。
在开始游戏的时候,由客户端向服务端发送这条消息,服务端接到后设置对方的姓名,并将自己的姓名同样用这条消息回发给客户端。
5.2.11 再次开局消息——MSG_PLAYAGAIN
表明对方希望开始一局新的棋局,除uMsg成员外其余成员皆无效。
接到这个消息后,会弹出MessageBox询问是否接受对方的请求(如图5.8所示),并根据玩家的选择回返MSG_AGREEAGAIN消息或直接断开网络。
图5.8再次开局
5.2.12 同意再次开局消息——MSG_AGREEAGAIN
表明对方同意了再次开局的请求,除uMsg成员外其余成员皆无效。
接到这个消息后,将开启一局新游戏。
第六章 主要算法
五子棋游戏中,有相当的篇幅是算法的部分。
无论是人机对弈,还是网络对弈,都需要合理算法的支持,本节中将详细介绍五子棋中使用的算法。
[13]
6.1 判断胜负
五子棋的胜负,在于判断棋盘上是否有一个点,从这个点开始的右、下、右下、左下四个方向是否有连续的五个同色棋子出现,如图6.1:
图6.1判断胜负方向
这个算法也就是CTable的Win成员函数。
从设计的思想上,需要它接受一个棋子颜色的参数,然后返回一个布尔值,这个值来指示是否胜利,代码如下:
BOOLCTable:
Win(intcolor)const
intx,y;
//判断横向
for(y=0;
y<
15;
y++)
{
for(x=0;
x<
11;
x++)
if(color==m_data[x][y]&
&
color==m_data[x+1][y]&
color==m_data[x+2][y]&
color==m_data[x+3][y]&
color==m_data[x+4][y])
returnTRUE;
}
//判断纵向
color==m_data[x][y+1]&
color==m_data[x][y+2]&
color==m_data[x][y+3]&
color==m_data[x][y+4])
//判断“\”方向
color==m_data[x+1][y+1]&
color==m_data[x+2][y+2]&
color==m_data[x+3][y+3]&
color==m_data[x+4][y+4])
//判断“/”方向
for(x=4;
color==m_data[x-1][y+1]&
color==m_data[x-2][y+2]&
color==m_data[x-3][y+3]&
color==m_data[x-4][y+4])
//不满足胜利条件
returnFALSE;
需要说明的一点是,由于这个算法所遵循的搜索顺序是从左到右、自上而下,因此在每次循环的时候,都有一些坐标无需纳入考虑范围。
例如对于横向判断而言,由于右边界所限,因而所有横坐标大于等于11的点,都构不成达到五子连的条件,所以横坐标的循环上界也就定为11,这样也就提高了搜索的速度。
6.2 人机对弈算法
人机对弈算法完全按照CGame基类定义的接口标准,封装在了COneGame派生类之中。
下面将对这个算法进行详细地介绍。
[14]
6.2.1 获胜组合
获胜组合是一个三维数组,它记录了所有取胜的情况。
也就是说,参考于CTable:
Win中的情况,对于每一个落子坐标,获胜的组合一共有
15*11*2+11*11*2=572种。
而对于每个坐标的获胜组合,应该设置一个[15][15][572]大小的三维数组。
在拥有了这些获胜组合之后,就可以参照每个坐标的572种组合给自己的局面和玩家的局面进行打分,也就是根据当前盘面中某一方所拥有的获胜组合多少进行权值的估算,给出最有利于自己的一步落子坐标。
由于是双方对弈,所以游戏的双方都需要一份获胜组合,也就是:
boolm_Computer[15][15][572];
//电脑获胜组合
boolm_Player[15][15][572];
//玩家获胜组合
在每次游戏初始化(COneGame:
Init)的时候,需要将每个坐标下可能的获胜组合都置为true。
此外,还需要设置计算机和玩家在各个获胜组合中所填入的棋子数:
intm_Win[2][572];
在初始化的时候,将每个棋子数置为0。
6.2.2 落子后处理
每当一方落子后,都需要作如下处理:
●如果己方此坐标的获胜组合仍为true,且仍有可能在此获胜组合处添加棋子,则将此获胜组合添加棋子数加1;
●如果对方此坐标的获胜组合仍为true,则将对方此坐标的获胜组合置为false,并将对方此获胜组合添加棋子数置为-1(不可能靠此组合
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 论文 五子棋 游戏 设计 实现
![提示](https://static.bdocx.com/images/bang_tan.gif)