二打一棋用户需要的功能如下:
(1)移动棋子:玩家通过鼠标点击能够实现棋子的移动,同时保证每次只能移动一格,且只能移动到未被占领的格子上。
(2)吃掉棋子:同一条线上的己方两个棋子可以吃掉对方的一个棋子,让对方棋子消失。
(3)棋子闪烁:点击己方棋子,棋子闪烁,同时保证己方回合内点击对方棋子,对方棋子不闪烁。
(4)重新开始:游戏重新开始。
(5)黑棋先行:黑棋优先移动。
(6)红棋先行:红棋优先移动。
(7)退出游戏:退出二打一棋。
根据游戏需求,需要利用MFC环境定义一个对话框类,提供程序的初始界面,其中包括重新开始按钮、黑棋先行按钮、红棋先行按钮、退出游戏按钮钮。同时游戏用户对棋盘的相关操作还要通过TVSODlg类来实现。
项目中主要的类:TVSODlg。
TVSODlg类:实现棋盘画面绘制,对棋子进行操作等相关作用。
继承:系统中的对话框基类CDialogEx。
成员变量和成员函数如下:
void Hoxiaoyuan(inti,int j) :绘制/红色小圆
void Hexiaoyuan(inti,int j) :绘制黑色小圆
void dayuan(int i,int j):绘制大圆
void youxiao(CPoint q) :确定点击的有效位置
void beijing(CDC* pDC) :绘制棋盘背景
void qizhi() :初始棋子放置
void tiaojian(int i,intj) :棋子消失(胜负)条件判断
int pointvalue[7][6] :点初始值为0,红棋标记为1,黑棋标记为2
CPoint q :保存点信息
int p,n,c,d :p=1,黑棋移动,p=2,红棋移动;n=0点未被选定,n=1,点已选定,c,d标记选定的点
int pblack,pred :保存红棋和黑棋个数,初始个数均为6。
int k :判断棋子是否需要初始化 int i,j
CBitmap beijingtu :插入背景图
afx_msg void OnLButtonDown(UINTnFlags, CPoint point) :鼠标左键点击
afx_msg voidOnTimer(UINT_PTR nIDEvent) :计时器函数
afx_msg void OnBnClickedButton1():重新开始
afx_msg voidOnBnClickedButton2() :黑棋先行
afx_msg voidOnBnClickedButton3() :红棋先行
afx_msg voidOnBnClickedButton4() :退出游戏
新建基于对话框的MFC应用程序项目TVSO。
从控件列表中选择按钮控件放于对话框上,修改按钮控件的属性,设计结果如下。
通过调用绘图相关函数画出如下所示棋盘界面:相关函数代码在beijing(pDC)中实现。
⑴用二维数组将图中相关点的信息保存POINT pointt[7][6]
⑵通过调用绘图相关函数画出下图所示棋子界面,并对相关点做标记:相关代码在void CTVSODlg ::qizhi()中
⑴为TVSODlg类添加消息处理函数OnLButtonDown
⑵OnLButtonDown函数中,需调用以下函数:
youxiao(CPoint q):确定点击的有效位置
dayuan(c,d):绘制大圆
Hexiaoyuan(i,j);:绘制黑色小圆
Hoxiaoyuan(i,j):绘制红色小圆
tiaojian(i,j):胜负条件判断
hongheiqi():右上角红黑棋显示
⑶棋子移动的原理:即是绘制新圆覆盖掉原来的圆,同时修改相关标记。
⑴为TVSODlg类添加消息处理函数OnTimer
⑵在绘制棋子函数中添加SetTimer函数。
⑴将.bmp图片文件放置在项目res文件夹下。
⑵在资源视图中导入.bmp格式图片文件。
⑶为其添加相关函数代码,该函数代码在void CTVSODlg::OnPaint()函数中。
如果要显示背景、棋子、背景图等,则需要在void CTVSODlg::OnPaint()函数中调用。
该函数添加在void CTVSODlg::OnPaint()函数的else之中。
CPaintDC dc(this);
CDC DC; //定义并创建一个内存设备环境
DC.CreateCompatibleDC(&dc);//创建兼容性DC
DC.SelectObject(&beijingtu);//调用函数显示图片
dc.StretchBlt(0,0,800,800,&DC,0,0,800,800,SRCCOPY);
CDC *pDC=GetDC();
beijing(pDC);
ReleaseDC(pDC);
qizhi();
for(i=0;i<7;i++)//重新绘制
{
for(j=0;j<6;j++)
{
if(pointvalue[i][j]==1)Hoxiaoyuan(i,j);
elseif(pointvalue[i][j]==2) Hexiaoyuan(i,j);
}
}
voidCTVSODlg::OnLButtonDown(UINT nFlags, CPoint point)
{
i=-1;j=-1;
q=point;
youxiao(q);
if(p==1)//黑棋移动
{
if(pointvalue[i][j]==2)
{ c=i;d=j;n=1;}//n=1时,表示选定该点 获取i,j的值
else if(pointvalue[i][j]==0&&n==1)
{
if(abs(i-c)==1&&j==d||abs(j-d)==1&&i==c)//判断能够移动,则执行
{
pointvalue[c][d]=0;
pointvalue[i][j]=2;
dayuan(c,d);
Hexiaoyuan(i,j); //黑棋时
tiaojian(i,j);
p=2;n=0;c=-1;d=-1; hongheiqi();
}
}
}
else if(p==2)
{
if(pointvalue[i][j]==1){c=i;d=j;n=1;}
else if(pointvalue[i][j]==0&&n==1)
{
if(abs(i-c)==1&&j==d||abs(j-d)==1&&i==c)//判断能够移动,则执行
{
pointvalue[c][d]=0;
pointvalue[i][j]=1;//红棋的值
dayuan(c,d);
Hoxiaoyuan(i,j);
tiaojian(i,j);
p=1;n=0;c=-1;d=-1; hongheiqi();
}
}
}
CDialogEx::OnLButtonDown(nFlags, point);
}
voidCTVSODlg::Hoxiaoyuan(int i,int j) //绘制红色小圆
{
CDC *pDC=GetDC();
CPen redbian(PS_SOLID,3,RGB(255,0,0));
pDC->SelectObject(redbian);
CBrush red(RGB(255,0,0));
pDC->SelectObject(red);
pDC->Ellipse(pointt[i][j].x-10,pointt[i][j].y-10,pointt[i][j].x+10,pointt[i][j].y+10);
ReleaseDC(pDC);
}
voidCTVSODlg::Hexiaoyuan(int i,int j)//绘制黑色小圆
{
CDC *pDC=GetDC();
CPen redbian(PS_SOLID,3,RGB(0,0,0));
pDC->SelectObject(redbian);
CBrush black(RGB(0,0,0));
pDC->SelectObject(black);
pDC->Ellipse(pointt[i][j].x-10,pointt[i][j].y-10,pointt[i][j].x+10,pointt[i][j].y+10);
ReleaseDC(pDC);
}
voidCTVSODlg::dayuan(int i,int j) //绘制大圆
{
CDC *pDC=GetDC();
CPen whitebian(PS_SOLID,1,RGB(255,255,255));
pDC->SelectObject(whitebian);
pDC->Ellipse(pointt[i][j].x-20,pointt[i][j].y-20,pointt[i][j].x+20,pointt[i][j].y+20);
ReleaseDC(pDC);
}
voidCTVSODlg::hongheiqi()//右上角红黑棋显示
{
CDC *pDC=GetDC();
if(p==1)
{
CPen redbian(PS_DASH,3,RGB(0,0,0));
pDC->SelectObject(redbian);
CBrush black(RGB(0,0,0));
pDC->SelectObject(black);
pDC->Ellipse(350-10,30-10,350+10,30+10);
}
else if(p==2)
{
CPen redbian(PS_DASH,3,RGB(255,0,0));
pDC->SelectObject(redbian);
CBrush red(RGB(255,0,0));
pDC->SelectObject(red);
pDC->Ellipse(350-10,30-10,350+10,30+10);
}
ReleaseDC(pDC);
}
voidCTVSODlg::youxiao(CPoint q)
{
for(i=1;i<=5;i++)
{
for(j=1;j<=4;j++)
{
if(q.x>=pointt[i][j].x-20&&q.x<=pointt[i][j].x+20&&q.y>=pointt[i][j].y-20&&q.y<=pointt[i][j].y+20)
{m=1;break;}//设置点有效位置
}
if(m==1){m=0;break;}
}
}
voidCTVSODlg::beijing(CDC* pDC) //背景绘制
{
for(j=100;j<=500;j=j+100)
{pDC->MoveTo(100,j); pDC->LineTo(400,j);}
for(i=100;i<=400;i=i+100)
{pDC->MoveTo(i,100); pDC->LineTo(i,500);}
for(i=1;i<6;i++)
{
for(j=1;j<5;j++)
dayuan(i,j);//绘制背景圆
}
}
void CTVSODlg::qizhi()//初始棋子绘制
{
SetTimer(1,1000,NULL);
if(k==0)
{
for(i=0;i<7;i++) //点初始值为0,红棋标记为1,黑棋标记为2
{for(j=0;j<6;j++) pointvalue[i][j]=0;}
//初始化棋盘(红棋)
for(j=1;j<=4;j++){Hoxiaoyuan(1,j);pointvalue[1][j]=1;}
Hoxiaoyuan(2,1); pointvalue[2][1]=1;
Hoxiaoyuan(2,4); pointvalue[2][4]=1;
//初始化棋盘(黑棋)
for(j=1;j<=4;j++){Hexiaoyuan(5,j);pointvalue[5][j]=2;}
Hexiaoyuan(4,1); pointvalue[4][1]=2;
Hexiaoyuan(4,4); pointvalue[4][4]=2;
k=1;
}
}
voidCTVSODlg::tiaojian(int i,int j)//棋子消失(胜负)条件判断
{
if(pointvalue[i][j]==2) //黑棋时
{
if(pointvalue[i-1][j]==2)//上
{
if(pointvalue[i+1][j]==1&&pointvalue[i+2][j]!=1)
{
pointvalue[i+1][j]=0;
dayuan(i+1,j);
pred--;
}
if(pointvalue[i-2][j]==1&&pointvalue[i-3][j]!=1)
{
pointvalue[i-2][j]=0;
dayuan(i-2,j);
pred--;
}
}
if(pointvalue[i+1][j]==2)//下
{
if(pointvalue[i-1][j]==1&&pointvalue[i-2][j]!=1)
{
pointvalue[i-1][j]=0;
dayuan(i-1,j);
pred--;
}
if(pointvalue[i+2][j]==1&&pointvalue[i+3][j]!=1)
{
pointvalue[i+2][j]=0;
dayuan(i+2,j);
pred--;
}
}
if(pointvalue[i][j-1]==2)//左
{
if(pointvalue[i][j+1]==1&&pointvalue[i][j+2]!=1)
{
pointvalue[i][j+1]=0;
dayuan(i,j+1);
pred--;
}
if(pointvalue[i][j-2]==1&&pointvalue[i][j-3]!=1)
{
pointvalue[i][j-2]=0;
dayuan(i,j-2);
pred--;
}
}
if(pointvalue[i][j+1]==2)//右
{
if(pointvalue[i][j-1]==1&&pointvalue[i][j-2]!=1)
{
pointvalue[i][j-1]=0;
dayuan(i,j-1);
pred--;
}
if(pointvalue[i][j+2]==1&&pointvalue[i][j+3]!=1)
{
pointvalue[i][j+2]=0;
dayuan(i,j+2);
pred--;
}
}
if(pred==0) AfxMessageBox("黑旗获胜");
}
else if(pointvalue[i][j]==1)//红棋时
{
if(pointvalue[i-1][j]==1)//上
{
if(pointvalue[i+1][j]==2&&pointvalue[i+2][j]!=2)
{
pointvalue[i+1][j]=0;
dayuan(i+1,j);
pblack--;
}
if(pointvalue[i-2][j]==2&&pointvalue[i-3][j]!=2)
{
pointvalue[i-2][j]=0;
dayuan(i-2,j);
pblack--;
}
}
if(pointvalue[i+1][j]==1)//下
{
if(pointvalue[i-1][j]==2&&pointvalue[i-2][j]!=2)
{
pointvalue[i-1][j]=0;
dayuan(i-1,j);
pblack--;
}
if(pointvalue[i+2][j]==2&&pointvalue[i+3][j]!=2)
{
pointvalue[i+2][j]=0;
dayuan(i+2,j);
pblack--;
}
}
if(pointvalue[i][j-1]==1)//左
{
if(pointvalue[i][j+1]==2&&pointvalue[i][j+2]!=2)
{
pointvalue[i][j+1]=0;
dayuan(i,j+1);
pblack--;
}
if(pointvalue[i][j-2]==2&&pointvalue[i][j-3]!=2)
{
pointvalue[i][j-2]=0;
dayuan(i,j-2);
pblack--;
}
}
if(pointvalue[i][j+1]==1)//右
{
if(pointvalue[i][j-1]==2&&pointvalue[i][j-2]!=2)
{
pointvalue[i][j-1]=0;
dayuan(i,j-1);
pblack--;
}
if(pointvalue[i][j+2]==2&&pointvalue[i][j+3]!=2)
{
pointvalue[i][j+2]=0;
dayuan(i,j+2);
pblack--;
}
}
if(pblack==0) AfxMessageBox("红旗获胜");
}
}
voidCTVSODlg::OnTimer(UINT_PTR nIDEvent)
{
if(pointvalue[i][j]==2&&p==1)
{
dayuan(i,j);
Hexiaoyuan(i,j);
}
else if(pointvalue[i][j]==1&&p==2)
{
dayuan(i,j);
Hoxiaoyuan(i,j);
}
CDialogEx::OnTimer(nIDEvent);
}
voidCTVSODlg::OnBnClickedButton1()
{
p=1;n=0;
pblack=6;pred=6;
k=0;
OnPaint();
}
voidCTVSODlg::OnBnClickedButton2()
{
OnBnClickedButton1();
}
voidCTVSODlg::OnBnClickedButton3()
{
OnBnClickedButton1();
p=2;
}
voidCTVSODlg::OnBnClickedButton4()
{
CTVSODlg::OnCancel();
}