美文网首页
MFC实现2048小游戏

MFC实现2048小游戏

作者: downdemo | 来源:发表于2018-07-19 10:12 被阅读118次
  • 删除最初的static text框和两个button
  • 手动添加一个MyRect.h到头文件
#include "stdafx.h"

class MyRect
{
public:
    MyRect(UINT x1, UINT y1, UINT x2, UINT y2);
    ~MyRect();
public:
    //矩形框的当前值
    UINT uValue;//矩形顶点坐标
    UINT x1;
    UINT y1;
    UINT x2;
    UINT y2;
};
  • 手动添加一个MyRect.cpp到源文件
#include "stdafx.h"
#include "MyRect.h"

MyRect::MyRect(UINT x1, UINT y1, UINT x2, UINT y2)
{
    this->x1 = x1;
    this->y1 = y1;
    this->x2 = x2;
    this->y2 = y2;
    uValue = 0;
}
MyRect::~MyRect(){}
  • 在Dlg.cpp中添加包含头文件,并添加全局变量和函数
#include "MyRect.h"

#define LINELENGTH 4
#define RECTNUM (LINELENGTH*LINELENGTH)

struct MyPoint{
    int x;
    int y;
};

//实际矩形数组,面板上显示的每个矩形都是CRect类型,声明在这里
CRect *rect[LINELENGTH][LINELENGTH];

//控制是否生成新数字,为true的时候说明有动作,就会生成新数字
bool bHaveDoneSth;

//端点位置
MyPoint point[LINELENGTH][LINELENGTH] = { 0 };

//矩形对象数组,相当于逻辑部分,保存矩形的显示值,坐标
MyRect *myrect[LINELENGTH][LINELENGTH];

//填充画刷,可以控制矩形填充不同的颜色
CBrush *brush;

//生成一个新数字,随机一个0-RECTNUM的整数,根据这个整数计算出二维数组的横坐标和竖坐标
//  A/LINELENGTH 是横坐标, A%LINELENGTH 是竖坐标, 当生成的位置有值的时候,重新生成
// 初始值为2, 可以再这里加控制生成2,或 4 。
void GenerateNewNum()
{
    srand(time(0));
    int A = rand() % RECTNUM;
    while (myrect[A / LINELENGTH][A%LINELENGTH]->uValue != 0)
    {
        A = rand() % RECTNUM;
    }
    myrect[A / LINELENGTH][A%LINELENGTH]->uValue = 2;
}

