鉴于大家对VC与C++类别十分关注,我们编辑小组在此为大家搜集整理了“C++游戏毕业设计的开发-五子棋游戏设计”一文,供大家参考学习!
客服咨询,网学网竭诚为您服务,本站永久域名:myeducs.cn | |||||||
3 棋盘类——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 在每一局游戏开始的时候都需要调用这个函数将棋盘清空,也就是棋盘的初始化工作。在这个函数中,主要发生了这么几件事情: l 将m_data中每一个落子位都置为无子状态(-1)。 l 按照传入的参数设置棋盘等待标志m_bWait,以供先、后手的不同情况之用。 l 使用delete将m_pGame指针所指向的原有游戏模式对象从堆上删除。 3.2.3 绘制棋子——Draw 这无疑是很重要的一个函数,它根据参数给定的坐标和颜色绘制棋子。绘制的详细过程如下: l 将给定的棋盘坐标换算为绘图的像素坐标。 l 根据坐标绘制棋子位图。 l 如果先前曾下过棋子,则利用R2_NOTXORPEN将上一个绘制棋子上的最后落子指示矩形擦除。 l 在刚绘制完成的棋子四周绘制最后落子指示矩形。 3.2.4 左键消息——OnLButtonUp 作为棋盘唯一响应的左键消息,也需要做不少的工作: l 如果棋盘等待标志m_bWait为TRUE,则直接发出警告声音并返回,即禁止落子。 l 如果点击时的鼠标坐标在合法坐标(0, 0)~(14, 14)之外,亦禁止落子。 l 如果走的步数大于1步,方才允许悔棋。 l 进行胜利判断,如胜利则修改UI状态并增加胜利数的统计。 l 如未胜利,则向对方发送已经落子的消息。 l 落子完毕,将m_bWait标志置为TRUE,开始等待对方回应。 3.2.5 绘制棋盘——OnPaint 每当WM_PAINT消息触发时,都需要对棋盘进行重绘。OnPaint作为响应绘制消息的消息处理函数使用了双缓冲技术,减少了多次绘图可能导致的图像闪烁问题。这个函数主要完成了以下工作: l 装载棋盘位图并进行绘制。 l 根据棋盘数据绘制棋子。 l 绘制最后落子指示矩形。 3.2.6 对方落子完毕——Over 在对方落子之后,仍然需要做一些判断工作,这些工作与OnLButtonUp中的类似,在此不再赘述。 3.2.7 设置游戏模式——SetGameMode 这个函数通过传入的游戏模式参数对m_pGame指针进行了初始化,代码如下: void CTable::SetGameMode( int nGameMode ) { if ( 1 == nGameMode ) m_pGame = new COneGame( this ); else m_pGame = new CTwoGame( this ); m_pGame->Init(); } 这之后,就可以利用OO的继承和多态特点[8]来使m_pGame指针使用相同的调用来完成不同的工作了,事实上,COneGame::Init和CTwoGame::Init都是不同的。 3.2.8 胜负的判断——Win 这是游戏中一个极其重要的算法,用来判断当前棋盘的形势是哪一方获胜。其详细内容请参见“主要算法”一节。 4 游戏模式类——CGame 这个类负责对游戏模式进行管理,以及在不同的游戏模式下对不同的用户行为进行不同的响应。由于并不需要CGame本身进行响应,所以将其设计为了一个纯虚类[9],它的定义如下: class CGame { protected: CTable *m_pTable; public: // 落子步骤 list< STEP > m_StepList; public: // 构造函数 CGame( CTable *pTable ) : m_pTable( pTable ) {} // 析构函数 virtual ~CGame(); // 初始化工作,不同的游戏方式初始化也不一样 virtual void Init() = 0; // 处理胜利后的情况,CTwoGame需要改写此函数完成善后工作 virtual void Win( const STEP& stepSend ); // 发送己方落子 virtual void SendStep( const STEP& stepSend ) = 0; // 接收对方消息 virtual void ReceiveMsg( MSGSTRUCT *pMsg ) = 0; // 发送悔棋请求 virtual void Back() = 0; }; 4.1 主要成员变量说明 4.1.1 棋盘指针——m_pTable 由于在游戏中需要对棋盘以及棋盘的父窗口——主对话框进行操作及UI状态设置,故为CGame类设置了这个成员。当对主对话框进行操作时,可以使用m_pTable->GetParent()得到它的窗口指针。 4.1.2 落子步骤——m_StepList 一个好的棋类程序必须要考虑到的功能就是它的悔棋功能,所以需要为游戏类设置一个落子步骤的列表。由于人机对弈和网络对弈中都需要这个功能,故将这个成员直接设置到基类CGame中。另外,考虑到使用的简便性,这个成员使用了C++标准模板库[10](Standard Template Library,STL)中的std::list,而不是MFC的CList。 4.2 主要成员函数说明 4.2.1 悔棋操作——Back 在不同的游戏模式下,悔棋的行为是不一样的。 l 人机对弈模式下,计算机是完全允许玩家悔棋的,但是出于对程序负荷的考虑(此原因请参见“几点补充说明”一节),只允许玩家悔当前的两步棋(计算机一步,玩家一步)。 l 双人网络对弈模式下,悔棋的过程为:首先由玩家向对方发送悔棋请求(悔棋消息),然后由对方决定是否允许玩家悔棋,在玩家得到对方的响应消息(允许或者拒绝)之后,才进行悔棋与否的操作。 4.2.2 初始化操作——Init 对于不同的游戏模式而言,也就有不同的初始化方式。对于人机对弈模式而言,初始化操作包括以下几个步骤: l 设置网络连接状态m_bConnected为FALSE。 l 设置主界面计算机玩家的姓名。 l 初始化所有的获胜组合。 l 如果是计算机先走,则占据天元(棋盘正中央)的位置。 网络对弈的初始化工作暂为空,以供以后扩展之用。 4.2.3 接收来自对方的消息——ReceiveMsg 这个成员函数由CTable棋盘类的Receive成员函数调用,用于接收来自对方的消息。对于人机对弈游戏模式来说,所能接收到的就仅仅是本地模拟的落子消息MSG_PUTSTEP;对于网络对弈游戏模式来说,这个成员函数则负责从套接字读取对方发过来的数据,然后将这些数据解释为自定义的消息结构,并回到CTable::Receive来进行处理。 4.2.4 发送落子消息——SendStep 在玩家落子结束后,要向对方发送自己落子的消息。对于不同的游戏模式,发送的目标也不同: l 对于人机对弈游戏模式,将直接把落子的信息(坐标、颜色)发送给COneGame类相应的计算函数。 l 对于网络对弈游戏模式,将把落子消息发送给套接字,并由套接字转发给对方。 4.2.5 胜利后的处理——Win 这个成员函数主要针对CTwoGame网络对弈模式。在玩家赢得棋局后,这个函数仍然会调用SendStep将玩家所下的制胜落子步骤发送给对方玩家,然后对方的游戏端经由CTable::Win来判定自己失败。 5 消息机制 Windows系统拥有自己的消息机制,在不同事件发生的时候,系统也可以提供不同的响应方式[11]。五子棋程序也模仿Windows系统实现了自己的消息机制,主要为网络对弈服务,以响应多种多样的网络消息。 5.1 消息机制的架构 当继承自CAsyncSocket的套接字类CFiveSocket收到消息时,会触发CFiveSocket::OnReceive事件[12]CTable::Receive,CTable::Receive开始按照自定义的消息格式接收套接字发送的数据,并对不同的消息类型进行分发处理。,在这个事件中调用
图5.1 自定义的消息机制 如图5.1所示,当CTable获得了来自网络的消息之后,就可以使用一个switch结构来进行消息的分发了。 5.2 各种消息说明 网络间传递的消息,都遵循以下一个结构体的形式: // 摘自Messages.h typedef struct _tagMsgStruct { // 消息ID UINT uMsg; // 落子信息 int x; int y; int color; // 消息内容 TCHAR szMsg[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成员外其余成员皆无效。接到这个消息后,将开启一局新游戏。 | |||||||
本站发布的计算机毕业设计均是完整无错的全套作品,包含开题报告+程序+论文+源代码+翻译+答辩稿PPT | |||||||
本文选自计算机毕业设计http://myeducs.cn |