⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ffview.cpp

📁 利用Visual c++编程思想方法实现五子棋游戏的程序设计整个过程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ffView.cpp : implementation of the CFfView class
//

#include "stdafx.h"
#include "ff.h"
#include "LinkDialog.h"
#include "ffDoc.h"
#include "ffView.h"

#pragma comment(lib, "winmm.lib")

#define ID_TIMER 1

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CFfView

IMPLEMENT_DYNCREATE(CFfView, CView)

BEGIN_MESSAGE_MAP(CFfView, CView)
	//{{AFX_MSG_MAP(CFfView)
	ON_WM_PAINT()
	ON_WM_SETCURSOR()
	ON_WM_TIMER()
	ON_COMMAND(ID_ACTION_DISLINK, OnActionDislink)
	ON_COMMAND(ID_ACTION_LINK, OnActionLink)
	ON_COMMAND(ID_ACTION_NEW, OnActionNew)
	ON_COMMAND(ID_ACTION_SURRENDER, OnActionSurrender)
	ON_COMMAND(ID_MUSIC_MUSIC, OnMusicMusic)
	ON_UPDATE_COMMAND_UI(ID_MUSIC_MUSIC, OnUpdateMusicMusic)
	ON_UPDATE_COMMAND_UI(ID_ACTION_DISLINK, OnUpdateActionDislink)
	ON_UPDATE_COMMAND_UI(ID_ACTION_LINK, OnUpdateActionLink)
	ON_UPDATE_COMMAND_UI(ID_ACTION_NEW, OnUpdateActionNew)
	ON_UPDATE_COMMAND_UI(ID_ACTION_SURRENDER, OnUpdateActionSurrender)
	ON_WM_LBUTTONDOWN()
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
	ON_MESSAGE(WM_USER_NEWGAME, OnNewGame)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFfView construction/destruction

CFfView::CFfView()
{
	// TODO: add construction code here
	m_bMusicOn = FALSE;
	m_pListenSocket = NULL;
	m_pClientSocket = NULL;
	m_pClientSocket2 = NULL;
	m_bMyTurn = FALSE;
	m_bLinked = FALSE;
	m_bOpponentWin = FALSE;
	m_bInGame = FALSE;
	m_bFlag = FALSE;
	ResetCoords();
	CreateListenSocket();
}

CFfView::~CFfView()
{
	DestroyListenSocket();
	DestroyClientSocket();
	DestroyClientSocket2();
	m_bLinked = FALSE;

	if(m_bMusicOn)
		KillTimer(ID_TIMER);
}

BOOL CFfView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CFfView drawing

void CFfView::OnDraw(CDC* pDC)
{
	CFfDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
}

/////////////////////////////////////////////////////////////////////////////
// CFfView printing

BOOL CFfView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CFfView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CFfView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CFfView diagnostics

#ifdef _DEBUG
void CFfView::AssertValid() const
{
	CView::AssertValid();
}

