C语言 2048游戏项目 EasyX图形库

一.任务详细

任务要求

第三次考核.pdf

我的完成

  1. 2048游戏进入界面完成
  2. 正常按键操作
  3. 开始界面的鼠标菜单
  4. 文件保存,前十成绩显示
  5. 游戏界面不采用贴图
  6. 菜单界面采用贴图加音乐循环

二.EasyX图形库的安装和使用

安装教程

具体我推荐按照以下链接来
https://www.bilibili.com/video/BV1Xv4y1p7z1/?spm_id_from=333.337.search-card.all.click&vd_source=3ca547207338045ac672be8086fa0cda

使用教程

推荐学习视频
囊括了图片、按键、鼠标、音乐、弹窗
https://www.bilibili.com/video/BV11p4y1i74A/?spm_id_from=333.337.search-card.all.click&vd_source=3ca547207338045ac672be8086fa0cda

三.代码块

准备素材

将需要的图片、声音、文本放入文件夹内
用于菜单界面的图片显示和游戏背景音乐和成绩储存

QQ截图20231116144348.png

全部代码块

主函数源文件

#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();//清理图形窗口

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值