联机五子棋小程序:C++ MFC创建游戏界面
利用C++,通过MFC搭建游戏界面,制作了一个可以在局域网内联机对战的五子棋小程序,在小程序中添加了电脑玩家角色,用以辅助对战(也可以将电脑玩家角色独立出来做成单机版)
放上网盘分享:
https://pan.baidu.com/s/1oTlQm3YqI7wihmXNK-qkBA
3ise
下面对程序作简要说明
(1)由于是联机游戏,双人对战,所以网络部分采用了客户端/服务器的模式。采用的Socket基类为MFC中封装的 CAsyncSocket。
(2)程序分为客户端和服务器。其中客户端部分包含三个部分:
a)chess MFC界面和游戏响应部分
b)nettask 网络交互部分
c)AIStratege 电脑玩家算法部分
其中服务器部分仅包含界面和网络交互部分
(3)MVS2017作为编译器
先给出最终的效果:
下面为完整的详细源码:
<chess.h>
#pragma once
#include <afxwin.h>#define VACANT TRUE
#define IMVACANT FALSE#define NONE 0
#define WHITE 1
#define BLACK 2#define LINENUM 15//控件
#define IDC_BUTTONCHOOSE 0x00100001
#define IDC_BUTTONNEWGAME 0x00100002//网络传输信息的MsgID
#define NETMSG_NEWGAME 1
#define NETMSG_ONEPUT 2class CMySocket;
struct OnePut
{int x;int y;int Player;
};//定义用于网络的消息传输结构
struct NetMsg
{int MsgID;OnePut aput;
};class ChessBoard
{
public:void Initialize(CPoint LUpoint);//用左上角在客户区的位置初始化它public://棋盘在客户区内的范围限制int TopBund;int LeftBund;int RightBund;int BottomBund;int GridGap;int ChessRidius=15;
public:int NofLine = LINENUM;int BrdWidth = 600; //设置为(NofLine-1)的整数倍合适int BrdHeight = 600;
};class ChessApp :public CWinApp
{
public:virtual BOOL InitInstance();
};//
class ChessFrame :public CFrameWnd
{
public:ChessFrame();~ChessFrame();
protected:afx_msg void OnPaint();afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void ChooseWhite();afx_msg void NewGame();DECLARE_MESSAGE_MAP()
private:int nput = 0;//已经放置的棋子数量OnePut* allput=NULL;//存放所有的棋子(对应位置和颜色)int* gridstate = NULL; //存放棋盘上所有位置的占用状态ChessBoard m_CBoard;int m_nWndWidth = 1000;int m_nWndHeight = 700;int ThisPlayer=BLACK;
public: // 创建棋盘void CreateChessBoard(CDC &dc);bool isInChessBoard(CPoint &point);// 放置一个棋子void PutAChess(CPoint &location, int player);void PlotAChess(CPoint &location, int player);//画一个棋子void DrawAllChess();//画出所有棋子// 将Location转换为一个PointCPoint LocationToPoint(CPoint &location);// 将Point转换为一个LocationCPoint PointToLocation(CPoint &point);// 根据一个location获取一个rectCRect GetChessRectByLocation(CPoint &location);public:void OnAIPlayer();public:CString m_strServName="192.168.1.100";int m_nServPort = 1000;CMySocket m_sConnectSocket;//用来与服务器端连接的套接字//用来处理与服务器端的通信void OnCloseConnect();void OnConnect();void OnReceive();void SendMsg(NetMsg &amsg);public://控件CButton m_btnchoose;CButton m_btnnewgame;afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
};
<chess.cpp>
#include "nettask.h"
#include "chess.h"#include "AIStratege.h"//实例化一个应用程序对象,有且仅有一个
ChessApp myapp;BOOL ChessApp::InitInstance()
{// TODO: 在此添加专用代码和/或调用基类//创建窗口ChessFrame* myframe = new ChessFrame;myframe->ShowWindow(SW_SHOWNORMAL);myframe->UpdateWindow();m_pMainWnd = myframe;//return CWinApp::InitInstance();//创建客户机端套接字对象的底层套接字,使用默认的参数if (!AfxSocketInit()) //初始化!!!{AfxMessageBox(TEXT("Failed to Initialize Sockets"), MB_OK | MB_ICONSTOP);return FALSE;}if (!myframe->m_sConnectSocket.Create()){ CString str;str.Format(TEXT("Error Code:%d "), CSocket::GetLastError());AfxMessageBox(TEXT("Failed to Create Socket!\n ") + str);return FALSE;}//调用套接字类的成员函数,连接到服务器myframe->m_sConnectSocket.Connect(myframe->m_strServName, myframe->m_nServPort);return TRUE;
}BEGIN_MESSAGE_MAP(ChessFrame,CFrameWnd)ON_WM_PAINT()ON_WM_KEYDOWN()ON_WM_PAINT()ON_WM_LBUTTONDOWN()ON_BN_CLICKED(IDC_BUTTONCHOOSE, &ChessFrame::ChooseWhite)ON_BN_CLICKED(IDC_BUTTONNEWGAME, &ChessFrame::NewGame)
END_MESSAGE_MAP()ChessFrame::ChessFrame()
{//创建一个自定义风格的窗口CString strWndClass = AfxRegisterWndClass(CS_DBLCLKS,AfxGetApp()->LoadStandardCursor(IDC_ARROW),(HBRUSH)(COLOR_3DFACE + 1),AfxGetApp()->LoadStandardIcon(IDI_WINLOGO));CreateEx(0, strWndClass, TEXT("Five VS Five"), WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL);SetWindowPos(NULL, 0, 0, m_nWndWidth, m_nWndHeight, SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);//控件CRect rect(800, 20, 860, 50);m_btnchoose.Create(TEXT("执白"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, rect, this, IDC_BUTTONCHOOSE);rect = CRect(880, 20, 940, 50);m_btnnewgame.Create(TEXT("新局"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, rect, this, IDC_BUTTONNEWGAME);//初始化allput = new OnePut[LINENUM*LINENUM];gridstate = new int[LINENUM*LINENUM];for (int i = 0; i < LINENUM*LINENUM; ++i){gridstate[i] = NONE;}CPoint pt(20, 20);m_CBoard.Initialize(pt);m_sConnectSocket.SetParent(this);
}ChessFrame::~ChessFrame()
{delete[] allput;delete[] gridstate;gridstate = NULL;allput = NULL;
}void ChessFrame::OnPaint()
{CPaintDC dc(this); // device context for painting// TODO: 在此处添加消息处理程序代码// 不为绘图消息调用 CFrameWnd::OnPaint()CreateChessBoard(dc);DrawAllChess();
}// 创建棋盘
void ChessFrame::CreateChessBoard(CDC &dc)
{// TODO: 在此处添加实现代码.//CRect rect;//GetClientRect(&rect);//客户区大小怎么确定的???////CString str;//str.Format(TEXT("h=%d,w=%d"), rect.Height(), rect.Width());//AfxMessageBox(str);CRect wdbound(m_CBoard.LeftBund, m_CBoard.TopBund, m_CBoard.RightBund, m_CBoard.BottomBund);CPen pen(PS_SOLID, 3, RGB(10, 10, 10));CBrush brush(RGB(215, 115, 5));CPen* oldpen = dc.SelectObject(&pen);CBrush* oldbrush = dc.SelectObject(&brush);dc.Rectangle(wdbound);//画出边界//画出格子CPen pen1(PS_SOLID, 2, RGB(50, 50, 50));dc.SelectObject(&pen1);for (int i = m_CBoard.TopBund; i < m_CBoard.BottomBund; i += m_CBoard.GridGap){dc.MoveTo(m_CBoard.LeftBund, i);dc.LineTo(m_CBoard.RightBund, i);}for (int i = m_CBoard.LeftBund; i < m_CBoard.RightBund; i += m_CBoard.GridGap){dc.MoveTo(i, m_CBoard.TopBund);dc.LineTo(i, m_CBoard.BottomBund);}dc.SelectObject(oldpen);dc.SelectObject(oldbrush);}bool ChessFrame::isInChessBoard(CPoint &point)
{return (point.y > m_CBoard.TopBund&&point.y<m_CBoard.BottomBund&&point.x>m_CBoard.LeftBund&&point.x < m_CBoard.RightBund);
}void ChessFrame::OnLButtonDown(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值if (isInChessBoard(point)){CPoint location = PointToLocation(point);NetMsg amsg;amsg.aput.x = location.x;amsg.aput.y = location.y;amsg.aput.Player = ThisPlayer;amsg.MsgID = NETMSG_ONEPUT;SendMsg(amsg);}//PutAChess(location, BLACK);CFrameWnd::OnLButtonDown(nFlags, point);
}void ChessFrame::ChooseWhite()
{if (ThisPlayer == WHITE){ThisPlayer = BLACK;m_btnchoose.SetWindowTextW(TEXT("执白"));}else{ThisPlayer = WHITE;m_btnchoose.SetWindowTextW(TEXT("执黑"));}}//新建一局
void ChessFrame::NewGame()
{//发送一个消息:NetMsg amsg;amsg.MsgID = NETMSG_NEWGAME;SendMsg(amsg);
}void ChessBoard::Initialize(CPoint LUpoint)
{GridGap = BrdWidth / (NofLine - 1);BrdWidth = GridGap * (NofLine - 1); //重设为GridGap的整数倍BrdHeight = BrdWidth;//设置棋盘在客户区内的范围TopBund = LUpoint.y;LeftBund = LUpoint.x;RightBund = BrdWidth + LeftBund;BottomBund = BrdHeight + TopBund;
}// 放置一个棋子
void ChessFrame::PutAChess(CPoint &location, int player)
{// TODO: 在此处添加实现代码.if (gridstate[location.y*LINENUM + location.x] == NONE){allput[nput].x = location.x;allput[nput].y = location.y;allput[nput].Player = player;gridstate[location.y*LINENUM + location.x] = player;nput++;//重绘上一个棋子if (nput > 1){CPoint lastlocation(allput[nput - 2].x, allput[nput - 2].y);PlotAChess(lastlocation, allput[nput-2].Player);}PlotAChess(location, player);//画标记CClientDC dc(this);CRect rect = GetChessRectByLocation(location);dc.SetROP2(R2_NOT);//设置绘图模式dc.MoveTo((rect.left + rect.right) / 2.0, rect.top + rect.Height()/4);dc.LineTo((rect.left + rect.right) / 2.0, rect.bottom - rect.Height() / 4);dc.MoveTo(rect.left + rect.Height() / 4, (rect.top + rect.bottom) / 2.0);dc.LineTo(rect.right - rect.Height() / 4, (rect.top + rect.bottom) / 2.0);}
}//画出一个棋子
void ChessFrame::PlotAChess(CPoint &location, int player)
{//画出当前的棋子CClientDC dc(this);CBrush brush1(RGB(0, 0, 0));CBrush brush2(RGB(255, 255, 255));CRect rect = GetChessRectByLocation(location);if (player == WHITE)dc.SelectObject(&brush2);elsedc.SelectObject(&brush1);dc.Ellipse(&rect);
}void ChessFrame::DrawAllChess()
{CClientDC dc(this);CBrush brush1(RGB(0, 0, 0));CBrush brush2(RGB(255, 255, 255));CRect rect;CPoint location;int player;for (int i = 0; i < nput; ++i){location.x = allput[i].x;location.y = allput[i].y;player = allput[i].Player;rect = GetChessRectByLocation(location);if (player == WHITE)dc.SelectObject(&brush2);elsedc.SelectObject(&brush1);dc.Ellipse(&rect);}
}// 将Location转换为一个Point
CPoint ChessFrame::LocationToPoint(CPoint &location)
{// TODO: 在此处添加实现代码.int x, y;x = location.x*m_CBoard.GridGap+m_CBoard.LeftBund;y=location.y*m_CBoard.GridGap+m_CBoard.TopBund;return CPoint(x,y);
}// 将Point转换为一个Location
CPoint ChessFrame::PointToLocation(CPoint &point)
{// TODO: 在此处添加实现代码.//还需要处理点击在棋盘外面的情况int x,y;x = 1.0*(point.x - m_CBoard.LeftBund) / m_CBoard.GridGap + 0.5;y = 1.0*(point.y - m_CBoard.TopBund) / m_CBoard.GridGap + 0.5;return CPoint(x,y);
}// 根据一个location获取一个rect
CRect ChessFrame::GetChessRectByLocation(CPoint &location)
{// TODO: 在此处添加实现代码.CPoint point;point = LocationToPoint(location);return CRect(point.x-m_CBoard.ChessRidius,point.y- m_CBoard.ChessRidius,point.x+ m_CBoard.ChessRidius,point.y+ m_CBoard.ChessRidius);
}void ChessFrame::OnAIPlayer()
{CPoint location;location =CallAIPlayer(gridstate,LINENUM,nput);if (location.x > -1&&location.y>-1){//画出当前的棋子CClientDC dc(this);CBrush brush1(RGB(180, 180, 180));CRect rect = GetChessRectByLocation(location);dc.SelectObject(&brush1);dc.Ellipse(&rect);}
}//
void ChessFrame::OnCloseConnect()
{m_sConnectSocket.Close();//关闭客户端的连接套接字
}void ChessFrame::OnConnect()
{}void ChessFrame::OnReceive()
{char *pBuf = new char[1025];//客户机的数据接收缓冲区int nBufSize = 1024;//可接收的最大长度int nReceived; //实际接收到的数据长度NetMsg* pamsg;//接收套接字中的服务器发来的消息nReceived = m_sConnectSocket.Receive(pBuf, nBufSize);if (nReceived != SOCKET_ERROR) //判断接收成功{pBuf[nReceived] = NULL; //如果接收成功,将字符串的结尾置为空pamsg = (NetMsg*)pBuf; //把消息复制到变量中//解析接收到的消息switch (pamsg->MsgID){case NETMSG_ONEPUT:{CPoint location(pamsg->aput.x, pamsg->aput.y);PutAChess(location, pamsg->aput.Player);}break;case NETMSG_NEWGAME://接收到新建局的消息for (int i = 0; i < LINENUM*LINENUM; ++i){nput = 0;gridstate[i] = NONE;}Invalidate();break;default:break;}}else{AfxMessageBox(TEXT("数据接收错误!"), MB_OK | MB_ICONSTOP);}
}void ChessFrame::SendMsg(NetMsg &amsg)
{int nLen; //消息的长度int nSent; //被发送的消息的长度nLen = sizeof(NetMsg); //获得消息的长度nSent = m_sConnectSocket.Send(LPCTSTR(&amsg), nLen);//(char*)&acput 发送消息,并返回实际发送的字节长度if (nSent != SOCKET_ERROR) //检测是否发送成功{//AfxMessageBox(TEXT("数据发送成功!"));}else{AfxMessageBox(TEXT("数据发送错误!"), MB_OK | MB_ICONSTOP);}
}void ChessFrame::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{// TODO: 在此添加消息处理程序代码和/或调用默认值switch (nChar){case VK_SPACE:OnAIPlayer();break;default:break;}//CFrameWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
<nettask.h>
#pragma once
#include <afxsock.h>class ChessFrame;class CMySocket :public CAsyncSocket
{
public:CMySocket();~CMySocket();private:ChessFrame* m_pFrm;public:virtual void OnClose(int nErrorCode);virtual void OnConnect(int nErrorCode);virtual void OnReceive(int nErrorCode);void SetParent(ChessFrame* pFrm);
};
<nettask.cpp>
#include <afxsock.h>
#include "nettask.h"
#include "chess.h"CMySocket::CMySocket()
{m_pFrm = NULL;
}CMySocket::~CMySocket()
{m_pFrm = NULL;
}void CMySocket::SetParent(ChessFrame* pFrm)
{m_pFrm = pFrm;
}void CMySocket::OnClose(int nErrorCode)
{// TODO: 在此添加专用代码和/或调用基类if (nErrorCode == 0) m_pFrm->OnCloseConnect();//CAsyncSocket::OnClose(nErrorCode);
}void CMySocket::OnConnect(int nErrorCode)
{// TODO: 在此添加专用代码和/或调用基类if (nErrorCode == 0) m_pFrm->OnConnect();//CAsyncSocket::OnConnect(nErrorCode);
}void CMySocket::OnReceive(int nErrorCode)
{// TODO: 在此添加专用代码和/或调用基类if (nErrorCode == 0) m_pFrm->OnReceive();//CAsyncSocket::OnReceive(nErrorCode);
}
<AIStratege.h>
#pragma once
#include <afxwin.h>int chessscore(int x, int y, int player, int* gridstate,int line); //棋盘权值函数
CPoint CallAIPlayer(int* gridstate,int line, int nput);
<AIStratege.cpp>
#include<math.h>#include "AIStratege.h"CPoint CallAIPlayer(int* gridstate,int line,int nput)//nput相邻数目
{int i, j, cscore, cscorel, pscore, pscorel, row1, col1, row2, col2, x, y;cscore = pscore = 0; row1 = row2 = col1 = col2 = 0;CPoint aput;if (nput == 1){srand((unsigned)time(NULL));row1 = rand() % line;col1 = rand() % line;while (gridstate[row1*line+ col1]!=0){row1 = rand() % line;col1 = rand() % line;}//一个返回点aput.x = col1; aput.y = row1;return aput;}else{for (i = 0; i < line; i++){for (j = 0; j < line; j++){if (gridstate[i*line + j] == 0){cscorel = chessscore(i, j, 1,gridstate,line);if (cscorel > cscore){cscore = cscorel;row1 = i;col1 = j;}pscorel = chessscore(i, j, 2, gridstate,line);if (pscorel > pscore){pscore = pscorel;row2 = i;col2 = j;}}}}if (nput == 3){//一个返回点aput.x = col1; aput.y = row1;return aput;}else{if (cscore >= pscore){//一个返回点aput.x = col1; aput.y = row1;return aput;}else{//一个返回点aput.x = col2; aput.y = row2;return aput;}}}aput.x = -1; aput.y = -1;return aput;
}int chessscore(int x, int y, int player,int* gridstate,int line) //棋盘权值函数
{int count3, count4, sumscore = 0;char u, d, l, r, lu, ld, ru, rd; //u上 d下 l左 r右 lu左斜上 ld左斜下 ru右斜上 rd右斜下int row, col, count1, count2; //1表示横向 2表示竖向 3表示斜上方向 4表示斜下方向count1 = count2 = count3 = count4 = 1;l = r = u = d = lu = ld = ru = rd = 0;gridstate[x*line + y] = player; //模拟下棋/*---------------------------------------①判断横向棋子并记录空格子---------------------------*/row = x, col = y + 1;while (gridstate[row*line + col] == player && col < line){count1++;col++;}while (col < line && gridstate[row*line + col] == 0){r++;col++;}row = x, col = y - 1;while (gridstate[row*line + col] == player && col >= 0){count1++;col--;}while (col >= 0 && gridstate[row*line + col] == 0){l++;col--;}/*------------------------------------------------------------------------------------------*//*-------------------------------------②判断竖向棋子并记录空格子---------------------------*/row = x + 1, col = y;while (gridstate[row*line + col] == player && row < line){count2++;row++;}while (row < line && gridstate[row*line + col] == 0){d++;row++;}row = x - 1, col = y;while (gridstate[row*line + col] == player && row >= 0){count2++;row--;}while (row >= 0 && gridstate[row*line + col] == 0){u++;row--;}/*------------------------------------------------------------------------------------------*//*------------------------------------③判断斜上向棋子并记录空格子--------------------------*/row = x - 1, col = y + 1;while (gridstate[row*line + col] == player && col < line && row >= 0){count3++;col++;row--;}while (col < line && row >= 0 && gridstate[row*line + col] == 0){ru++;col++; row--;}row = x + 1, col = y - 1;while (gridstate[row*line + col] == player && col >= 0 && row < line){count3++;col--;row++;}while (col >= 0 && row < line && gridstate[row*line + col] == 0){ld++;col--;row++;}/*------------------------------------------------------------------------------------------*//*-----------------------------------④判断斜下向棋子并记录空格子---------------------------*/row = x + 1, col = y + 1;while (gridstate[row*line + col] == player && col < line && row < line){count4++; col++; row++;}while (col < line && row < line && gridstate[row*line + col] == 0){rd++; col++; row++;}row = x - 1, col = y - 1;while (gridstate[row*line + col] == player && col >= 0 && row >= 0){count4++; col--; row--;}while (col >= 0 && row >= 0 && gridstate[row*line + col] == 0){lu++; col--; row--;}/*------------------------------------------------------------------------------------------*/gridstate[x*line + y] = 0;//恢复为空置状态if (count1 >= 5 || count2 >= 5 || count3 >= 5 || count4 >= 5) //判断五子{return sumscore = 5000000;}if ((count1 == 4 && count2 == 4 && l >= 1 && r >= 1 && u >= 1 && d >= 1)|| (count1 == 4 && count3 == 4 && l >= 1 && r >= 1 && ru >= 1 && ld >= 1)|| (count1 == 4 && count4 == 4 && l >= 1 && r >= 1 && rd >= 1 && lu >= 1)|| (count2 == 4 && count3 == 4 && u >= 1 && d >= 1 && ru >= 1 && ld >= 1)|| (count2 == 4 && count4 == 4 && u >= 1 && d >= 1 && lu >= 1 && rd >= 1)|| (count3 == 4 && count4 == 4 && ru >= 1 && ld >= 1 && lu >= 1 && rd >= 1)) //判断双活四{return sumscore = 4000000;}if ((count1 == 4 && l >= 1 && r >= 1) || (count2 == 4 && u >= 1 && d >= 1)|| (count3 == 4 && ru >= 1 && ld >= 1) || (count4 == 4 && lu >= 1 && rd >= 1)) //判断活四{return sumscore = 800000;}if ((count1 == 4 && ((l == 0 && r >= 1) || (l >= 1 && r == 0)))|| (count2 == 4 && ((u == 0 && d >= 1) || (u >= 1 && d == 0)))|| (count3 == 4 && ((ld == 0 && ru >= 1) || (ld >= 1 && ru == 0)))|| (count4 == 4 && ((lu == 0 && rd >= 1) || (lu >= 1 && rd == 0)))){sumscore = sumscore + 35000; //成四}if ((count1 == 3 && count2 == 3 && l >= 1 && r >= 1 && u >= 1 && d >= 1)|| (count1 == 3 && count3 == 3 && l >= 1 && r >= 1 && ru >= 1 && ld >= 1)|| (count1 == 3 && count4 == 3 && l >= 1 && r >= 1 && rd >= 1 && lu >= 1)|| (count2 == 3 && count3 == 3 && u >= 1 && d >= 1 && ru >= 1 && ld >= 1)|| (count2 == 3 && count4 == 3 && u >= 1 && d >= 1 && lu >= 1 && rd >= 1)|| (count3 == 3 && count4 == 3 && ru >= 1 && ld >= 1 && lu >= 1 && rd >= 1)) //判断双活三{return sumscore + 400000;}if ((count1 == 3 && l >= 1 && r >= 1) || (count2 == 3 && u >= 1 && d >= 1)|| (count3 == 3 && ru >= 1 && ld >= 1) || (count4 == 3 && lu >= 1 && rd >= 1)){sumscore = sumscore + 60000;return sumscore;} //判断活三if ((count1 == 2 && count2 == 2 && l >= 1 && r >= 1 && u >= 1 && d >= 1)|| (count1 == 2 && count3 == 2 && l >= 1 && r >= 1 && ru >= 1 && ld >= 1)|| (count1 == 2 && count4 == 2 && l >= 1 && r >= 1 && rd >= 1 && lu >= 1)|| (count2 == 2 && count3 == 2 && u >= 1 && d >= 1 && ru >= 1 && ld >= 1)|| (count2 == 2 && count4 == 2 && u >= 1 && d >= 1 && lu >= 1 && rd >= 1)|| (count3 == 2 && count4 == 2 && ru >= 1 && ld >= 1 && lu >= 1 && rd >= 1)){sumscore = sumscore + 20000; //判断双活二}if ((count1 == 2 && l >= 1 && r >= 1) || (count2 == 2 && u >= 1 && d >= 1)|| (count3 == 2 && ru >= 1 && ld >= 1) || (count4 == 2 && lu >= 1 && rd >= 1)){sumscore = sumscore + 10000; //单活二}return sumscore;
}
下面是服务器部分的详细源码:
<ChessServ.h>
#pragma once
#include <afxwin.h>class CMySocket;
struct OnePut
{int x;int y;int Player;
};//定义用于网络的消息传输结构
struct NetMsg
{int MsgID;OnePut aput;
};class CServApp :public CWinApp
{
public:virtual BOOL InitInstance();
};class CServFrm :public CFrameWnd
{
public:CServFrm();public://afx_msg void OnPaint();DECLARE_MESSAGE_MAP()public:CString m_strServName= "192.168.1.100";int m_nServPort = 1000;// 用来监听客户机端连接请求的套接字CMySocket m_sListenSocket;// 用来与客户端连接的套接字int Nconnect = 0;//CString rSocketAddress1;//UINT rSocketPort1;//CString rSocketAddress2;//UINT rSocketPort2;CMySocket m_sConnectSocket1;CMySocket m_sConnectSocket2;void OnCloseListen();void OnAccept();void OnRecieve(CMySocket &socket);void SendMsg(NetMsg &amsg);
};
<ChessServ.cpp>
#include "CMysocket.h"
#include "ChessServ.h"CServApp myapp;BOOL CServApp::InitInstance()
{// TODO: 在此添加专用代码和/或调用基类CServFrm* servfrm = new CServFrm;servfrm->ShowWindow(SW_SHOWNORMAL);servfrm->UpdateWindow();m_pMainWnd = servfrm;if (!AfxSocketInit()) //初始化!!!{AfxMessageBox(TEXT("Failed to Initialize Sockets"), MB_OK | MB_ICONSTOP);return FALSE;}if (servfrm->m_sListenSocket.Create(servfrm->m_nServPort))AfxMessageBox(TEXT("成功创建listen"));elseAfxMessageBox(TEXT("创建listen失败"));//开始监听if(servfrm->m_sListenSocket.Listen())AfxMessageBox(TEXT("服务器开启监听"));else{AfxMessageBox(TEXT("服务器开启监听失败"));return FALSE;}return TRUE;
}BEGIN_MESSAGE_MAP(CServFrm,CFrameWnd)//ON_WM_PAINT()
END_MESSAGE_MAP()CServFrm::CServFrm()
{CRect rect(200, 200, 600, 500);Create(NULL, TEXT("ChessServ"), WS_OVERLAPPEDWINDOW, rect);//网络部分开始m_sConnectSocket1.SetParent(this);m_sConnectSocket2.SetParent(this);m_sListenSocket.SetParent(this);
}//void CServFrm::OnPaint()
//{
//
//}void CServFrm::OnCloseListen()
{m_sConnectSocket1.Close();m_sConnectSocket2.Close();m_sListenSocket.Close();
}void CServFrm::OnAccept()
{Nconnect++;if (Nconnect < 2){m_sListenSocket.Accept(m_sConnectSocket1);//rSocketAddress1 = rSocketAddress;//rSocketPort1 = rSocketPort;//CString str;//str.Format(TEXT("rSocketProt:%d "), rSocketPort);//AfxMessageBox(rSocketAddress+str);//输出 0.0.0.0 1000} else{m_sListenSocket.Accept(m_sConnectSocket2);//rSocketAddress2 = rSocketAddress;//rSocketPort2 = rSocketPort;//CString str;//str.Format(TEXT("rSocketProt:%d "), rSocketPort);//AfxMessageBox(rSocketAddress+str);//输出 0.0.0.0 1000}AfxMessageBox(TEXT("服务器收到一个连接"));
}void CServFrm::OnRecieve(CMySocket &socket)
{char *pBuf = new char[1025];//客户机的数据接收缓冲区int nBufSize = 1024;//可接收的最大长度int nReceived; //实际接收到的数据长度NetMsg* pamsg;//CString str;//str.Format(TEXT("rSocketProt:%d "), rSocketPort);//AfxMessageBox(rSocketAddress + str);//输出127.0.0.1 1000//接收套接字中的服务器发来的消息//int playerid = 0;//if (rSocketAddress == rSocketAddress1 && rSocketPort == rSocketPort1)//{nReceived = socket.Receive(pBuf, nBufSize);// playerid = 1;//} //else if (rSocketAddress == rSocketAddress2 && rSocketPort == rSocketPort2)//{// nReceived = m_sConnectSocket2.Receive(pBuf, nBufSize);// playerid = 2;//}if (nReceived != SOCKET_ERROR) //判断接收成功{pBuf[nReceived] = NULL; //如果接收成功,将字符串的结尾置为空pamsg = (NetMsg*)pBuf; //把消息复制到变量中//解析接收到的消息//处理接收到的信息//AfxMessageBox(TEXT("服务器收到一个信息"));//OnePut bput;//bput.x = acput->x + 1;//bput.y = acput->y + 1;//bput.Player = TRUE;SendMsg(*pamsg);}else{AfxMessageBox(TEXT("数据接收错误!"), MB_OK | MB_ICONSTOP);}}void CServFrm::SendMsg(NetMsg &amsg)
{int nLen; //消息的长度int nSent; //被发送的消息的长度nLen = sizeof(NetMsg); //获得消息的长度nSent = m_sConnectSocket2.Send(LPCTSTR(&amsg), nLen);//(char*)&acput 发送消息,并返回实际发送的字节长度nSent = m_sConnectSocket1.Send(LPCTSTR(&amsg), nLen);//(char*)&acput 发送消息,并返回实际发送的字节长度if (nSent != SOCKET_ERROR) //检测是否发送成功{}else{AfxMessageBox(TEXT("数据发送错误!"), MB_OK | MB_ICONSTOP);}
}
<CMysocket.h>
#pragma once
#include <afxsock.h>class CServFrm;
class CMySocket : public CAsyncSocket
{
public:CMySocket();~CMySocket();virtual void OnAccept(int nErrorCode);virtual void OnClose(int nErrorCode);virtual void OnReceive(int nErrorCode);private:CServFrm* m_pFrm;public:void SetParent(CServFrm* pFrm);
};
<CMysocket.cpp>
#include "CMysocket.h"
#include "ChessServ.h"CMySocket::CMySocket()
{m_pFrm = NULL;
}CMySocket::~CMySocket()
{m_pFrm = NULL;
}void CMySocket::OnAccept(int nErrorCode)
{// TODO: 在此添加专用代码和/或调用基类if (nErrorCode == 0) m_pFrm->OnAccept();//CAsyncSocket::OnAccept(nErrorCode);
}void CMySocket::OnClose(int nErrorCode)
{// TODO: 在此添加专用代码和/或调用基类if (nErrorCode == 0) m_pFrm->OnCloseListen();//CAsyncSocket::OnClose(nErrorCode);
}void CMySocket::OnReceive(int nErrorCode)
{// TODO: 在此添加专用代码和/或调用基类if (nErrorCode == 0) m_pFrm->OnRecieve(*this);//CAsyncSocket::OnReceive(nErrorCode);
}void CMySocket::SetParent(CServFrm* pFrm)
{m_pFrm = pFrm;
}
联机五子棋小程序:C++ MFC创建游戏界面相关推荐
- 编写五子棋的完整python代码_python实现五子棋小程序
本文实例为大家分享了python实现五子棋小程序的具体代码,供大家参考,具体内容如下 一.结合书上例子,分三段编写: wuziqi.py #coding:utf-8 from win_notwin i ...
- python五子棋程序教程_python实现五子棋小程序
本文实例为大家分享了python实现五子棋小程序的具体代码,供大家参考,具体内容如下 一.结合书上例子,分三段编写: wuziqi.py #coding:utf-8 from win_notwin i ...
- hbulider初学教程及html5五子棋小程序
一.JavaScript简介 JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript引擎,为浏览器的一部分, ...
- python之用循环实现五子棋小程序
在python中我们学过流程控制中的循环结构,现在我们来进行一个小应用的练习 本程序是通过循环控制结构来实现五子棋小程序的 游戏规则 五子棋的规则如下: 对局双方各执一色棋子. 空棋盘开局. 黑先.白 ...
- 基于微信小程序的五子棋小程序(含简单人机)
基于微信小程序的五子棋小程序(含简单人机) 运行截图 项目结构目录 基本思路 实现过程 棋盘的生成 落子 判断胜负 悔棋 人机对战的实现 权值表 机器人落子逻辑 改进胜负判断方法 更多功能 结语 运行 ...
- 怎么创建小程序?如何创建一个小程序呢?
怎么创建小程序?如何创建一个小程序呢?关于怎么创建小程序,是对于一些初次接触小程序或者是想拥有小程序的企业商家来说首先想要搞清楚的问题,其实创建小程序的方法很简单,下面就给大家简单介绍一下怎么创建小程 ...
- 网络联机五子棋小游戏(C++)
目录 项目简介 整体效果展示 菜单 本地游戏 网络游戏 游戏大厅 对局效果 部分代码 ending 项目简介 这是一个具备实时联机对局功能的五子棋游戏项目,该项目分为客户端与服务端两部分,客户端页面基 ...
- 一、微信小程序-快速回顾(创建项目、项目结构分析)
文章目录 一. 创建微信小程序项目 1.1. 准备工作 1.2. 创建微信小程序项目 二.项目结构分析 2.1. 其他文件 2.2. 全局文件 2.3. 页面文件 前言:软件开发需要学习的东西真的是太 ...
- 微信小程序五(创建轮播图)
应用中最常见的就是轮播图了,今儿个就讲讲微信小程序中轮播图的使用 轮播图,不外乎俩个要素,跳转链接 和 图片地址 1. 设置数据 我在 pages/test/test.js中添加如下数据 //test ...
最新文章
- php与js的关系,Php与Js的交互
- 笔记-项目沟通管理-沟通表达方式
- 主成分分析法_主成分分析法在地震学领域的新应用
- 二次重建基本完成辣!
- gulp webpack整合
- jenkins组权限_JENKINS针对不同项目组对用户进行权限分配-阿里云开发者社区
- qt creator php扩展,用qt creator搭建开发、调试php扩展的环境
- CentOS7.2安装Oracle12.1.0.2
- 特斯拉起诉小鹏汽车员工窃取 30 多万份商业机密,何小鹏回应
- Exadata Griddisk Can't be auto added
- CentOS 6.9下的iptables在本机用DNAT转发指定IP到内网IP无效的问题解决(127.0.0.1)
- vi 编辑器基本命令
- mysql日常工作中批量插入效率问题
- div内容上下左右居中
- 三角形中重心、内心、外心、垂心向量计算公式
- Python工程师Java之路(n)手写中文分词
- C#里的进制与ASCII转换
- 打开win10应用商店,提示管理员已阻止这个应用
- 天黑请闭眼 杀人游戏 规则
- 京东优惠券获取、分析
热门文章
- android 图像对比度,关于opengl-es:Android-OpenGL-ES-反相曝光对比度饱和度色调滤镜
- IMU 惯性测量单元 介绍(一)
- iOS学习笔记2-使用Audio Queues录音,取得实时PCM数据
- word中做电子签名
- 2015中兴校园招聘 软件A卷
- Tomcat 9 下载与安装【个人总结】
- dell r720服务器安装esxi
- 高德地图三月更新数千条重要道路 数据能力持续领先
- 会计与计算机发展现状及发展趋势,会计电算化的现状及其发展趋势毕业论文.doc...
- 半透明: MFC实现父窗口不透明,子窗口半透明效果