//判断游戏结束
bool GameOver()
{
    //如果有值为0 的矩形,则游戏肯定可以继续,所以直接返回false
    for (int i = 0; i < LINELENGTH; i++)
        for (int j = 0; j < LINELENGTH; j++)
        {
            if (myrect[i][j]->uValue == 0)
                return false;
        }
    // 对每一行相邻的两个数,如果有相同的,那么游戏可以继续,返回false
    for (int i = 0; i < LINELENGTH; i++)
        for (int j = 0; j < LINELENGTH - 1; j++)
        {
            if (myrect[i][j]->uValue == myrect[i][j + 1]->uValue)
                return false;
        }

    // 对每一列相邻的两个数,如果有相同的,那么游戏可以继续,返回false
    for (int j = 0; j < LINELENGTH; j++)
        for (int i = 0; i < LINELENGTH - 1; i++)
        {
            if (myrect[i][j]->uValue == myrect[i + 1][j]->uValue)
                return false;
        }
    return true;
}
  • 在Dlg::OnInitDialog()中添加初始化代码
    ::SetWindowPos(this->m_hWnd, HWND_BOTTOM, 0, 0, 25 + LINELENGTH * 100, 48 + LINELENGTH * 100, SWP_NOZORDER);
    //初始化每个矩形的左上角点的坐标
    for (int i = 0; i < LINELENGTH; i++)
    {
        for (int j = 0; j < LINELENGTH; j++)
        {
            point[i][j].x = j * 100 + 10;
            point[i][j].y = i * 100 + 10;
        }
    }
    //初始化矩形和填充画刷
    for (int i = 0; i < LINELENGTH; i++)
    {
        for (int j = 0; j < LINELENGTH; j++)
        {
            myrect[i][j] = new MyRect(point[i][j].x, point[i][j].y, point[i][j].x + 90, point[i][j].y + 90);
            myrect[i][j]->uValue = 0;
        }
    }
    //初始化数字
    srand(time(0));
    int A = rand() % RECTNUM;
    int B = rand() % RECTNUM;
    while (B == A)
    {
        B = rand() % RECTNUM;
    }
    myrect[A / LINELENGTH][A % LINELENGTH]->uValue = 2;
    myrect[B / LINELENGTH][B % LINELENGTH]->uValue = 2;
  • 在OnPaint()中添加绘制代码
    CFont font;
    font.CreateFont(25, 25, 0, 0, 700, false, false, false,
        CHINESEBIG5_CHARSET, OUT_CHARACTER_PRECIS,
        CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY,
        FF_MODERN, TEXT("宋体"));

    //客户区设备环境
    CClientDC dc(this);
    //新建画笔
    CPen pen;
    pen.CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
    //选中字体
    dc.SelectObject(pen);
    for (int i = 0; i < LINELENGTH; i++)
    {
        for (int j = 0; j < LINELENGTH; j++)
        {
            //画矩形
            //dc.RoundRect(myrect[i][j]->getRect(), 4, 4);
            dc.Rectangle(myrect[i][j]->x1, myrect[i][j]->y1, myrect[i][j]->x2, myrect[i][j]->y2);
            //填充矩形
            rect[i][j] = new CRect(myrect[i][j]->x1, myrect[i][j]->y1, myrect[i][j]->x2, myrect[i][j]->y2);

            //设置文字背景透明
            dc.SetBkMode(TRANSPARENT);
            //选中字体
            dc.SelectObject(font);
            //写数字
            if (myrect[i][j]->uValue == 0)
            {
                brush = new CBrush(RGB(0xFC, 0xFC, 0xFC));
                dc.FillRect(rect[i][j], brush);
                delete brush;
            }
            else if (myrect[i][j]->uValue != 0)
            {
                switch (myrect[i][j]->uValue)
                {
                case 2:brush = new CBrush(RGB(0xFF, 0xFF, 0xFF)); break;
                case 4:brush = new CBrush(RGB(0xFF, 0xE4, 0xC4)); break;
                case 8:brush = new CBrush(RGB(0xFF, 0xB6, 0xC1)); break;
                case 16:brush = new CBrush(RGB(0xFF, 0x83, 0xFA)); break;
                case 32:brush = new CBrush(RGB(0xFF, 0xC1, 0x25)); break;
                case 64:brush = new CBrush(RGB(0xFF, 0x6A, 0x6A)); break;
                case 128:brush = new CBrush(RGB(0xFF, 0x14, 0x93)); break;
                case 256:brush = new CBrush(RGB(0xCD, 0x66, 0x1D)); break;
                case 512:brush = new CBrush(RGB(0x94, 0x00, 0xD3)); break;
                case 1024:brush = new CBrush(RGB(0xFF, 0xFF, 0x00)); break;
                case 2048:brush = new CBrush(RGB(0xFF, 0x00, 0x00)); break;
                default:brush = new CBrush(RGB(0xFF, 0x00, 0x00)); break;
                }
                dc.FillRect(rect[i][j], brush);
                delete brush;
                CString str;
                str.Format(_T("%d"), myrect[i][j]->uValue);
                dc.DrawText(str, rect[i][j], DT_VCENTER | DT_CENTER | DT_SINGLELINE);
            }
        }
    }
  • 为了让对话框直接捕获消息,重载PreTranslateMessage,重载前要在Dlg.h中给Dlg类添加声明virtual BOOL PreTranslateMessage(MSG* pMsg);
