利用VC制作单机版五子棋游戏

    技术2022-05-20  33

     

    利用VC制作单机版五子棋游戏

    计算机语言类 2009-11-25 22:08:12 阅读134 评论2  字号: 订阅

    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)的函数,来在界面的顶部显示白子,黑子,还有到谁走棋等界面显示。

    定义一个全局变量type1type1=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;

     


    最新回复(0)