利用C++,通过MFC搭建游戏界面,制作了一个可以在局域网内联机对战的五子棋小程序,在小程序中添加了电脑玩家角色,用以辅助对战(也可以将电脑玩家角色独立出来做成单机版)
放上网盘分享:
https://pan.baidu.com/s/1oTlQm3YqI7wihmXNK-qkBA
3ise
下面对程序作简要说明
(1)由于是联机游戏,双人对战,所以网络部分采用了客户端/服务器的模式。采用的Socket基类为MFC中封装的 CAsyncSocket。
(2)程序分为客户端和服务器。其中客户端部分包含三个部分:
a)chess MFC界面和游戏响应部分
b)nettask 网络交互部分
c)AIStratege 电脑玩家算法部分
其中服务器部分仅包含界面和网络交互部分
(3)MVS2017作为编译器
先给出最终的效果:
下面为完整的详细源码:
#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;
}