void CFfView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CFfDoc* CFfView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFfDoc)));
	return (CFfDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CFfView message handlers

void CFfView::ResetCoords()
{
	for(int i = 0; i < DIVISIONS; i++)
	{
		for(int j = 0; j < DIVISIONS; j++)
			m_nCoords[i][j] = 0;
	}
	if (m_bFlag)
	{
		Invalidate(FALSE);
		UpdateWindow();
	}
}

void CFfView::RequestAccepted(int accept)
{//处理连接请求
	if(!m_pClientSocket)
	{//在socket连接没有创建时,创建新的连接
		m_pClientSocket = new CClientSocket(this);

		if(!m_pListenSocket->Accept(*m_pClientSocket))
		{//释放资源
			DestroyClientSocket();
			GetParent()->SetWindowText(_T("Ygj - Ready"));
			AfxMessageBox(_T("You cannot accept this request!"));
		}

		if(accept == IDYES)
		{//接收连接请求,开始创建连接
			int buf[3] = {ACCEPT, 0, 0};
			if(m_pClientSocket->Send(buf, 3 * sizeof(int)) == SOCKET_ERROR)
			{//发送接受连接请求,
				AfxMessageBox(_T("Connection interrupted!\n"
								"Cannot open the new game."));
				m_bLinked = FALSE;
				m_bInGame = FALSE;
				DestroyClientSocket();
				GetParent()->SetWindowText(_T("Ygj - Ready"));
				return;
			}
			m_bMyTurn = TRUE;
			m_bLinked = TRUE;
			m_bOpponentWin = FALSE;
			m_bInGame = TRUE;
			m_bFlag = TRUE;
			ResetCoords();
			m_nColor = 1;
			GetParent()->SetWindowText(_T("Ygj - Your turn"));
		}
		else
		{
			int buf[3] = {DECLINE, 0, 0};//拒绝对方连接请求
			m_pClientSocket->Send(buf, 3 * sizeof(int));
			GetParent()->SetWindowText(_T("Ygj - Ready"));//等待下次连接
			DestroyClientSocket();
		}
		return;
	}

	//创建备用连接,当程序已经创建好连接,开始游戏时,会创建备用连接,用于响应
	//其他连接请求
	if(m_pClientSocket2)
		DestroyClientSocket2();

	m_pClientSocket2 = new CClientSocket(this);

	if(!m_pListenSocket->Accept(*m_pClientSocket2))
	{
		DestroyClientSocket2();
		GetParent()->SetWindowText(_T("Ygj - Ready"));
		AfxMessageBox(_T("You cannot accept this request!"));
	}

	int buf[3] = {DECLINE, 0, 0};
	m_pClientSocket2->Send(buf, 3 * sizeof(int));
	GetParent()->SetWindowText(_T("Ygj - Ready"));
	DestroyClientSocket2();
}

LRESULT CFfView::OnNewGame(WPARAM wParam, LPARAM lParam)
{
	int result = AfxMessageBox(_T("Do you want to play a new game?"),
								MB_YESNO);
	if(result == IDYES)
	{
		int buf[3] = {ACCEPT, 0, 0};
		if(m_pClientSocket->Send(buf, 3 * sizeof(int)) == SOCKET_ERROR)
		{
			AfxMessageBox(_T("Connection interrupted!\n"
						"Cannot open the new game."));
			m_bLinked = FALSE;
			m_bInGame = FALSE;
			DestroyClientSocket();
			GetParent()->SetWindowText(_T("Ygj - Ready"));
			return 1;
		}
		m_bMyTurn = TRUE;
		m_bLinked = TRUE;
		m_bOpponentWin = FALSE;
		m_bInGame = TRUE;
		m_bFlag = TRUE;
		ResetCoords();
		m_nColor = 1;
		GetParent()->SetWindowText(_T("Ygj - Your turn"));
	}
	else
	{
		int buf[3] = {NONEWGAME, 0, 0};
		if(m_pClientSocket->Send(buf, 3 * sizeof(int)) == SOCKET_ERROR)
		{
			AfxMessageBox(_T("Connection interrupted!\n"
						"Cannot open the new game."));
			m_bLinked = FALSE;
			m_bInGame = FALSE;
			DestroyClientSocket();
			GetParent()->SetWindowText(_T("Ygj - Ready"));
			return 1; 
		}
		GetParent()->SetWindowText(_T("Ygj - Game over"));
	}
	return 0;
}

void CFfView::DrawPieces()
{//绘制棋盘棋子
	CClientDC dc(this);//载入黑白棋子背景画到位图图象,棋子为矩形

	CBitmap bmWhite, bmBlack, bmMask;
	bmWhite.LoadBitmap(IDB_WHITEPIECE);
	bmBlack.LoadBitmap(IDB_BLACKPIECE);
	bmMask.LoadBitmap(IDB_MASK);

	CDC dcMemWhite;
	dcMemWhite.CreateCompatibleDC(&dc);
	CBitmap* pOld1 = dcMemWhite.SelectObject(&bmWhite);//白棋子绘制对象

	CDC dcMemBlack;
	dcMemBlack.CreateCompatibleDC(&dc);
	CBitmap* pOld2 = dcMemBlack.SelectObject(&bmBlack);//黑棋子绘制对象

	CDC dcMemMask;
	dcMemMask.CreateCompatibleDC(&dc);
	CBitmap* pOld3 = dcMemMask.SelectObject(&bmMask);//用黑色覆盖棋子边缘部分,使其成为圆形

	dcMemWhite.BitBlt(0, 0, 36, 36, &dcMemMask, 0, 0, SRCAND);
	dcMemBlack.BitBlt(0, 0, 36, 36, &dcMemMask, 0, 0, SRCAND);
        //拷贝覆盖部分带黑白棋子部分,并进行与运算,得到圆形棋子
	for(int i = 0; i < DIVISIONS; i++)
		for(int j = 0; j < DIVISIONS; j++)
		{
			if(m_nCoords[i][j] == -1)
			{//m_nCoords用来保存游戏中各个棋子的状态,1为黑,-1为白,0为无棋子
				dc.BitBlt((i + 1) * CELLSIZE - 18,
						  (j + 1) * CELLSIZE - 18,
						  36, 36, &dcMemMask,
						  0, 0, 0x220326);

				dc.BitBlt((i + 1) * CELLSIZE - 18,
						  (j + 1) * CELLSIZE - 18,
						  36, 36, &dcMemWhite,
						  0, 0, SRCPAINT);
			}
			
			if(m_nCoords[i][j] == 1)
			{
				dc.BitBlt((i + 1) * CELLSIZE - 18,
						  (j + 1) * CELLSIZE - 18,
						  36, 36, &dcMemMask,
						  0, 0, 0x220326);

				dc.BitBlt((i + 1) * CELLSIZE - 18,
						  (j + 1) * CELLSIZE - 18,
						  36, 36, &dcMemBlack,
						  0, 0, SRCPAINT);
			}

			if(i == m_ptLastStep.x && 
			   j == m_ptLastStep.y &&
			   m_nCoords[i][j] != 0)
			{
				CPen pen(PS_SOLID, 1, RGB(192, 0, 0));
				CPen* pOldPen = dc.SelectObject(&pen);
				dc.SelectStockObject(NULL_BRUSH);

				dc.Rectangle((i + 1) * CELLSIZE - 18,
							 (j + 1) * CELLSIZE - 18,
							 (i + 1) * CELLSIZE + 18,
							 (j + 1) * CELLSIZE + 18);
				dc.SelectObject(pOldPen);
			}
		}

	dcMemWhite.SelectObject(pOld1);
	dcMemBlack.SelectObject(pOld2);
	dcMemMask.SelectObject(pOld3);
}

void CFfView::CreateClientSocket(CString &strAddress)
{
	if(m_pClientSocket)
		DestroyClientSocket();

	m_pClientSocket = new CClientSocket(this);
		
	if(!m_pClientSocket->Create())
	{
		DestroyClientSocket();
		GetParent()->SetWindowText(_T("Ygj - Ready"));
		AfxMessageBox(_T("Port creation failed!\n"
						"Please try again later."));
		return;
	}

	while(!m_pClientSocket->Connect(strAddress, PORT_NUM))
	{
		if(AfxMessageBox(_T("Cannot reach your partner right now.\n"),
			MB_RETRYCANCEL) == IDCANCEL)
		{
			DestroyClientSocket();
			GetParent()->SetWindowText(_T("Ygj - Ready"));
			return;
		}
	}
}

void CFfView::CreateListenSocket()
{
	if(m_pListenSocket)
		DestroyListenSocket();

	m_pListenSocket = new CListenSocket(this);

	if(!m_pListenSocket->Create(PORT_NUM))
	{
		DestroyListenSocket();
		AfxMessageBox(_T("Port creation failed!\n"
						"Please try again later."));
		return;
	}

	if(!m_pListenSocket->Listen())
	{
		DestroyClientSocket();
		AfxMessageBox(_T("Due to socket problems on your machine,\n"
						"you cannot respond to incoming request.\n"
						"You can only request a new game to others."));
	}
}

void CFfView::DestroyClientSocket()
{
	if(m_pClientSocket)
	{
		delete m_pClientSocket;
		m_pClientSocket = NULL;
	}
}

void CFfView::DestroyClientSocket2()
{
	if(m_pClientSocket2)
	{
		delete m_pClientSocket2;
		m_pClientSocket2 = NULL;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -