2048小游戏
小小的更新了一波~
- 🍳增加了积分功能,会在结束时显示~
- 🚩修改了结束文本的颜色
你问我为什么更新到8192?还不是我朋友打到2048找我贴脸嘲讽😵💫
下面是基于EasyX的代码~
#include <iostream>
#include <algorithm>
#include <string>
#include <graphics.h>
#include <windows.h>
#include <random>
#include <conio.h>
#include <easyx.h>
#include <Windows.h>
#define GRID_CNT 4
#define GRID_WIDTH 100
#define INTERVAL 15
long long score = 0;
// 设置元素颜色
enum Color {
c0 = RGB(205,193,180),
c2 = RGB(238, 228, 218),
c4 = RGB(237, 224, 200),
c8 = RGB(242, 177, 121),
c16 = RGB(245, 149, 99),
c32 = RGB(246, 124, 95),
c64 = RGB(246, 94, 59),
c128 = RGB(233, 206, 119),
c256 = RGB(237, 204, 97),
c512 = RGB(255, 0, 128),
c1024 = RGB(145, 0, 72),
c2048 = RGB(242, 17, 158),
c4096 = BLUE,
c8192 = GREEN,
back = RGB(187, 173, 160)
};
Color color[8193];
int mp[GRID_CNT][GRID_CNT];
// 先来一个全局的生成器
std::random_device rd;
std::mt19937 gen(rd());
// 以 5% 概率生成 4,以 95% 概率生成 2
int randNum() {
std::uniform_int_distribution<> rand(1, 100);
if (rand(gen) <= 5) {
return 4;
} else {
return 2;
}
}
// 随机获取一个空位置
void getLocation() {
std::uniform_int_distribution<> rand(0, GRID_CNT - 1);
while (1) {
int x = rand(gen), y = rand(gen);
if (mp[x][y] == 0) {
mp[x][y] = randNum();
break;
}
}
}
// 移动规则
bool upCheck() {
bool res = false;
for (int i = 0; i < GRID_CNT; i++) {
for (int j = 0; j < GRID_CNT; j++) {
if (j == 0) {
if (mp[j][i] == 0 && mp[j - 1][i] != 0) {
res = true;
}
} else {
if (mp[j][i] != 0) {
if (mp[j - 1][i] == 0) {
res = true;
} else {
if (mp[j - 1][i] == mp[j][i]) {
res = true;
}
}
}
}
}
}
return res;
}
bool downCheck() {
bool res = false;
for (int i = 0; i < GRID_CNT; i++) {
for (int j = GRID_CNT - 1; j >= 0; j--) {
if (j == GRID_CNT - 1) {
if (mp[j][i] == 0 && mp[j - 1][i] != 0) {
res = true;
}
} else {
if (mp[j][i] != 0) {
if (mp[j + 1][i] == 0) {
res = true;
} else {
if (mp[j + 1][i] == mp[j][i]) {
res = true;
}
}
}
}
}
}
return res;
}
bool leftCheck() {
bool res = false;
for (int i = 0; i < GRID_CNT; i++) {
for (int j = 0; j < GRID_CNT; j++) {
if (j == 0) {
if (mp[i][j] == 0 && mp[i][j + 1] != 0) {
res = true;
}
} else {
if (mp[i][j] != 0) {
if (mp[i][j - 1] == 0) {
res = true;
} else {
if (mp[i][j - 1] == mp[i][j]) {
res = true;
}
}
}
}
}
}
return res;
}
bool rightCheck() {
bool res = false;
for (int i = 0; i < GRID_CNT; i++) {
for (int j = GRID_CNT - 1; j >= 0; j--) {
if (j == GRID_CNT - 1) {
if (mp[i][j] == 0 && mp[i][j - 1] != 0) {
res = true;
}
} else {
if (mp[i][j] != 0) {
if (mp[i][j + 1] == 0) {
res = true;
} else {
if (mp[i][j + 1] == mp[i][j]) {
res = true;
}
}
}
}
}
}
return res;
}
// 移动函数
int vis[GRID_CNT]; // 这个数组用来标记格子是否是合成过的,以免重复合成和少合成
void moveUp() {
if (upCheck()) {
for (int i = 0; i < GRID_CNT; i++) {
for (int j = 1; j < GRID_CNT; j++) {
for (int k = 0; k < j; k++) {
if (mp[k][i] == 0) {
mp[k][i] = mp[j][i];
mp[j][i] = 0;
break;
} else {
if ((mp[k][i] == mp[j][i] && mp[k + 1][i] == 0) || (mp[k][i] == mp[j][i] && j - k == 1)) {
if (!vis[k]) {
mp[k][i] += mp[j][i];
score += mp[k][i]; // 新增积分模块
mp[j][i] = 0;
vis[k] = 1;
break;
}
}
}
}
}
std::fill(vis, vis + GRID_CNT, 0);
}
getLocation();
}
}
void moveDown() {
if (downCheck()) {
for (int i = 0; i < GRID_CNT; i++) {
for (int j = GRID_CNT - 2; j >= 0; j--) {
for (int k = GRID_CNT - 1; k > j; k--) {
if (mp[k][i] == 0) {
mp[k][i] = mp[j][i];
mp[j][i] = 0;
break;
} else {
if ((mp[k][i] == mp[j][i] && mp[k - 1][i] == 0) || (mp[k][i] == mp[j][i] && k - j == 1)) {
if (!vis[k]) {
mp[k][i] += mp[j][i];
score += mp[k][i];
mp[j][i] = 0;
vis[k] = 1;
break;
}
}
}
}
}
std::fill(vis, vis + GRID_CNT, 0);
}
getLocation();
}
}
void moveLeft() {
if (leftCheck()) {
for (int i = 0; i < GRID_CNT; i++) {
for (int j = 1; j < GRID_CNT; j++) {
for (int k = 0; k < j; k++) {
if (mp[i][k] == 0) {
mp[i][k] = mp[i][j];
mp[i][j] = 0;
break;
} else {
if ((mp[i][k] == mp[i][j] && mp[i][k + 1] == 0) || (mp[i][k] == mp[i][j] && j - k == 1)) {
if (!vis[k]) {
mp[i][k] += mp[i][j];
score += mp[i][k];
mp[i][j] = 0;
vis[k] = 1;
break;
}
}
}
}
}
std::fill(vis, vis + GRID_CNT, 0);
}
getLocation();
}
}
void moveRight() {
if (rightCheck()) {
for (int i = 0; i < GRID_CNT; i++) {
for (int j = GRID_CNT - 2; j >= 0; j--) {
for (int k = GRID_CNT - 1; k > j; k--) {
if (mp[i][k] == 0) {
mp[i][k] = mp[i][j];
mp[i][j] = 0;
break;
} else {
if ((mp[i][k] == mp[i][j] && mp[i][k - 1] == 0) || (mp[i][k] == mp[i][j] && k - j == 1)) {
if (!vis[k]) {
mp[i][k] += mp[i][j];
score += mp[i][k];
mp[i][j] = 0;
vis[k] = 1;
break;
}
}
}
}
}
std::fill(vis, vis + GRID_CNT, 0);
}
getLocation();
}
}
// 控制函数
void Control() {
char key = _getch();
if (key == 'w' || key == 'W' || key == 72) moveUp();
else if (key == 'a' || key == 'A' || key == 75) moveLeft();
else if (key == 'd' || key == 'D' || key == 77) moveRight();
else if (key == 's' || key == 'S' || key == 80) moveDown();
}
// 是否获胜
bool is_win() {
for (int i = 0; i < GRID_CNT; i++) {
for (int j = 0; j < GRID_CNT; j++) {
if (mp[i][j] == 8192) {
return true;
}
}
}
return false;
}
// 是否失败
bool is_lose() {
for (int i = 0; i < GRID_CNT; i++) {
for (int j = 0; j < GRID_CNT; j++) {
if (mp[i][j] == 0) {
return false;
}
}
}
for (int i = 0; i < GRID_CNT; i++) {
for (int j = 0; j < GRID_CNT; j++) {
if (i < GRID_CNT - 1 && mp[i][j] == mp[i + 1][j]) {
return false; // 上下相邻的两个相同数字可以合并
}
if (j < GRID_CNT - 1 && mp[i][j] == mp[i][j + 1]) {
return false; // 左右相邻的两个相同数字可以合并
}
}
}
return true;
}
// 绘制格子
void girdDraw() {
for (int i = 0; i < GRID_CNT; i++) {
for (int j = 0; j < GRID_CNT; j++) {
int x = (j + 1) * INTERVAL + j * GRID_WIDTH;
int y = (i + 1) * INTERVAL + i * GRID_WIDTH;
setfillcolor(color[mp[i][j]]);
solidrectangle(x, y,x + GRID_WIDTH, y + GRID_WIDTH);
if (mp[i][j] != 0) {
RECT rect = {x, y, x + GRID_WIDTH, y + GRID_WIDTH};
std::string str = std::to_string(mp[i][j]);
setbkmode(TRANSPARENT);
settextstyle(50, 0, "Clear Sans");
drawtext(str.c_str(), &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
}
}
}
// 绘制结束文本
void drawEnd(const char *str) {
setfillcolor(RGB(255, 255, 255));
settextcolor(BLACK);
settextstyle(60, 0, "Clear Sans");
RECT rect = {80, GRID_CNT * GRID_WIDTH / 2 - 40, GRID_CNT * GRID_WIDTH + 5 * INTERVAL - 50, GRID_CNT * GRID_WIDTH / 2 + 40};
setbkmode(TRANSPARENT);
drawtext(str, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
std::string point = "Scores: " + std::to_string(score);
RECT rec = {30, GRID_CNT * GRID_WIDTH / 2 + 320, GRID_CNT * GRID_WIDTH + 5 * INTERVAL, GRID_CNT * GRID_WIDTH / 2 + 40};
setbkmode(TRANSPARENT);
drawtext(point.c_str(), &rec, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
bool is_restart(int x, int y) {
return x >= GRID_CNT * GRID_WIDTH / 4 && x <= 3 * GRID_CNT * GRID_WIDTH / 4 &&
y >= GRID_CNT * GRID_WIDTH / 2 + 60 && y <= GRID_CNT * GRID_WIDTH / 2 + 120;
}
void gameLoop() {
while (1) {
cleardevice();
girdDraw();
settextcolor(WHITE);
if (is_win()) {
cleardevice();
girdDraw();
drawEnd("YOU WIN!");
RECT button = {180, GRID_CNT * GRID_WIDTH / 2 + 60, 3 * GRID_CNT * GRID_WIDTH / 4, GRID_CNT * GRID_WIDTH / 2 + 120};
setfillcolor(RGB(0, 255, 0)); // 绿色按钮
solidrectangle(button.left, button.top, button.right, button.bottom);
settextstyle(30, 0, "Clear Sans");
setbkmode(TRANSPARENT);
drawtext("Restart", &button, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
MOUSEMSG m = GetMouseMsg();
while (m.uMsg != WM_LBUTTONUP) {
m = GetMouseMsg();
}
if (is_restart(m.x, m.y)) {
std::fill(mp[0], mp[0] + GRID_CNT * GRID_CNT, 0);
getLocation();
getLocation();
continue;
}
} else if (is_lose()) {
cleardevice();
girdDraw();
drawEnd("YOU LOSE");
RECT button = {180, GRID_CNT * GRID_WIDTH / 2 + 60, 3 * GRID_CNT * GRID_WIDTH / 4, GRID_CNT * GRID_WIDTH / 2 + 120};
setfillcolor(RGB(0, 255, 0));
solidrectangle(button.left, button.top, button.right, button.bottom);
settextstyle(30, 0, "Clear Sans");
setbkmode(TRANSPARENT);
drawtext("Restart", &button, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
MOUSEMSG m = GetMouseMsg();
while (m.uMsg != WM_LBUTTONUP) {
m = GetMouseMsg();
}
if (is_restart(m.x, m.y)) {
std::fill(mp[0], mp[0] + GRID_CNT * GRID_CNT, 0);
getLocation();
getLocation();
continue;
}
}
girdDraw();
Control();
}
}
int main() {
std::fill(color, color + 2049, c0);
color[2] = c2, color[4] = c4, color[8] = c8, color[16] = c16, color[32] = c32, color[64] = c64, color[128] = c128,
color[256] = c256, color[512] = c512, color[1024] = c1024, color[2048] = c2048, color[4096] = c4096, color[8192] = c8192;
// 创建窗口,大小及颜色如下
initgraph(GRID_CNT * GRID_WIDTH + 5 * INTERVAL, GRID_CNT * GRID_WIDTH + 5 * INTERVAL);
setbkcolor(back);
cleardevice();
// 随机挑选两个格子填上 2 或 4
getLocation();
getLocation();
// 游戏部分
gameLoop();
getchar();
return 0;
}
这下是真的干到400行了~
贴一张游戏截图~😘
别问为什么没有win的截图😅😅 更新前都没打出来过
收工!