1, 制作用户登录框
比如有两个用户,张三和李四
定义两个全局变量
CString nameblack;//保存黑子玩家的名字
CString namewhite;//保存白子玩家的名字
GetDlgItemText(IDC_EDIT1,nameblack);
GetDlgItemText(IDC_EDIT2,namewhite);
为了让这个登录框先运行
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
在return -1后面加一个
Clogin login; //Clogin为对话框的类名
login.DoModal();
这时,就会先运行这个对话框的东西
2, 在CMainFrame::PreCreateWindow(CREATESTRUCT& cs)函数中设置单文档的高度和宽度,还有起点
cs.x=100;
cs.y=0;
cs.cx=850;//界面的宽度
cs.cy=700;//界面的高度
cs.hMenu=0;
3, 设置界面的标题
在Doc类中设置
BOOL CGobangDoc::OnNewDocument()
加一句
SetTitle("张靖");
4, 导入背景图片
在bitmap资源里导入资源图片。
给背景图片取好ID
譬如说ID号是IDB_Chessboard
然后在view类中定义成员变量
CBitmap m_chessboard;
CDC Chessboard;
然后在view类中的OnDraw函数中
m_chessboard.LoadBitmap(IDB_Chessboard);
Chessboard.CreateCompatibleDC(pDC);
Chessboard.SelectObject(m_chessboard);
pDC->BitBlt(0,0,850,600,&Chessboard,0,0,SRCCOPY);(8个参数)
这样就把背景图片画出来了
5,用同样的方法把开始按钮,退出按钮,悔棋按钮,重新开始按钮,黑子,白子。并用
pDC->BitBlt()这个函数把这些bitmap图片放到适当的位置
贴图的时候注意,把先贴最大的图片,然后再贴最小的图片,不然顺序乱的话,就会大图把小图给盖住,从而影响到游戏的效果。
还有一点要注意,在贴完图后一定别忘了ReleaseDC(pDC);很重要,不然会内存泄露。
6, 在界面上显示鼠标的纵横坐标。
在view类里添加鼠标移动的消息响应
void CGobangView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CView::OnMouseMove(nFlags, point);
int x=point.x;
int y=point.y;
CString st;
st.Format(("%d ,%d "),x,y);
CDC *pDC=GetDC();
pDC->TextOut(200,0,st);
ReleaseDC(pDC);
SetCursor(LoadCursor(NULL,IDC_CROSS));//加载一个十字形状的鼠标光标。
CView::OnMouseMove(nFlags,point);
}
7, 添加一个PrintState(CDC *pDC)的函数,来在界面的顶部显示白子,黑子,还有到谁走棋等界面显示。
定义一个全局变量type1,type1=1时,黑子走棋,type1=0时,白子走棋,当type1=2时,游戏还没有开始。三种状态,三种不同的写法,但是都是大同小异。
void CGobangView::PrintState(CDC *pDC)//把这个函数要写在PrintAll()这个重绘函数里面。
{
CString st;
if(type1==1)
{
st=" ";
pDC->TextOut(280,10,st);
//这个函数的功能是在距左边框280,距上边框10的地方放上st里面的内容。
st=nameblack+"黑子走棋";
//UpdateData(true);
//PrintPart(8,-1,0,pDC);
UpdateData(false);
}
else if (type1==0)
{
st=" ";
pDC->TextOut(280,10,st);
st=namewhite+"白子走棋";
//UpdateData(true);
//PrintPart(8,-1,1,pDC);
UpdateData(false);
}
else
if(type1==2)
{
st.Format("游戏还没有开始");
}
pDC->TextOut(280,10,st);
pDC->TextOut(130,25,"黑子:");
pDC->TextOut(440,25,"白子");
pDC->TextOut(190,25,nameblack);
pDC->TextOut(480,25,namewhite);
st.ReleaseBuffer();//当调用st.GetBuffer()是才会用到ReleaseBuffer()这个方法
}
8, 添加void CGobangView::PrintAll(CDC *pDC)函数
void CGobangView::PrintAll(CDC *pDC)
{
int x;
int y;
pDC->BitBlt(0,0,800,600,&Chessboard,0,0,SRCCOPY);//画背景
pDC->BitBlt(590,145,119,64,&Begin,0,0,SRCCOPY);//画开始按钮
pDC->BitBlt(590,275,115,63,&End,0,0,SRCCOPY);//贴结束按钮
pDC->BitBlt(530,400,300,100,&Score,0,0,SRCCOPY);//贴悔棋按钮
pDC->BitBlt(80,530,300,100,&restart,0,0,SRCCOPY);//贴重新开始按钮
PrintState(pDC);
for ( x=0;x<15;x++)//绘制整个棋盘的棋子
for ( y=0;y<15;y++)
{
if (chess[x][y]==1)
redraw(x,y,0,pDC);//负责画白子
else if (chess[x][y]==2)
redraw(x,y,1,pDC);//负责画黑子
}
}
9, 添加redraw(x,y,1,pDC);//根据传进去的坐标和棋子类型判断画白子还是画黑子
void CGobangView::redraw(int x,int y,int type,CDC *pDC)】
{
if(type==0)
{
pDC->BitBlt(73+30*x-14,86+30*y-14,27,28,&Mask,0,0,MERGEPAINT);
pDC->BitBlt(73+30*x-14,86+30*y-14,27,28,&Blackchess,0,0,SRCAND);
}
else if (type==1)
{
pDC->BitBlt(73+30*x-14,86+30*y-14,27,28,&Mask,0,0,MERGEPAINT);
pDC->BitBlt(73+30*x-14,86+30*y-14,27,28,&Whitechess,0,0,SRCAND);
}
10, 添加一个鼠标点击下去时贴棋子的函数
void CGobangView::PrintPart(int x, int y, int type, CDC *pDC)
{
if (chess[x][y]==0)
{
if(type==0)
{
{
pDC->BitBlt(73+30*x-14,86+30*y-14,27,28,&Mask,0,0,MERGEPAINT);//画棋子的背景
pDC->BitBlt(73+30*x-14,86+30*y-14,27,28,&Blackchess,0,0,SRCAND);//画真正的棋子
}
chess[x][y]=1;
type1=1;
}
else if (type==1)
{
{
pDC->BitBlt(73+30*x-14,86+30*y-14,27,28,&Mask,0,0,MERGEPAINT);
pDC->BitBlt(73+30*x-14,86+30*y-14,27,28,&Whitechess,0,0,SRCAND);
}
chess[x][y]=2;
type1=0;
}
}
//AfxBeginThread(&thread1,0);
// AfxBeginThread(&thread,0);
PlaySound(MAKEINTRESOURCE(IDR_luozishengyi),AfxGetResourceHandle(), SND_ASYNC |SND_RESOURCE);
}
11, 添加鼠标左键单击的消息响应函数(这一步是关键)
void CGobangView::OnLButtonDown(UINT nFlags, CPoint point)
{
CDC *pDC=GetDC();
int x=point.x;
int y=point.y;
if (x>=582&&x<=720&&y>=140&&y<=212)
{
MessageBox("游戏准备开始");
PlaySound(MAKEINTRESOURCE(IDR_bgsound),AfxGetResourceHandle(), SND_ASYNC |SND_RESOURCE|SND_LOOP);
paste=1;
}
if(x>=584&&x<=709&&y>=268&&y<=346)
{
if(MessageBox("你确实要退出游戏吗!","标题", MB_OKCANCEL )==IDOK)
exit(0);
}
if (x>=92&&x<=248&&y>=537&&y<=583)
{
if(MessageBox("你确要重新开始吗!","标题", MB_OKCANCEL )==IDOK)
{
for(int i=0;i<15;i++)
for(int j=0;j<15;j++)
{
chess[i][j]=0;
}
paste=1;
win_state=0;
PrintAll(pDC);
}
}
if (x>=530&&x<788&&y>=400&&y<=500&&win_state==0)
{
MessageBox("悔棋");
{
chess[temp_mx][temp_my]=0;
paste=1;
if(type1==0)
{
type1=1;
UpdateData(false);
}
else
if(type1==1)
{
type1=0;
UpdateData(false);
}
UpdateData(false);
}
PrintAll(pDC);
}
//下面是具体的贴棋子以及判断胜负的算法
if(paste==1)
{
int mx=(point.x-61)/30;
int my=(point.y-68)/30;
temp_mx=mx;
temp_my=my;
if(mx>=0&&mx<15&&my>=0&&my<15)
{
PrintState(pDC);
if(type1==0)//白棋子的判断
{
PrintPart(mx,my,0,pDC);
//。。。。是判断输赢的算法
从当前的位置开始判断判断八个方向
如果有一个方向满足了五个,则游戏结束
如果胜利,则
{
nameblack="黑方获胜";
pDC->TextOut(190,25,nameblack);
win_state=1;//游戏结束了
PlaySound(MAKEINTRESOURCE(IDR_BLACK_WIN),AfxGetResourceHandle(), SND_ASYNC |SND_RESOURCE);//奏响胜利的凯歌
MessageBox("黑方获胜");
paste=0;//不能贴子了
UpdateData(false);
}
}
如果是黑子,道理和白子相同
}
12, 要注意的知识点
在使用BitBlt时,有两个属性
一个MERGEPAINT//先反色,后OR
另一个是SRCAND//进行and操作
任何颜色同白色进行OR运算结果都是白色,进行AND运算结果都是该颜色本身.
任何颜色同黑色进行OR运算结果都是该颜色本身,进行AND运算,结果都是黑色
13, 小知识点
都是在App类中的InitInstance函数中添加的
让窗口居中
AfxGetMainWnd()->CenterWindow();//直接让窗口居中
让窗口最大化
m_nCmdShow = SW_SHOWMAXIMIZED;
让窗口最小话
m_nCmdShow = SW_SHOWMINIMIZED;