1、它负责响应Receive的消息。服务器端和客户端都用这个socket 发送和接受数据。_ CMessg.h/CMessg.cpp:发送和接受的数据的定义。它采用串行化的方式对网络数据进行处理。五子棋规则部分包括如下文件。_ Match.h/Match.cpp:Match 类中保存着当前的棋盘,它还负责判断是否能够在指定的位置落子,是否出现输赢局面。1.4 代码详细分析下面将分析网络五子棋游戏中的网络控制、五子棋规则和视图控制部分的相关代码。_ 网络控制部分:CServerSocket、CClientSocket 和CMessg。第4 章网络游戏开发209CServerSocket 类是一个专门
2、用来监听客户端连接的Socket 类,它继承于CSocket,响应OnAccept消息。CServerSocket 类声明如下:class CServerSocket : public CSocketpublic:CFiveChessView * m_view; /主视图的指针,为接受连接函数服务UINT m_uPort; /需要监听的端口BOOL Init(UINT port, CFiveChessView* dlg); /socket 的初始化virtual void OnAccept(int nErrorCode); /接受连接消息处理函数;在ServerSocket.cpp 中的核心代
3、码如下,其中成员函数Init 负责初始化ServerSocket,而OnAccept函数负责接收客户端连接。BOOL CServerSocket:Init(UINT port, CFiveChessView* view)m_uPort=port;m_view=view;/创建socketif(Create(m_uPort)=FALSE)AfxMessageBox(Server Socket Create Error);return FALSE;/监听socketif(Listen()=FALSE)Server Listen Errorreturn TRUE;void CServerSocket
4、:OnAccept(int nErrorCode) /接受客户端连接CSocket:OnAccept(nErrorCode);/调用视图类中的连接处理函数m_view-ProcessPendingAccept();CClientSocket 类是一个专门用做会话的类,它负责数据的发送和接收。它继承自CSocket,负责响应OnReceive 和OnClose 消息。另外,作为CSocket 类的继承类,理所当然的采用了串行化的方式来处理网络数据。网络数据是由CMessg 的对象构成的。另外,在CClientSocket 类中还定义了几个静态函数,它们用来得到本机的名字和本机的IP 地址。CCl
5、ientSocket 类声明如下:class CClientSocket :210 Visual C+游戏开发技术与实例CArchive* m_aSessionIn; /输入数据的串行化CArchive* m_aSessionOut; /输出数据的串行化CSocketFile* m_sfSocketFile; /Socket 关联文件指针 /视图指针bool m_bInit; /是否初始化bool m_bClose; /连接是否已关闭void Init(CFiveChessView * view); /socket 和串行化相关的初始化BOOL SendMessage(CMessg * msg
6、); /发送消息的函数void CloseSocket(); /关闭socket 函数 /几个静态函数,用来得到主机名和主机IP 地址static int GetLocalHostName(CString &sHostName); /获得本地计算机名称static int GetIpAddress(const CString &sHostName, CString &sIpAddress);/获得本地IPsHostName, BYTE &f0,BYTE &f1,BYTE &f2,BYTE&f3);/这个静态函数根据GetLastError()返回的tag 找到网络失败的原因static CSt
7、ring ErrorReason(int tag);virtual void OnReceive(int nErrorCode); /数据接受消息的处理函数virtual void OnClose(int nErrorCode); /socket 关闭的消息处理函数ClientSocket.cpp 中的核心代码如下(构造函数负责部分初始化工作):CClientSocket:CClientSocket()m_aSessionIn=NULL;m_aSessionOut=NULL;m_sfSocketFile=NULL;m_bInit=false;m_bClose=false;析构函数负责清除内存。
8、CClientSocket()if(m_aSessionIn)delete m_aSessionIn;if(m_aSessionOut)delete m_aSessionOut;if(m_sfSocketFile)delete m_sfSocketFile;OnReceive 函数负责接收对方发送过来的数据,并对数据进行相应的处理。这是一个消息响应函数:void CClientSocket:OnReceive(int nErrorCode)OnReceive(nErrorCode);do第4 章网络游戏开发211CMessg temp;temp.Serialize(*m_aSessionIn)
9、;m_sMsgList+=temp.m_strText; /加入新的对话内容/把新的对话内容显示在主视图窗口的一个Edit 控件中m_outputedit.SetWindowText(m_view-m_sMsgList);/把Edit 窗口中显示的内容滚动到当前的位置m_iLineCurrentPos=m_view-m_outputedit.GetLineCount();m_outputedit.LineScroll(m_view-m_iLineCurrentPos);/判断对方发送过来的数据是否是落子的位置if(m_view-m_match.CanDown(temp.m_x,temp.m_y
10、,m_view-m_who2+1)/是对方发送的落子信息m_turn=temp.m_turn; /该轮到我走棋了Invalidate(FALSE); /刷新视图,显示对方的走子位置/对方是否赢了m_match.IsWin(m_view-m_who2+1,m_view-m_winpos)m_bWin=TRUE; /对方赢了m_bOver=TRUE;你输了 /显示输棋的对话框m_sMsgList+=;while (!m_aSessionIn-IsBufferEmpty();Init 函数负责初始化串行化socket:Init(CFiveChessView * view)m_sfSocketFile
11、= new CSocketFile(this);m_aSessionIn=new CArchive(m_sfSocketFile,CArchive:load);m_aSessionOut=new CArchive(m_sfSocketFile,CArchive:store);this-SendMessage 函数负责串行化数据到对方socket:BOOL CClientSocket:SendMessage(CMessg * msg)if (m_aSessionOut != NULL)msg-Serialize(*m_aSessionOut); /输出串行化m_aSessionOut-Flush
12、(); /直接发送212 Visual C+游戏开发技术与实例else/对方关闭了连接m_bClose=true;CloseSocket();关闭Socket、清除串行化数据的工作由函数CloseSocket 完成:CloseSocket()Close();对方关闭了Socket 的消息响应处理函数OnClose:OnClose(int nErrorCode)OnClose(nErrorCode);GetLocalHostName 函数负责获得本地计算机名称:int CClientSocket:GetLocalHostName(CString &sHostName)char szHostNam
13、e256;int nRetCode;nRetCode=gethostname(szHostName,sizeof(szHostName);if(nRetCode!=0)/产生错误sHostName=_T(没有取得return GetLastError();第4 章网络游戏开发213sHostName=szHostName;return 0;GetIpAddress 函数负责获得本地IP 地址:GetIpAddress(const CString &sIpAddress)struct hostent FAR * lpHostEnt=gethostbyname(sHostName);if(lpHo
14、stEnt=NULL)sIpAddress=_T(/获取IPLPSTR lpAddr=lpHostEnt-h_addr_list0;if(lpAddr)struct in_addr inAddr;memmove(&inAddr,lpAddr,4);/转换为标准格式sIpAddress=inet_ntoa(inAddr);if(sIpAddress.IsEmpty()GetIpAddress 的一个重载:f1,BYTEf2,BYTE &f3)f0=f1=f2=f3=0;f0=inAddr.S_un.S_un_b.s_b1;f1=inAddr.S_un.S_un_b.s_b2;f2=inAddr.
15、S_un.S_un_b.s_b3;f3=inAddr.S_un.S_un_b.s_b4;214 Visual C+游戏开发技术与实例CMessg 类是一个数据类,它继承于CObject。在这个程序中,让CMessg 类发挥串行化数据的作用。CMessg 类中包括了几个主要的成员变量:CString m_strText;int m_turn;int m_x;int m_y;其中m_strText 表示聊天的字符串;m_turn 表示轮到谁走棋;m_x 表示落子的水平方向的位置;m_y 表示落子的竖直方向的位置。这4 个数据构成了网络传输数据的全部信息。事实上,在发送具体的CMessg 数据的时候
16、并不需要用到所有这4 个成员变量。例如,用户只是聊天的时候,只需要填充m_strText 就可以了,m_turn、m_x 和m_y 会被初始填充为1,表示没有子落下。而当用户落子的时候,m_strText 会被初始填充成NULL,m_turn、m_x 和m_y 会被填充成具体的落子位置和轮换信息。CMessg.h 中的核心代码如下:class CMessg : public CObjectprotected:DECLARE_DYNCREATE(CMessg) /聊天的内容 /轮到谁落子 /落子的水平位置 /落子的竖直位置void Init(); /初始化virtual void Seriali
17、ze(CArchive& ar); /串行化数据类CMessg.cpp 中的核心代码如下:IMPLEMENT_DYNCREATE(CMessg, CObject)void CMessg:Init() /初始化m_strText = _T(m_x=-1;m_y=-1;m_turn=-1;Serialize(CArchive& ar) /数据串行化if (ar.IsStoring()ar _ Match 类(五子棋规则)正如前面所说的,每一种游戏都有一定的规则,Match 类正是五子棋的规则处理类。在Match 类中保存着一个当前的棋盘,它是一个二维的数组int chessboardLWLW。如果
18、chessboardxy为0,则表示(x,y)的位置上没有棋子;如果chessboardxy为1 表示该位置上有黑子;如果chessboardxy为2,则表示该位置上有白子。Match 类还负责判断是否能在某个位置落子,是否有人赢棋。Cmatch 类声明如下:#define LW 19 /棋盘的水平竖直方向的格数class MatchMatch();virtual Match();int chessboardLWLW; /0 表示没有子落下;1 表示黑子落下;2 表示白子落下BOOL CanDown(int x,int y,int who); /是否能在x,y 的位置落子BOOL IsWin(
19、int who,int pos52); /判断是否赢棋void Clear(); /清除棋盘内容Match.cpp 中的核心代码如下(在构造函数里初始化棋盘):Match:Match()for(int i=0;iLW;i+)for(int j=0;jj+)chessboardij=0;Clear 函数负责清除棋盘内容:void Match:Clear()CanDown 函数负责判断在点(x,y)位置是否能落子:216 Visual C+游戏开发技术与实例BOOL Match:CanDown(int x,int y,int who)if(x=LW|y=LW)if(chessboardxy!che
20、ssboardxy=who;判断玩家是否赢棋,如果赢棋则标注五子连珠的位置。IsWin(int who,int pos52)int i,j;for(i=0;for(j=0;if(chessboardij=who)/水平方向if(j+4LW)if(chessboardij+1=who&chessboardij+2=who&chessboardij+3=who&chessboardij+4=who) /赢棋/标注赢棋的关键子的位置for(int k=0;k5;k+)posk0=i;posk1=j+k;/垂直if(i+4if(chessboardi+1j=who&chessboardi+2j=who&chessboardi+3j=who&boardi+4j=who)posk0=i+k;posk1=j;LW&j+40&if(chessboardi-1j+1=who&chessboardi-2j+2=who&chessboardi-
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1