最近周末看了下windows SDK编程,用GDI画了个2048练练手。
1. 是方块配置类
#include "framework.h"
//宏定义set.get
#define ATTRIBUTE_MEMBER_FUNC(argType, arg)\
public:\
void set_##arg(const argType& v) {\
arg = v;\
}\
argType get_##arg() {\
return arg;\
}
class DigitalConfig
{
public:
DigitalConfig();
~ DigitalConfig();
ATTRIBUTE_MEMBER_FUNC(int, digital);
ATTRIBUTE_MEMBER_FUNC(int, digitalSize);
ATTRIBUTE_MEMBER_FUNC(int, digitalColor);
ATTRIBUTE_MEMBER_FUNC(HBRUSH, digitalBk);
private:
int digital; //方块数字
int digitalSize; //方块字体大小
int digitalColor; //方块字体颜色
HBRUSH digitalBk; // 方块背景画刷
};
2 数字操作类
#pragma once
#include <iostream>
#include <vector>
#define PIECE_LENGTH 4
#include <functional>
class Checkerboard
{
public:
Checkerboard();
~Checkerboard();
void left(int*);
void right(int*);
void up(int*);
void down(int*);
void hanleNum(bool); //产生随机2或4
bool thanNewAndOld(); //判断数组是否改变
void changeTemp(); //改变temp
bool IsGameOver();
void restart(); //重新开始
void drawArray(std::function<void(int**)> drawCallBabck); //画数组回调
private:
int** pieceArray;
int** tempArray;
std::vector<int> temp; //存在数组为0的下标
};
2.1数组产生2或4
void Checkerboard:: hanleNum(bool init)
{
bool flag = false;
//比较在按完方向键后数组是否发生变化
if (!init) {
if (thanNewAndOld())
{
return;
}
}
//在剩余为0的坐标中产生随机数
int xy = rand() % (temp.size() == 0 ? 16 : temp.size());
int data = rand() % 5; // 2和4出现概率为1:4
if (data != 4) {
data = 2;
}
//init 是用来开始时只能产生2
if (init)
{
this->pieceArray[xy / PIECE_LENGTH][xy % PIECE_LENGTH] = 2;
}
else {
this->pieceArray[temp[xy] / PIECE_LENGTH][temp[xy] % PIECE_LENGTH] = data;
}
for (size_t i = 0; i < PIECE_LENGTH; i++)
{
for (size_t j = 0; j < PIECE_LENGTH; j++)
{
this->tempArray[i][j] = pieceArray[i][j];
}
}
//将数组还为0下标的存入temp可以更好的随机出坐标
changeTemp();
}
//记录为0的坐标
void Checkerboard::changeTemp()
{
temp.clear();
for (size_t i = 0; i < PIECE_LENGTH; i++)
{
for (size_t j = 0; j < PIECE_LENGTH; j++)
{
if (pieceArray[i][j] == 0)
{
//i*4+i用1维记录二维的下标
temp.push_back(i * PIECE_LENGTH + j);
}
}
}
}
2.2 移动算法
void Checkerboard::left(int* fraction)
{
for (int i = 0; i < PIECE_LENGTH; i++)
{
int tempLeft[] = { 0,0,0,0 };
int k = 0;
for (int j = 0; j < PIECE_LENGTH; j++)
{
if (j < PIECE_LENGTH - 1 && pieceArray[i][j] != 0)
{
//
for (int l = j + 1; l < PIECE_LENGTH; l++) {
//不为0不相等
if (pieceArray[i][l] != 0 && pieceArray[i][j] != pieceArray[i][l]) {
break;
}
//不为0相等相等
if (pieceArray[i][l] != 0 && pieceArray[i][j] == pieceArray[i][l]) {
pieceArray[i][j] = pieceArray[i][j] * 2;
*fraction += pieceArray[i][j];
pieceArray[i][l] = 0;
break;
}
}
}
//记录不为0的数,这样为0的数字都到了右边
if (pieceArray[i][j] != 0)
{
tempLeft[k] = pieceArray[i][j];
k++;
}
}
for (int j = 0; j < PIECE_LENGTH; j++)
{
pieceArray[i][j] = tempLeft[j];
}
}
}
3. 绘图
checkerboard->drawArray([=](int** arr) {
int y = 205;
//循环画每个方块
for (size_t i = 0; i < PIECE_LENGTH; i++)
{
int x = 35;
for (size_t j = 0; j < PIECE_LENGTH; j++)
{
HFONT hFont = CreateFont(mapColor[arr[i][j]]->get_digitalSize(), 0, 0, 0, 1000, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, L"等线");
SelectObject(hBitmapDC, hFont);
SelectObject(hBitmapDC, mapColor[arr[i][j]]->get_digitalBk());
SetTextColor(hBitmapDC, mapColor[arr[i][j]]->get_digitalColor());
RECT rect;
rect.left = x;
rect.top = y+(100- mapColor[arr[i][j]]->get_digitalSize())/2;
rect.right = x + 100;
rect.bottom = y + 100;
char text1[10];
//画带圆角的方块
RoundRect(hBitmapDC, x, y, x + 100, y + 100,5,5);
//画数为0画空格
if (arr[i][j] == 0) {
DrawText(hBitmapDC, L" ", 1, &rect, DT_CENTER);
}
else {
snprintf(text1, 9, "%d", arr[i][j]);
wchar_t* text = char2wchar(text1);
DrawText(hBitmapDC, (LPCWSTR)text, wcslen(text), &rect, DT_CENTER);
//delete text;
}
DeleteObject(hFont);
x += 115;
}
y += 115;
}
});
以上时主要实现
游戏界面:
下载地址:(没积分留言)https://download.youkuaiyun.com/download/mengxiangsun/11981736