BOOL CMy3Dlg::PreTranslateMessage(MSG* pMsg)
{
    // TODO: Add your specialized code here and/or call the base class
    if (pMsg->message == WM_KEYUP)
    {
        switch (pMsg->wParam)
        {
        case VK_LEFT:
            //判断是否有动作,用来控制是否生成新数字
            bHaveDoneSth = false;
            for (int i = 0; i < LINELENGTH; i++)
            {

                //去掉空格
                for (int j = 0; j < LINELENGTH; j++)
                {
                    //
                    if (myrect[i][j]->uValue != 0)
                    {
                        for (int k = 0; k < j; k++)
                        {
                            if (myrect[i][k]->uValue == 0)
                            {
                                bHaveDoneSth = true;
                                myrect[i][k]->uValue = myrect[i][j]->uValue;
                                myrect[i][j]->uValue = 0;
                                break;
                            }
                        }
                    }
                }

                //相加
                for (int j = 0; j < LINELENGTH - 1; j++)
                {
                    if (myrect[i][j]->uValue != 0)
                    {
                        if (myrect[i][j + 1]->uValue == myrect[i][j]->uValue)
                        {
                            bHaveDoneSth = true;
                            myrect[i][j]->uValue += myrect[i][j + 1]->uValue;
                            myrect[i][j + 1]->uValue = 0;
                        }
                    }
                }

                //去掉空格
                for (int j = 0; j < LINELENGTH; j++)
                {
                    if (myrect[i][j]->uValue != 0)
                    {
                        for (int k = 0; k < j; k++)
                        {
                            if (myrect[i][k]->uValue == 0)
                            {
                                bHaveDoneSth = true;
                                myrect[i][k]->uValue = myrect[i][j]->uValue;
                                myrect[i][j]->uValue = 0;
                                break;
                            }
                        }
                    }
                }
            }
            break;
        case VK_UP:
            bHaveDoneSth = false;
            for (int j = 0; j < LINELENGTH; j++)
            {
                //去掉空格
                for (int i = 0; i < LINELENGTH; i++)
                {
                    //
                    if (myrect[i][j]->uValue != 0)
                    {
                        for (int k = 0; k < i; k++)
                        {
                            if (myrect[k][j]->uValue == 0)
                            {
                                bHaveDoneSth = true;
                                myrect[k][j]->uValue = myrect[i][j]->uValue;
                                myrect[i][j]->uValue = 0;
                                break;
                            }
                        }
                    }
                }

                //相加
                for (int i = 0; i < LINELENGTH - 1; i++)
                {
                    if (myrect[i][j]->uValue != 0)
                    {
                        if (myrect[i + 1][j]->uValue == myrect[i][j]->uValue)
                        {
                            bHaveDoneSth = true;
                            myrect[i][j]->uValue += myrect[i + 1][j]->uValue;
                            myrect[i + 1][j]->uValue = 0;
                        }
                    }
                }

                //去掉空格
                for (int i = 0; i < LINELENGTH; i++)
                {
                    //
                    if (myrect[i][j]->uValue != 0)
                    {
                        for (int k = 0; k < i; k++)
                        {
                            if (myrect[k][j]->uValue == 0)
                            {
                                bHaveDoneSth = true;
                                myrect[k][j]->uValue = myrect[i][j]->uValue;
                                myrect[i][j]->uValue = 0;
                                break;
                            }
                        }
                    }
                }
            }

            break;
        case VK_RIGHT:
            bHaveDoneSth = false;
            for (int i = 0; i < LINELENGTH; i++)
            {
                //去掉空格
                for (int j = LINELENGTH - 1; j >= 0; j--)
                {
                    //
                    if (myrect[i][j]->uValue != 0)
                    {
                        for (int k = LINELENGTH - 1; k >= j; k--)
                        {
                            if (myrect[i][k]->uValue == 0)
                            {
                                bHaveDoneSth = true;
                                myrect[i][k]->uValue = myrect[i][j]->uValue;
                                myrect[i][j]->uValue = 0;
                                break;
                            }
                        }
                    }
                }

                //相加
                for (int j = LINELENGTH - 1; j > 0; j--)
                {
                    if (myrect[i][j]->uValue != 0)
                    {
                        if (myrect[i][j - 1]->uValue == myrect[i][j]->uValue)
                        {
                            bHaveDoneSth = true;
                            myrect[i][j]->uValue += myrect[i][j - 1]->uValue;
                            myrect[i][j - 1]->uValue = 0;
                        }
                    }
                }

                //去掉空格
                for (int j = LINELENGTH - 1; j >= 0; j--)
                {
                    //
                    if (myrect[i][j]->uValue != 0)
                    {
                        for (int k = LINELENGTH - 1; k >= j; k--)
                        {
                            if (myrect[i][k]->uValue == 0)
                            {
                                bHaveDoneSth = true;
                                myrect[i][k]->uValue = myrect[i][j]->uValue;
                                myrect[i][j]->uValue = 0;
                                break;
                            }
                        }
                    }
                }
            }

            break;
        case VK_DOWN:
            bHaveDoneSth = false;
            for (int j = LINELENGTH - 1; j >= 0; j--)
            {

                //去掉空格
                for (int i = LINELENGTH - 1; i >= 0; i--)
                {
                    //
                    if (myrect[i][j]->uValue != 0)
                    {
                        for (int k = LINELENGTH - 1; k >= i; k--)
                        {
                            if (myrect[k][j]->uValue == 0)
                            {
                                bHaveDoneSth = true;
                                myrect[k][j]->uValue = myrect[i][j]->uValue;
                                myrect[i][j]->uValue = 0;
                                break;
                            }
                        }
                    }
                }

                //相加
                for (int i = LINELENGTH - 1; i > 0; i--)
                {
                    if (myrect[i][j]->uValue != 0)
                    {
                        if (myrect[i - 1][j]->uValue == myrect[i][j]->uValue)
                        {
                            bHaveDoneSth = true;
                            myrect[i][j]->uValue += myrect[i - 1][j]->uValue;
                            myrect[i - 1][j]->uValue = 0;
                        }
                    }
                }

                //去掉空格
                for (int i = LINELENGTH - 1; i >= 0; i--)
                {
                    //
                    if (myrect[i][j]->uValue != 0)
                    {
                        for (int k = LINELENGTH - 1; k >= i; k--)
                        {
                            if (myrect[k][j]->uValue == 0)
                            {
                                bHaveDoneSth = true;
                                myrect[k][j]->uValue = myrect[i][j]->uValue;
                                myrect[i][j]->uValue = 0;
                                break;
                            }
                        }
                    }
                }
            }

            break;
        default:
            break;
        }

        if (bHaveDoneSth)
        {
            GenerateNewNum();
        }

        Invalidate(FALSE);
        if (GameOver())
        {
            MessageBox(_T("游戏结束!"));
        };
    }
    return CDialog::PreTranslateMessage(pMsg);
}

