- 删除最初的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;
};
#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;
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);
}
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;
}
网友评论