我看的是JEFF PROSISE的MFC WINDOWS程序设计,看到第三章时,根据其提供的TICTAG程序,改了一下,做了个简单的五子棋,源码如下,希望能跟学MFC的新手一起进步。
FIVE.H
//头文件
#define EX 1
#define OH 2
class CMyApp:public CWinApp
{public:
virtual BOOL InitInstance();
}
;
class CMainWindow:public CWnd
{
protected:
static const CRect m_rcSquares[25];
int m_nGameGrid[25];
int m_nNextChar;
int GetRectID(CPoint point);
void DrawBoard(CDC *pDC);
void DrawX(CDC *pDC,int nPos);
void DrawO(CDC *pDC,int nPos);
void ResetGame();
void CheckForGameOver();
int IsWinner();
BOOL IsDraw();
public:
CMainWindow();
protected:
virtual void PostNcDestroy();
afx_msg void OnPaint();
afx_msg void OnLButtonDown(UINT nFlags,CPoint point);
afx_msg void OnLButtonDblClk(UINT nFlags,CPoint point);
afx_msg void OnRButtonDown(UINT nFlags,CPoint point);
DECLARE_MESSAGE_MAP()
};
FIVE.CPP
// 以下为主程序
#include<afxwin.h>
#include"five.h"
CMyApp myApp;
BOOL CMyApp::InitInstance()
{
m_pMainWnd=new CMainWindow;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
BEGIN_MESSAGE_MAP(CMainWindow,CWnd)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
END_MESSAGE_MAP()
const CRect CMainWindow::m_rcSquares[25]=
{
CRect(16,16,32,32),
CRect(32,16,48,32),
CRect(48,16,64,32),
CRect(64,16,80,32),
CRect(80,16,96,32),
CRect(16,32,32,48),
CRect(32,32,48,48),
CRect(48,32,64,48),
CRect(64,32,80,48),
CRect(80,32,96,48),
CRect(16,48,32,64),
CRect(32,48,48,64),
CRect(48,48,64,64),
CRect(64,48,80,64),
CRect(80,48,96,64),
CRect(16,64,32,80),
CRect(32,64,48,80),
CRect(48,64,64,80),
CRect(64,64,80,80),
CRect(80,64,96,80),
CRect(16,80,32,96),
CRect(32,80,48,96),
CRect(48,80,64,96),
CRect(64,80,80,96),
CRect(80,80,96,96)
};
CMainWindow::CMainWindow()
{
m_nNextChar=EX;
::ZeroMemory(m_nGameGrid,25*sizeof(int));
CString strWndClass=AfxRegisterWndClass(
CS_DBLCLKS,
AfxGetApp()->LoadStandardCursor(IDC_ARROW),
(HBRUSH)(COLOR_3DFACE+1),
AfxGetApp()->LoadStandardIcon(IDI_WINLOGO)
);
CreateEx(0,strWndClass,_T("五子棋"),
WS_OVERLAPPED|WS_SYSMENU|WS_CAPTION|WS_MINIMIZEBOX,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL);
CRect rect(0,0,96,96);
CalcWindowRect(&rect);
SetWindowPos(NULL,0,0,rect.Width(),rect.Height(),
SWP_NOZORDER|SWP_NOMOVE|SWP_NOREDRAW);
};
void CMainWindow::PostNcDestroy()
{delete this;
}
void CMainWindow::OnPaint()
{CPaintDC dc(this);
DrawBoard(&dc);
}
void CMainWindow::OnLButtonDown(UINT nFlags,CPoint point)
{if(m_nNextChar!=EX)
return;
int nPos=GetRectID(point);
if((nPos==-1)||(m_nGameGrid[nPos]!=0))
return;
m_nGameGrid[nPos]=EX;
m_nNextChar=OH;
CClientDC dc(this);
DrawX(&dc,nPos);
CheckForGameOver();
}
void CMainWindow::OnRButtonDown(UINT nFlags,CPoint point)
{
if(m_nNextChar!=OH)
return;
int nPos=GetRectID(point);
if((nPos==-1)||(m_nGameGrid[nPos]!=0))
return;
m_nGameGrid[nPos]=OH;
m_nNextChar=EX;
CClientDC dc(this);
DrawO(&dc,nPos);
CheckForGameOver();
}
void CMainWindow::OnLButtonDblClk(UINT nFlags,CPoint point)
{
CClientDC dc(this);
if (dc.GetPixel(point)==RGB(0,0,0))
ResetGame();
}
int CMainWindow::GetRectID(CPoint point)
{
for(int i=0;i<25;i++)
{
if(m_rcSquares[i].PtInRect(point))
return i;
}
return -1;
}
void CMainWindow::DrawBoard(CDC *pDC)
{
CPen pen(PS_SOLID,5,RGB(0,0,0));
CPen *pOldPen=pDC->SelectObject(&pen);
pDC->MoveTo(16,32);
pDC->LineTo(96,32);
pDC->MoveTo(16,48);
pDC->LineTo(96,48);
pDC->MoveTo(16,64);
pDC->LineTo(96,64);
pDC->MoveTo(16,80);
pDC->LineTo(96,80);
pDC->MoveTo(32,16);
pDC->LineTo(32,96);
pDC->MoveTo(48,16);
pDC->LineTo(48,96);
pDC->MoveTo(64,16);
pDC->LineTo(64,96);
pDC->MoveTo(80,16);
pDC->LineTo(80,96);
for(int i=0;i<25;i++)
{
if(m_nGameGrid[i]==EX)
DrawX(pDC,i);
else if(m_nGameGrid[i]==OH)
DrawO(pDC,i);
}
pDC->SelectObject(pOldPen);
}
void CMainWindow::DrawX(CDC *pDC,int nPos)
{
CPen pen(PS_SOLID,4,RGB(255,0,0));
CPen *pOldPen=pDC->SelectObject(&pen);
CRect rect=m_rcSquares[nPos];
rect.DeflateRect(16,16);
pDC->MoveTo(rect.left,rect.top);
pDC->LineTo(rect.right,rect.bottom);
pDC->MoveTo(rect.left,rect.bottom);
pDC->LineTo(rect.right,rect.top);
pDC->SelectObject(pOldPen);
}
void CMainWindow::DrawO(CDC *pDC, int nPos)
{
CPen pen(PS_SOLID,2,RGB(12,33,255));
CPen *pOldPen=pDC->SelectObject(&pen);
CRect rect=m_rcSquares[nPos];
rect.DeflateRect(16,16);
pDC->MoveTo(rect.left,rect.top);
pDC->LineTo(rect.right,rect.bottom);
pDC->MoveTo(rect.left,rect.bottom);
pDC->LineTo(rect.right,rect.top);
pDC->SelectObject(pOldPen);
}
void CMainWindow::CheckForGameOver()
{
int nWinner;
if(nWinner=IsWinner())
{
CString string=(nWinner==EX)?_T("X Wins!"):_T("O Wins!");
MessageBox(string,_T("Game Over"),MB_ICONEXCLAMATION|MB_OK);
ResetGame();
}
else if(IsDraw())
{
MessageBox(_T("It's a draw!"),_T("Game Over"),MB_ICONEXCLAMATION|MB_OK);
ResetGame();
}
}
int CMainWindow::IsWinner()
{
static int nPattern[12][5]={
0,1,2,3,4,
5,6,7,8,9,
10,11,12,13,14,
15,16,17,18,19,
20,21,22,23,24,
0,5,10,15,20,
1,6,11,16,21,
2,7,12,17,22,
3,8,13,18,23,
4,9,14,19,24,
4,8,12,16,20,
0,6,12,18,24
};
for(int i=0;i<12;i++)
{
if((m_nGameGrid[nPattern[i][0]]==EX)&&
(m_nGameGrid[nPattern[i][1]]==EX)&&
(m_nGameGrid[nPattern[i][2]]==EX)&&
(m_nGameGrid[nPattern[i][3]]==EX)&&
(m_nGameGrid[nPattern[i][4]]==EX))
return EX;
if((m_nGameGrid[nPattern[i][0]]==OH)&&
(m_nGameGrid[nPattern[i][1]]==OH)&&
(m_nGameGrid[nPattern[i][2]]==OH)&&
(m_nGameGrid[nPattern[i][3]]==OH)&&
(m_nGameGrid[nPattern[i][4]]==OH))
return OH;
}
return 0;
}
BOOL CMainWindow::IsDraw()
{
for(int i=0;i<9;i++)
{
if(m_nGameGrid[i]==0)
return FALSE;
}
return TRUE;
}
void CMainWindow::ResetGame()
{
m_nNextChar=EX;
::ZeroMemory(m_nGameGrid,25*sizeof(int));
Invalidate();
}
下一节,我将详细解释代码的运行原理!