一.任务详细
任务要求
我的完成
- 2048游戏进入界面完成
- 正常按键操作
- 开始界面的鼠标菜单
- 文件保存,前十成绩显示
- 游戏界面不采用贴图
- 菜单界面采用贴图加音乐循环
二.EasyX图形库的安装和使用
安装教程
使用教程
推荐学习视频
囊括了图片、按键、鼠标、音乐、弹窗
https://www.bilibili.com/video/BV11p4y1i74A/?spm_id_from=333.337.search-card.all.click&vd_source=3ca547207338045ac672be8086fa0cda
三.代码块
准备素材
将需要的图片、声音、文本放入文件夹内
用于菜单界面的图片显示和游戏背景音乐和成绩储存
全部代码块
主函数源文件
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <stdio.h>
#include <time.h>
#include <graphics.h>
#include <conio.h>
#include<mmsystem.h>
#pragma comment(lib,"WINMM.LIB")
#include "My_Game.h"
#include "2048.h"
int main()
{
game_initialize();
while (true)//开始菜单
{
if (MouseHit())
{
MOUSEMSG msg = GetMouseMsg();//鼠标操作变量
switch (msg.uMsg)
{
case WM_LBUTTONDOWN://鼠标左键
if (msg.x > 17 && msg.x < 62 && msg.y>511 && msg.y < 585) Ranking_score(score);//排行榜
if (msg.x > 421 && msg.x < 579 && msg.y>453 && msg.y < 500)
{
game_2048();//游戏
/*Sleep(1550);
game_initialize();*/
}
break;
case WM_RBUTTONDOWN://鼠标右键
printf("鼠标(%d,%d)", msg.x, msg.y);
break;
}
}
}
int rubbish = getchar();//放置图形窗口闪屏
system("pause");//防止控制台窗口闪屏
return 0;
}
头文件
#pragma once
static int score[12] = {0,0,0,0,0,0,0,0,0,0,0};//保存历史成绩前十
static int Map[4][4]=
{
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0}
};
void Number_block_module(int x, int y, int Num_1);
void Ranking_score(int score[]);
void random_generation();
void bubble_sort(int num);
void Key_down_D(void);
void Key_down_A(void);
void Key_down_S(void);
void Key_down_W(void);
int End_game_test();
void Key_detection();
void Map_initialize(void);
void game_2048();
#pragma once
void game_initialize();
源文件
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>//c语言标准库
#include <string.h>
#include <graphics.h>//图形库
#include <conio.h>
#include <time.h>
#include "2048.h"
/*
参数:xy坐标
返回值:无
介绍:生成数字方块1个
*/
void Number_block_module(int x, int y, int Num_1)
{
x *= 100;
y *= 100;
y += 80;
switch (Num_1)
{
case 0:
setfillcolor(RGB(205, 193, 180));//0
break;
case 2:
setfillcolor(RGB(238, 228, 218));//2
break;
case 4:
setfillcolor(RGB(237, 224, 200));
break;
case 8:
setfillcolor(RGB(242, 177, 121));
break;
case 16:
setfillcolor(RGB(245, 149, 99));
break;
case 32:
setfillcolor(RGB(246, 124, 95));
break;
case 64:
setfillcolor(RGB(246, 94, 59));
break;
case 128:
setfillcolor(RGB(246, 94, 59));
break;
case 256:
setfillcolor(RGB(246, 94, 59));
break;
case 512:
setfillcolor(RGB(246, 94, 59));
break;
default:
setfillcolor(RGB(246, 94, 59));
break;
}
setlinecolor(RGB(187, 173, 160));//设置线条颜色
setlinestyle(PS_SOLID, 10);//设置线条样式
fillrectangle(x, y, x + 100, y + 100);
if (Num_1 == 0) return;
settextcolor(RGB(119, 110, 101));//设置字体颜色
setbkmode(TRANSPARENT);//设置背景模式
settextstyle(30, 20, "黑体");//设置文字样式
char Str1[20] = "";
sprintf(Str1, "%d", Num_1);
/*居中显示*/
int width = textwidth(Str1);//获取字符串实际占用的像素高度
int height = textheight(Str1);//获取字符串实际占用的像素宽度
outtextxy(x + ((100 - width) / 2), y + ((100 - height) / 2), Str1);//绘制文字
return;
}
void Ranking_score(int score[])
{
FILE* r_fp = fopen("score.txt", "r");//打开文件,只读模式
if (r_fp == NULL) return ;
int a = fscanf(r_fp, "%d %d %d %d %d %d %d %d %d %d ", &score[0], &score[1], &score[2], &score[3], &score[4], &score[5], &score[6], &score[7], &score[8], &score[9]);
fclose(r_fp);//关闭文件指针
setfillcolor(RGB(61, 91, 158));//设置填充颜色
setlinecolor(RGB(66, 93, 145));//设置线条颜色
setlinestyle(PS_SOLID, 10);//设置线条样式
fillrectangle(321, 92, 692, 400);
settextcolor(RGB(2, 3, 0));//设置字体颜色
setbkmode(TRANSPARENT);//设置背景模式
settextstyle(25, 18, "黑体");//设置文字样式
outtextxy(321, 92, "前十排行榜");//绘制文字
for (int i = 0; i < 10; i++)
{
char Str1[10] = "";
sprintf(Str1, "%d", score[i]);
outtextxy(321 , 122+28*i , Str1);//绘制文字
}
}
/*
参数:无
返回值:无
介绍:随机生成方块
*/
void random_generation()
{
//Sleep(150);
int x1, y1;
int cmp = 0;
for (int i = 0; i < 16; i++)
{
int y = i / 4;//0 1 2 3 行
int x = i % 4;//0 1 2 3 列
if (Map[x][y] == 0) cmp++;
}
while (cmp)
{
y1 = rand() % 4;//0 1 2 3 行
x1 = rand() % 4;//0 1 2 3 列
if (Map[x1][y1] == 0)
{
Map[x1][y1] = (rand() % 3) * 2;
if (Map[x1][y1] == 0) Map[x1][y1] = 2;
return;
}
else
{
continue;
}
}
}
/*
参数:无
返回值:无
介绍:初始化窗口
*/
void Map_initialize(void)
{
initgraph(100 * 4, 100 * 4 + 100, SHOWCONSOLE);//创建图形窗口//NOMINIMIZE
setbkcolor(RGB(250, 248, 239));
cleardevice();//清理图形窗口
setfillcolor(RED);//设置填充颜色
fillrectangle(0, 80, 100 * 4 - 1, 80 + 100 * 4 - 1);
settextcolor(RGB(119, 110, 101));//设置字体颜色
setbkmode(TRANSPARENT);//设置背景模式
settextstyle(65, 38, "华文彩云");//设置文字样式
outtextxy(0, 10, "2048游戏");//绘制文字
for (int i = 0; i < 16; i++)
{
int y = i / 4;//0 1 2 3 行
int x = i % 4;//0 1 2 3 列
Number_block_module(x, y, Map[y][x]);
}
}
/*
参数:无
返回值:无
介绍:游戏规则,合并
*/
void Key_down_D(void)
{
short cmp = 3;
while (cmp--)
{
for (int i = 0; i < 16; i++)//右键
{
int x = 3 - (i % 4);//3 2 1 0列
int y = i / 4;//0 1 2 3 行
if ((x - 1) >= 0)//一直运行到x=0时
{
if ((Map[y][x] == 0) && (Map[y][x - 1] != 0))//如果此为零,下一个不是零,就移动
{
Map[y][x] += Map[y][x - 1];
Map[y][x - 1] = 0;
}
if (Map[y][x] == Map[y][x - 1]) //如果此和下一个相等,就合并
{
Map[y][x] += Map[y][x - 1];
Map[y][x - 1] = 0;
}
}
}
}
}
void Key_down_A(void)
{
short cmp = 3;
while (cmp--)
{
for (int i = 0; i < 16; i++)//左键
{
int x = i % 4;//0 1 2 3 列
int y = i / 4;//0 1 2 3 行
if ((x + 1) < 4)
{
if ((Map[y][x] == 0) && (Map[y][x + 1] != 0))//移动不同
{
Map[y][x] += Map[y][x + 1];
Map[y][x + 1] = 0;
}
if ((Map[y][x] == Map[y][x + 1]) && (Map[y][x + 1] != 0))//合并相同
{
Map[y][x] += Map[y][x + 1];
Map[y][x + 1] = 0;
}
}
}
}
}
void Key_down_S(void)
{
short cmp = 3;
while (cmp--)
{
for (int i = 0; i < 16; i++)//下键
{
int x = i % 4;//0 1 2 3 列
int y = 3 - (i / 4);//3 2 1 0 行
if ((y - 1) >= 0)
{
if ((Map[y][x] == 0)&& (Map[y - 1][x] != 0))//移动不同
{
Map[y][x] += Map[y - 1][x];
Map[y - 1][x] = 0;
}
if ((Map[y][x] == Map[y - 1][x])&&(Map[y - 1][x] != 0)) //合并相同
{
Map[y][x] += Map[y - 1][x];
Map[y - 1][x] = 0;
}
}
}
}
}
void Key_down_W(void)
{
short cmp = 3;
while (cmp--)
{
for (int i = 0; i < 16; i++)//上键
{
int x = i % 4;//0 1 2 3 列
int y = i / 4;//0 1 2 3 行
if ((y + 1) < 4)//一直运行到x=0时
{
if ((Map[y][x] == 0)&&(Map[y + 1][x] != 0))//移动不同
{
Map[y][x] += Map[y + 1][x];
Map[y + 1][x] = 0;
}
if ((Map[y][x] == Map[y + 1][x])&& (Map[y + 1][x] != 0)) //合并相同
{
Map[y][x] += Map[y + 1][x];
Map[y + 1][x] = 0;
}
}
}
}
}
/*
参数:无
返回值:无
介绍:检测游戏得分,并判断游戏是否结束
*/
int End_game_test()
{
setfillcolor(WHITE);//设置填充颜色
setlinecolor(WHITE);//设置线条颜色
setlinestyle(PS_SOLID, 10);//设置线条样式
fillrectangle(0, 485, 400, 499);//画有边框的填充矩形
int total_points=0;//统计得分
for (int i = 0; i < 16; i++)
{
int x = i % 4;//0 1 2 3 列
int y = i / 4;//0 1 2 3 行
total_points += Map[x][y];
}
settextcolor(RGB(119, 110, 101));//设置字体颜色
setbkmode(TRANSPARENT);//设置背景模式
settextstyle(15, 10, "华文中宋");//设置文字样式
char j[50] = "游戏当前得分:";
char str[10];
sprintf(str, "%d", total_points);
strcat(j, str);
outtextxy(0, 483,ppppppppppppppppppppppppppppppppppppppplllllllllllllllllllllllllllllll );//绘制文字
int Num_0 = 0;
for (int i = 0; i < 16; i++)//游戏顺利判断
{
int x = i % 4;//0 1 2 3 列
int y = i / 4;//0 1 2 3 行
if (Map[x][y] == 20480)
{
fillrectangle(0, 0, 400, 80);
settextcolor(RGB(119, 110, 101));//设置字体颜色
setbkmode(TRANSPARENT);//设置背景模式
settextstyle(65, 38, "华文彩云");//设置文字样式
outtextxy(0, 10, "游戏成功");//绘制文字
return 0;
}
if (Map[x][y] == 0) Num_0++;
}
if (Num_0 == 0)//游戏失败判断
{
int cmp=0;//检查四边相同
for (int j = 0; j < 16; j++)
{
int x = j % 4;//0 1 2 3 列
int y = j / 4;//0 1 2 3 行
if ((Map[x][y] == Map[x][y + 1]) && (y + 1 < 4)) cmp++;//上下检测
if ((Map[x][y] == Map[x+1][y]) && (x + 1 < 4)) cmp++;//左右检测
}
if (cmp == 0)
{
fillrectangle(0, 0, 400, 80);
settextcolor(RGB(119, 110, 101));//设置字体颜色
setbkmode(TRANSPARENT);//设置背景模式
settextstyle(65, 38, "华文彩云");//设置文字样式
outtextxy(0, 10, "游戏失败");//绘制文字
return 0;
}
}
return 1;
}
/*
参数:无
返回值:无
介绍:检测按键
*/
void Key_detection(void)
{
char Key = _getch();
switch (Key)
{
case'W':case'w':case 72:Key_down_W(); break;
case'S':case's':case 80:Key_down_S(); break;
case'A':case'a':case 75:Key_down_A(); break;
case'D':case'd':case 77:Key_down_D(); break;
default:
break;
}
for (int i = 0; i < 16; i++)
{
int y = i / 4;//0 1 2 3 行
int x = i % 4;//0 1 2 3 列
Number_block_module(x, y, Map[y][x]);
}
random_generation();
for (int i = 0; i < 16; i++)
{
int y = i / 4;//0 1 2 3 行
int x = i % 4;//0 1 2 3 列
Number_block_module(x, y, Map[y][x]);
}
}
/*
开始游戏
*/
void game_2048()
{
Map_initialize();
FILE* r_fp = fopen("score.txt", "r");//打开文件,只读模式
if (r_fp == NULL) return;
int b = fscanf(r_fp, "%d %d %d %d %d %d %d %d %d %d ", &score[0], &score[1], &score[2], &score[3], &score[4], &score[5], &score[6], &score[7], &score[8], &score[9]);
fclose(r_fp);//关闭文件指针
int Tag = 1;
srand((unsigned)time(NULL)); // 随机种子
while (Tag)
{
Key_detection();
Tag=End_game_test();
}
int total_points = 0;//统计得分
for (int i = 0; i < 16; i++)
{
int x = i % 4;//0 1 2 3 列
int y = i / 4;//0 1 2 3 行
total_points += Map[x][y];
Map[x][y] = 0;
}
bubble_sort(total_points);
FILE* w_fp = fopen("score.txt", "w");//打开文件,只写模式
if (w_fp == NULL) return;
int a = fprintf(w_fp, "%d %d %d %d %d %d %d %d %d %d ", score[0], score[1], score[2], score[3], score[4], score[5], score[6], score[7], score[8], score[9]);
fclose(w_fp);//关闭文件指针
return;
}
void bubble_sort(int num)//冒泡排序
{
score[10] = num;
for (int i = 0; i < 11; i++)
{
for (int j = 0; j < 11; j++)
{
if (score[j] < score[j + 1])
{
int cmp = score[j];
score[j] = score[j+1];
score[j+1] = cmp;
}
}
}
}
#include "My_Game.h"
#include <graphics.h>
#include <time.h>
#include <conio.h>
void Menu()
{
initgraph(1000, 600, SHOWCONSOLE);
IMAGE picture1;//图片变量
loadimage(&picture1, "./game0.jpg", 1000, 600);
putimage(0, 0, &picture1);
setlinecolor(RGB(56, 56, 56));//设置线条颜色
setlinestyle(PS_SOLID, 10);//设置线条样式
settextcolor(RGB(30, 30, 30));//设置字体颜色
setbkmode(TRANSPARENT);//设置背景模式
settextstyle(50, 30, "黑体");//设置文字样式
}
/*
初始化游戏开始界面
*/
void game_initialize()
{
initgraph(1000, 600, SHOWCONSOLE);
IMAGE picture1;//图片变量
loadimage(&picture1, "./game0.jpg", 1000, 600);
putimage(0, 0, &picture1);
mciSendString("open ./bgm.mp3 alias BGM", 0, 0, 0);
mciSendString("play BGM repeat", 0, 0, 0);
Sleep(550);
loadimage(&picture1, "./game.png", 1000, 600);
putimage(0, 0, &picture1);
}
四.易错点分享
音乐播放没有声音的问题
注意:音乐不要在网易云音乐等音乐播放器里面下载的,不然声音无法加载(而且没有报错)
这里我留下一个网址让大家可以免费下载mp3音乐资源
https://www.gequbao.com/
而且也千万记得配置好
#include <graphics.h>
#include<mmsystem.h>
#pragma comment(lib,“WINMM.LIB”)
这三个预处理
图形库无法使用的问题
注意:一定要用cpp后缀不然EasyX无法正常使用
还有文件路径当前文件路径要用“./XXX.png”
画背景无法显示的问题
一定要先setbkcolor (颜色);//设置背景颜色(之后面记得运行清屏)
然后再cleardevice();//清理图形窗口