MFC对话框无法响应键盘按键

  • 给类添加一个WM_KEYUP的消息,运行时不会响应键盘,原因是控件需要首先对按键作出响应,比如多行编辑框会先处理回车防止回车关闭对话框。要直接让对话框响应按键,方法是重载PreTranslateMessage改变消息控制流程
  • 让对话框直接捕获消息
BOOL CMy3Dlg::PreTranslateMessage(MSG* pMsg)
{
    if (pMsg->message == WM_KEYUP)
    {
        switch (pMsg->wParam)
        {
            case VK_LEFT: ...; break;
            case VK_UP: ...; break;
            case VK_RIGHT: ...; break;
            case VK_DOWN: ...; break;
            default: break;
        }
    }
    return CDialog::PreTranslateMessage(pMsg);
}
  • 或者实现当按下方向键时调用OnKeyUp
BOOL CSampleControl::PreTranslateMessage(LPMSG lpmsg)
{
    BOOL bHandleNow = FALSE;
    switch (lpmsg->message)
    {
        case WM_KEYUP:
        switch (lpmsg->wParam)
        {
            case VK_UP:
            case VK_DOWN:
            case VK_LEFT:
            case VK_RIGHT:
            bHandleNow = TRUE;
            break;
        }
        if (bHandleNow)
        OnKeyUp(lpmsg->wParam, LOWORD(lpmsg ->lParam), HIWORD(lpmsg->lParam));
        break;
    }
    return bHandleNow;
}

相关文章

  • MFC实现2048小游戏

    删除最初的static text框和两个button 手动添加一个MyRect.h到头文件 手动添加一个MyRec...

  • 用C语言实现2048游戏

    2048_C_code 用C语言编写的2048 1 要实现我们的 2048 小游戏,需要涉及一些数据结构的知识,以...

  • python—手把手教你实现2048小游戏

    相信2048这个游戏对大家来说一定不陌生,下面这篇文章就主要给大家介绍了怎么用Python实现2048小游戏,文中...

  • 2048小游戏javascript实现

    原生js实现2048小游戏 GitHub地址 ,希望大家多多捧场觉得还可以就给个star吧~ 详情 利用了css3...

  • python实现小游戏2048

  • 2048小游戏

    2048小游戏 author:滚滚 构思来源:模仿现有的2048小游戏,并希望通过这次大作业学习pygame与py...

  • 使用鸿蒙开发一款TV版的小游戏

    2048大家应该都玩过,今天我们就来实现一个可以在鸿蒙系统上运行的2048小游戏,因为没有智慧屏,所以这里是在鸿蒙...

  • 用js实现2048小游戏

    笔记仓库:https://github.com/nnngu/LearningNotes 本文永久更新地址 http...

  • 用Python实现小游戏2048

    转自:Python中文网社区论坛 直接上代码吧!

  • 2048小游戏

    前言:最近在学习Python的过程中,在github上看见别人实现的一个小游戏2048,感觉很有趣,这里记录下实现...

网友评论

      本文标题:MFC实现2048小游戏

      本文链接:https://www.haomeiwen.com/subject/gebzpftx.html