联机五子棋小程序: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作为编译器

 

先给出最终的效果:

联机五子棋小程序:C++ MFC创建游戏界面_第1张图片

下面为完整的详细源码:

#pragma once
#include 

#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 2

class 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转换为一个Point
	CPoint LocationToPoint(CPoint &location);
	// 将Point转换为一个Location
	CPoint PointToLocation(CPoint &point);

	// 根据一个location获取一个rect
	CRect 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);
};

#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.ym_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);
	else
		dc.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);
		else
			dc.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);
}

#pragma once
#include 

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);
};

#include 
#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);
}

 

 

#pragma once
#include 

int chessscore(int x, int y, int player, int* gridstate,int line);   //棋盘权值函数
CPoint CallAIPlayer(int* gridstate,int line, int nput);

 

#include

#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;
}

 

 

下面是服务器部分的详细源码:

#pragma once
#include 

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);
};

 

 

#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"));
	else
		AfxMessageBox(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);
	}
}


 

#pragma once
#include 

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);
};

 

#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++,软件)