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

📄 cchess.cpp

📁 这是一个中国象棋的简单范例。 程序虽然简单
💻 CPP
字号:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
//  嗨!我是王晓钰。
//  我的E-mail是:XiaoYu.wang@263.net  有问题可以发邮件或在网站上留言
//  欢迎你访问我的个人主页:“笑语小园”http://xiaoyu.2699.comn
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
//  二○○○年七月
//  让我们继续看我的程序。
//这是课本上的例子。
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
//可供两人对弈的中国象棋程序
#include <afxwin.h>
// 棋盘类
class CPlate
{
	int m_ndx;		// 棋盘格宽
	int m_ndy;		// 棋盘格高
	int m_nLeft;		// 棋盘位置
	int m_nTop;
	int m_nRight;
	int m_nBottom;
public:
			CPlate();
	void		ShowPlate(CDC *pDC);
	void		DrawConer(CDC *pDC, int row, int col, int type);
	CPoint	GetPosition(int col, int row);
};
// 棋盘类的成员函数
// 构造函数: 初始化
CPlate::CPlate()
{
	m_ndx		= 50;
	m_ndy		= 45;
	m_nLeft		= 198;
	m_nTop		= 30;
	m_nRight		= m_nLeft+m_ndx*8;
	m_nBottom	= m_nTop+m_ndy*9;
}
// 显示棋盘
void CPlate::ShowPlate(CDC *pDC)
{
	// 画棋盘方格
	CPen penRed2(PS_SOLID,2,RGB(255,0,0));
	CPen *pOldPen = pDC->SelectObject(&penRed2);
	for(int i=0; i<10; i++)
	{
		pDC->MoveTo(m_nLeft, m_nTop+i*m_ndy);
		pDC->LineTo(m_nRight, m_nTop+i*m_ndy);
	}
	for(i=0; i<9; i++)
	{
		if(i==0 || i==8)
		{
			pDC->MoveTo(m_nLeft+i*m_ndx, m_nTop);
			pDC->LineTo(m_nLeft+i*m_ndx, m_nBottom);
		}
		else{
			pDC->MoveTo(m_nLeft+i*m_ndx, m_nTop);
			pDC->LineTo(m_nLeft+i*m_ndx, m_nTop+4*m_ndy);
			pDC->MoveTo(m_nLeft+i*m_ndx, m_nTop+5*m_ndy);
			pDC->LineTo(m_nLeft+i*m_ndx, m_nBottom);
		}
	}
	// 画棋盘斜线
	pDC->SelectObject(pOldPen);
	CPen penRed1(PS_SOLID,1,RGB(255,0,0));
	pOldPen = pDC->SelectObject(&penRed1);
	pDC->MoveTo(m_nLeft+3*m_ndx, m_nTop);
	pDC->LineTo(m_nLeft+5*m_ndx, m_nTop+2*m_ndy);
	pDC->MoveTo(m_nLeft+3*m_ndx, m_nTop+2*m_ndy);
	pDC->LineTo(m_nLeft+5*m_ndx, m_nTop);
	pDC->MoveTo(m_nLeft+3*m_ndx, m_nBottom);
	pDC->LineTo(m_nLeft+5*m_ndx, m_nBottom-2*m_ndy);
	pDC->MoveTo(m_nLeft+3*m_ndx, m_nBottom-2*m_ndy);
	pDC->LineTo(m_nLeft+5*m_ndx, m_nBottom);
	pDC->SelectObject(pOldPen);
	// 画兵, 炮位标记
	DrawConer(pDC, 2, 1, 0);
	DrawConer(pDC, 2, 7, 0);
	DrawConer(pDC, 3, 0, 1);
	DrawConer(pDC, 3, 2, 0);
	DrawConer(pDC, 3, 4, 0);
	DrawConer(pDC, 3, 6, 0);
	DrawConer(pDC, 3, 8, 2);
	DrawConer(pDC, 7, 1, 0);
	DrawConer(pDC, 7, 7, 0);
	DrawConer(pDC, 6, 0, 1);
	DrawConer(pDC, 6, 2, 0);
	DrawConer(pDC, 6, 4, 0);
	DrawConer(pDC, 6, 6, 0);
	DrawConer(pDC, 6, 8, 2);
}
// 绘制兵, 炮位标志
void CPlate::DrawConer(CDC *pDC, int row, int col, int type)
{
	CPen penRed1(PS_SOLID,1,RGB(255,0,0));
	CPen *pOldPen = pDC->SelectObject(&penRed1);
	if(type == 0 || type == 1)
	{
		pDC->MoveTo(m_nLeft+col*m_ndx+ 3, m_nTop+row*m_ndy-10);
		pDC->LineTo(m_nLeft+col*m_ndx+ 3, m_nTop+row*m_ndy-3);
		pDC->LineTo(m_nLeft+col*m_ndx+10, m_nTop+row*m_ndy-3);
		pDC->MoveTo(m_nLeft+col*m_ndx+ 3, m_nTop+row*m_ndy+10);
		pDC->LineTo(m_nLeft+col*m_ndx+ 3, m_nTop+row*m_ndy+3);
		pDC->LineTo(m_nLeft+col*m_ndx+10, m_nTop+row*m_ndy+3);
	}
	if(type == 0 || type == 2)
	{
		pDC->MoveTo(m_nLeft+col*m_ndx- 3, m_nTop+row*m_ndy-10);
		pDC->LineTo(m_nLeft+col*m_ndx- 3, m_nTop+row*m_ndy-3);
		pDC->LineTo(m_nLeft+col*m_ndx-10, m_nTop+row*m_ndy-3);
		pDC->MoveTo(m_nLeft+col*m_ndx- 3, m_nTop+row*m_ndy+10);
		pDC->LineTo(m_nLeft+col*m_ndx- 3, m_nTop+row*m_ndy+3);
		pDC->LineTo(m_nLeft+col*m_ndx-10, m_nTop+row*m_ndy+3);
	}
	pDC->SelectObject(pOldPen);
}
// 取棋盘上各交叉点的坐标
CPoint CPlate::GetPosition(int col, int row)
{
	CPoint point;
	point.x = m_nLeft+col*m_ndx;
	point.y = m_nTop+row*m_ndy;
	return point;
}
// 棋子类
// 定义棋子名称
#define		BING		1
#define		PAO		2
#define		JU		3
#define		MA		4
#define		XIANG		5
#define		SHI		6
#define		JIANG		7
class CStone	
{
	BOOL		m_bRed;			// 是否红方
	BOOL		m_bSelected;	// 是否被选择
	int			m_nCol;			// 路
	int			m_nRow;			// 行
	CRect		m_rectStone;	// 棋子包含矩形
	BOOL		m_bShow;		// 是否显示
	CString		m_sName;		// 棋子名称
	int			m_nR;			// 棋子半径
	int			m_nType;		// 棋子类型
public:
	CStone	(){}
	CStone	(BOOL red, int col, int row, LPCSTR name, int type, CPlate &plate);
	void		ShowStone(CDC *pDC);
	void		MoveTo(int col, int row, CPlate &plate);
	CRect	GetRect(){return m_rectStone;}
	int		GetType(){return m_nType;}
	BOOL		BeKilled(int col, int row)
{return m_bShow && m_nCol==col && m_nRow == row;}
	BOOL	MouseOnStone(CPoint point)
{return m_rectStone.PtInRect(point) && m_bShow;}
	void	KillIt(){m_bShow = FALSE;}
	void	SelectStone(){m_bSelected = !m_bSelected;}
};
// 棋子类的成员函数
// 棋子类的构造函数:初始化棋子
CStone::CStone(BOOL red, int col, int row, LPCSTR name, int type, CPlate &plate)
{
	m_bShow		= TRUE;
	m_bSelected = FALSE;
	m_bRed		= red;
	m_nCol		= col;
	m_nRow		= row;
	m_sName		= name;
	m_nType		= type;
	m_nR		= 23;
	CPoint pos = plate.GetPosition(col, row);
	m_rectStone = CRect(pos.x-m_nR, pos.y-m_nR, pos.x+m_nR, pos.y+m_nR);
}
// 显示棋子
void CStone::ShowStone(CDC *pDC)
{
	if(m_bShow)	// 只有未被吃掉的棋子才显示
	{
		// 准备画棋子的画笔和画刷
		CPen *pOldPen, penNormal(PS_SOLID, 3, RGB(120, 120, 120));
		CBrush *pOldBrush, brushNormal, brushSelected;
		brushNormal.CreateSolidBrush(RGB(255, 255, 0));
		brushSelected.CreateSolidBrush(RGB(127, 127, 0));
		pOldPen = pDC->SelectObject(&penNormal);
		// 被选中的棋子颜色不同
		if(m_bSelected)
			pOldBrush = pDC->SelectObject(&brushSelected);
		else
			pOldBrush = pDC->SelectObject(&brushNormal);
		// 显示棋子
		CRect r(m_rectStone);
		r.left	++;
		r.top	++;
		r.right	--;
		r.bottom--;
		pDC->Ellipse(r);
		pDC->SelectObject(pOldPen);
		pDC->SelectObject(pOldBrush);
		// 准备显示棋子名称的字体
		CFont *pOldFont, fontStone;
		fontStone.CreateFont(40, 0, 0, 0, 400, FALSE, FALSE,
							 0, OEM_CHARSET, OUT_DEFAULT_PRECIS,
							 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
							 DEFAULT_PITCH, "楷体");
		pOldFont = pDC->SelectObject(&fontStone);
		int tx = m_rectStone.left+6;
		int ty = m_rectStone.top+6;
		pDC->SetBkMode(TRANSPARENT);
		// 棋子背景均为黄色,字分红、黑两色
		pDC->SetTextColor(RGB(m_bRed?255:0, 0, 0));
		pDC->TextOut(tx, ty, m_sName);
		pDC->SelectObject(pOldFont);
	}
}
// 将棋子放到指定位置
void CStone::MoveTo(int col, int row, CPlate &plate)
{
	m_bSelected = FALSE;
	m_nCol		= col;
	m_nRow		= row;
	CPoint pos	= plate.GetPosition(col, row);
	m_rectStone = CRect(pos.x-m_nR, pos.y-m_nR, pos.x+m_nR, pos.y+m_nR);
}
// 框架窗口类
class CMyWnd: public CFrameWnd
{
	CPlate	m_Plate;				// 棋盘
	CStone	m_StoneList[32];		// 棋子数组
	BOOL		m_bRedTurn;			// 轮红方下
	BOOL		m_bSelectOne;		// 已选择一棋子
	int		m_nWhichStone;		// 被选择棋子的编号
	CRect	m_rectInfo;			// 信息显示位置
public:
	CMyWnd(){InitGame();}
	void InitGame();
	void ShowInfo(CDC *pDC);
	BOOL KillSelfStone(int col, int row, BOOL red);
	int  KillEnemy(int col, int row, BOOL red);
	void MoveStone(CPoint point);
	void SelectStone(CPoint point);
	void Go(CPoint);
	BOOL MoveTo(int, int);
protected:
	afx_msg void OnPaint();
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	DECLARE_MESSAGE_MAP()
};
// 消息映射
BEGIN_MESSAGE_MAP(CMyWnd,CFrameWnd)
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
// 框架窗口类的成员函数
// 初始化棋局
void CMyWnd::InitGame()
{
	m_bRedTurn		= TRUE;
	m_bSelectOne		= FALSE;
	m_rectInfo		= CRect(315, 480, 515, 550);
	m_StoneList[ 0] = CStone(TRUE, 0, 0, "车", 3, m_Plate);
	m_StoneList[ 1] = CStone(TRUE, 1, 0, "马", 4, m_Plate);
	m_StoneList[ 2] = CStone(TRUE, 2, 0, "象", 5, m_Plate);
	m_StoneList[ 3] = CStone(TRUE, 3, 0, "士", 6, m_Plate);
	m_StoneList[ 4] = CStone(TRUE, 4, 0, "将", 7, m_Plate);
	m_StoneList[ 5] = CStone(TRUE, 5, 0, "士", 6, m_Plate);
	m_StoneList[ 6] = CStone(TRUE, 6, 0, "象", 5, m_Plate);
	m_StoneList[ 7] = CStone(TRUE, 7, 0, "马", 4, m_Plate);
	m_StoneList[ 8] = CStone(TRUE, 8, 0, "车", 3, m_Plate);
	m_StoneList[ 9] = CStone(TRUE, 1, 2, "炮", 2, m_Plate);
	m_StoneList[10] = CStone(TRUE, 7, 2, "炮", 2, m_Plate);
	m_StoneList[11] = CStone(TRUE, 0, 3, "兵", 1, m_Plate);
	m_StoneList[12] = CStone(TRUE, 2, 3, "兵", 1, m_Plate);
	m_StoneList[13] = CStone(TRUE, 4, 3, "兵", 1, m_Plate);
	m_StoneList[14] = CStone(TRUE, 6, 3, "兵", 1, m_Plate);
	m_StoneList[15] = CStone(TRUE, 8, 3, "兵", 1, m_Plate);
	m_StoneList[16] = CStone(FALSE, 0, 9, "车", 3, m_Plate);
	m_StoneList[17] = CStone(FALSE, 1, 9, "马", 4, m_Plate);
	m_StoneList[18] = CStone(FALSE, 2, 9, "相", 5, m_Plate);
	m_StoneList[19] = CStone(FALSE, 3, 9, "仕", 6, m_Plate);
	m_StoneList[20] = CStone(FALSE, 4, 9, "帅", 7, m_Plate);
	m_StoneList[21] = CStone(FALSE, 5, 9, "仕", 6, m_Plate);
	m_StoneList[22] = CStone(FALSE, 6, 9, "相", 5, m_Plate);
	m_StoneList[23] = CStone(FALSE, 7, 9, "马", 4, m_Plate);
	m_StoneList[24] = CStone(FALSE, 8, 9, "车", 3, m_Plate);
	m_StoneList[25] = CStone(FALSE, 1, 7, "炮", 2, m_Plate);
	m_StoneList[26] = CStone(FALSE, 7, 7, "炮", 2, m_Plate);
	m_StoneList[27] = CStone(FALSE, 0, 6, "卒", 1, m_Plate);
	m_StoneList[28] = CStone(FALSE, 2, 6, "卒", 1, m_Plate);
	m_StoneList[29] = CStone(FALSE, 4, 6, "卒", 1, m_Plate);
	m_StoneList[30] = CStone(FALSE, 6, 6, "卒", 1, m_Plate);
	m_StoneList[31] = CStone(FALSE, 8, 6, "卒", 1, m_Plate);
}
// 处理 WM_ONPAINT 消息, 绘制窗口客户区 (绘制棋盘, 棋子等)
void CMyWnd::OnPaint()
{
	CPaintDC dc(this);
	m_Plate.ShowPlate(&dc);					// 显示棋盘
	for(int i=0; i<32; i++)					// 显示所有棋子
		m_StoneList[i].ShowStone(&dc);		
	ShowInfo(&dc);							// 显示轮谁行棋
}
// 处理 WM_ONLBUTTONDOWN 消息, 移动棋子
void CMyWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
	if(m_bSelectOne) // 已选择了要移动的棋子
		MoveStone(point);
	else				// 尚未选择要移动的棋子
		SelectStone(point);
}
// 移动棋子
void CMyWnd::MoveStone(CPoint point)
{
	// 如果选择原来的棋子, 作废原来的选择
	if(m_StoneList[m_nWhichStone].MouseOnStone(point))
	{
		m_StoneList[m_nWhichStone].SelectStone();
		m_bSelectOne = FALSE;
		InvalidateRect(m_StoneList[m_nWhichStone].GetRect(), FALSE);
	}
	else // 在棋盘其他位置行棋
		Go(point);
}
// 走棋或吃棋
void CMyWnd::Go(CPoint point)
{
	for(int col=0; col<9; col++)	// 检查鼠标是否指向某个棋盘交叉点
		for(int row=0; row<10; row++)
		{
			CPoint p = m_Plate.GetPosition(col, row);
			CRect  r(p.x-23, p.y-23, p.x+23, p.y+23);
			if(r.PtInRect(point)) // 鼠标指向该交叉点
			{
				if(KillSelfStone(col, row, m_bRedTurn))
					MessageBox("您竟然想吃自己人?!");
				else
					m_bRedTurn = MoveTo(col, row);
			}
		}
}
// 移到指定位置或吃子
BOOL CMyWnd::MoveTo(int col, int row)
{
	// 更新窗口客户区原来的棋子位置
	InvalidateRect(m_StoneList[m_nWhichStone].GetRect());
	// 棋子移向新位置
	m_StoneList[m_nWhichStone].MoveTo(col, row, m_Plate);
	// 更新窗口客户区新的棋子位置
	InvalidateRect(m_StoneList[m_nWhichStone].GetRect());
	// 还原选择棋子标志
	m_bSelectOne = FALSE;
	// 检查是否吃了对方的棋子
	int i = KillEnemy(col, row, m_bRedTurn);
	if(i>=0)	// 确实吃了对方棋子
	{
		m_StoneList[i].KillIt();
		if(m_StoneList[i].GetType() == JIANG)
		{
			if(m_bRedTurn)
				MessageBox(m_bRedTurn?"红方胜!":"黑方胜!");
			InitGame();
			Invalidate();
			return TRUE;
		}
	}
	// 更新窗口客户区提示信息位置
	InvalidateRect(m_rectInfo);
	return !m_bRedTurn;
}
// 选择棋子
void CMyWnd::SelectStone(CPoint point)
{
	int nwhich = m_bRedTurn?0:16;
	// 逐个查看己方棋子是否被选中
	for(int i=nwhich; i<nwhich+16; i++)
		if(m_StoneList[i].MouseOnStone(point))
		{
			m_StoneList[i].SelectStone();
			// 更新窗口客户区被选中棋子的位置(该棋子要变色)
			InvalidateRect(m_StoneList[i].GetRect(), FALSE);
			m_nWhichStone	= i;
			m_bSelectOne	= TRUE;
			break;
		}
}
// 显示轮谁行棋
void CMyWnd::ShowInfo(CDC *pDC)
{
	CFont *pOldFont, fontInfo;
	fontInfo.CreateFont(50, 0, 0, 0, 400, FALSE, FALSE,
					 0, OEM_CHARSET, OUT_DEFAULT_PRECIS,
					 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
					 DEFAULT_PITCH, "楷体");
	pOldFont = pDC->SelectObject(&fontInfo);
	pDC->SetTextColor(RGB(m_bRedTurn?255:0, 0, 0));
	pDC->TextOut(m_rectInfo.left, m_rectInfo.top,
				 m_bRedTurn?"红方行棋": "黑方行棋");
	pDC->SelectObject(pOldFont);
}
// 检查是否误杀己方棋子
BOOL CMyWnd::KillSelfStone(int col, int row, BOOL red)
{
	int from = red?0:16;
	// 逐个检查己方棋子是否被误杀
	for(int i=from; i<from+16; i++)
		if( m_StoneList[i].BeKilled(col, row))
			return TRUE;
	return FALSE;
}
// 检查是否吃对方棋子
int CMyWnd::KillEnemy(int col, int row, BOOL red)
{
	int from = red?16:0;
	// 逐个检查对方棋子是否被吃
	for(int i=from; i<from+16; i++)
		if( m_StoneList[i].BeKilled(col, row))
			return i;
	return -1;
}
// 应用程序类
class CMyApp: public CWinApp
{
public:
	BOOL	InitInstance();
};
// 应用程序类的实例初始化函数
BOOL CMyApp::InitInstance()
{
	CMyWnd *pFrame = new CMyWnd;
	pFrame->Create(0,_T("中国象棋程序"));
	pFrame->ShowWindow(SW_SHOWMAXIMIZED);
	pFrame->UpdateWindow(); 
	this->m_pMainWnd = pFrame;
	return TRUE;
}
// 应用程序类的全局对象
CMyApp ThisApp;

⌨️ 快捷键说明

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