C项目--羊了个羊(两关全)--含源码

文章目录

  • 一、项目信息
    • [   1、开发环境](#   1、开发环境)
    • [   2、项目模块](#   2、项目模块)
    • [   3、源码](#   3、源码)
  • 二、游戏初始化
    • [   1、加载相关资源](#   1、加载相关资源)
    • [   2、配置随机数种子](#   2、配置随机数种子)
    • [   3、创建游戏窗口](#   3、创建游戏窗口)
  • 三、地图构建
    • [   1、地图结构设计](#   1、地图结构设计)
    • [   2、图形示例](#   2、图形示例)
    • [   3、构建地图](#   3、构建地图)
  • 四、游戏渲染
    • [   刷新窗口](#   刷新窗口)
  • 五、游戏交互
    • [   检测用户输入](#   检测用户输入)
    • [   处理用户点击后工作](#   处理用户点击后工作)
  • 六、游戏状态控制
  • 七、帧率控制

一、项目信息

1、开发环境

VSCode + MinGw + EasyX

2、项目模块

游戏初始化

地图构建

游戏渲染

游戏交互

帧率控制

3、源码

通过网盘分享的文件:Game_YLGY.rar

链接: https://pan.baidu.com/s/1jal6Yt_mHL4MEu2quwna_g?pwd=91ju 提取码: 91ju

二、游戏初始化

1、加载相关资源

c 复制代码
		// 图片
		IMAGE g_imgWelcomeBg;     // 欢迎 图片
		IMAGE g_imgBg[2];         // 背景图片
		IMAGE g_imgBlocks[15][2]; // 图形块
		IMAGE g_imgLoseBg; // 失败背景图片
		IMAGE g_imgWinBg;  // 成功背景图片
		
		    // 加载背景图片
		    loadimage(&g_imgBg[0], "res/bg1.png");
		    loadimage(&g_imgBg[1], "res/bg2.png");
		    loadimage(&g_imgLoseBg, "res/false.png"); // 失败背景图片
		    loadimage(&g_imgWinBg, "res/win.png");    // 成功背景图片
		    loadimage(&g_imgWelcomeBg, "res/Welcome.png");

2、配置随机数种子

c 复制代码
		    // 配置随机种子
		    srand(time(NULL)); // 配置随机种子

3、创建游戏窗口

c 复制代码
		    // 创建窗口===========================================
		    initgraph(WIN_WIDTH, WIN_HEIGHT);

三、地图构建

1、地图结构设计

使用数据结构描述一个图形块:

c 复制代码
			// 图形块结构体
			struct block
			{
			    int layer;        // 图形块所在层
			    int type;         // 图形块类型
			    int row, col;     // 图形块所在层中,是第几行,第几列
			    int x, y;         // 图形块所在坐标
			    bool top;         // 图形块是否为顶层图形
			    int off_x, off_y; // 图形块所在层第一个方块的边界
			};
			struct block *   layer = (struct block *)malloc(sizeof(struct block));

使用一个指针n维数组描述单层图形块指针数组。

c 复制代码
			g_Maps[layer] = (struct block **)malloc(sizeof(struct block *) * (rows * cols + 1));

使用一个全局二级指针数组指向所有的单层图形块指针数组表示全局地图。

c 复制代码
			// 图形块保存数据体
			struct block **g_Maps[MAX_LAYER];

2、图形示例

3、构建地图

设计第一关地图和第二关地图共两关。

c 复制代码
		// 创建图形块单层
		void initLayer(int layer, int rows, int cols, int off_x, int off_y, int type)
		{
		    // 分配单层指针存储内存空间
		    g_Maps[layer] = (struct block **)malloc(sizeof(struct block *) * (rows * cols + 1));
		    for (int row = 0; row < rows; row++)
		    {
		        for (int col = 0; col < cols; col++)
		        {
		            g_Maps[layer][row * cols + col] = (struct block *)malloc(sizeof(struct block));
		            g_Maps[layer][row * cols + col]->off_x = off_x;
		            g_Maps[layer][row * cols + col]->off_y = off_y;
		            g_Maps[layer][row * cols + col]->row = row;
		            g_Maps[layer][row * cols + col]->col = col;
		            if (type == 0)
		            {
		                g_Maps[layer][row * cols + col]->type = 1 + rand() % 15;
		            }
		            else
		            {
		                g_Maps[layer][row * cols + col]->type = type;
		            }
		            g_Maps[layer][row * cols + col]->top = true;
		            g_Maps[layer][row * cols + col]->x = off_x + col * BLOCK_WIDTH;
		            g_Maps[layer][row * cols + col]->y = off_y + row * BLOCK_HEIGHT;
		            g_Maps[layer][row * cols + col]->layer = layer;
		        }
		    }
		    // 最后一个设为空,方便遍历
		    g_Maps[layer][rows * cols] = NULL;
		}
		// 初始化地图
		void initMap()
		{
		    int layer = 0;
		    if (GemaStatus == GAME_STATUS_INIT) // 在初始化状态  初始地图为第一关
		    {
		        int off = 10;                                              // 图片间隔
		        int offsetX = (WIN_WIDTH - BLOCK_WIDTH * 3 - off * 2) / 2; // 横起始坐标  (背景宽度-图片宽度*2-图片间隔*2)/2
		        int offsetY = 270;
		        /*先初始化为
		            1 1 1
		            2 2 2
		            3 3 3
		        */
		        for (int r = 0; r < 3; r++)
		        {
		            for (int c = 0; c < 3; c++)
		            {
		                int x = offsetX + c * (BLOCK_WIDTH + off);
		                int y = offsetY + r * (BLOCK_HEIGHT + off);
		                initLayer(layer++, 1, 1, x, y, r + 1);
		            }
		        }
		        // 然后打乱
		        for (int i = 0; i < g_Max_layer; i++)
		        {
		            int S = rand() % 9;
		            int D = rand() % 9;
		            int tmp = g_Maps[S][0]->type;
		            g_Maps[S][0]->type = g_Maps[D][0]->type;
		            g_Maps[D][0]->type = tmp;
		        }
		    }
		    if (GemaStatus == GAME_STATUS_LEVEL1) // 在第一关 初始地图为第二关
		    {
		        for (; layer < 12; layer++)
		            initLayer(layer, 1, 1, 30, 440 + layer * 10, 0);
		        for (; layer < 24; layer++)
		            initLayer(layer, 1, 1, 414, 440 + (layer - 12) * 10, 0);
		        for (; layer < 30; layer++)
		            initLayer(layer, 1, 1, 94, 583 + (layer - 24) * 10, 0);
		        for (; layer < 36; layer++)
		            initLayer(layer, 1, 1, 346, 583 + (layer - 30) * 10, 0);
		        for (; layer < 42; layer++)
		            initLayer(layer, 1, 1, 30 + (layer - 36) * 10, 130, 0);
		        for (; layer < 48; layer++)
		            initLayer(layer, 1, 1, 413 - (layer - 42) * 10, 130, 0);
		        initLayer(layer++, 4, 3, 159, 309, 0);
		        initLayer(layer++, 5, 3, 159, 228, 0);
		        initLayer(layer++, 5, 4, 129, 204, 0);
		        initLayer(layer++, 5, 5, 99, 180, 0);
		        initLayer(layer++, 3, 6, 70, 209, 0);
		        initLayer(layer++, 1, 4, 134, 133, 0);
		        initLayer(layer++, 1, 4, 134, 118, 0);
		        initLayer(layer++, 1, 4, 134, 103, 0);
		        initLayer(layer++, 2, 5, 100, 258, 0);
		        initLayer(layer++, 2, 5, 100, 243, 0);
		        initLayer(layer++, 2, 5, 100, 228, 0);
		        initLayer(layer++, 2, 5, 100, 228, 0);
		        initLayer(layer++, 2, 5, 100, 228, 0);
		        initLayer(layer++, 2, 5, 100, 228, 0);
		        //将地图校验并修正
		        checkMap();
		    }
		}

四、游戏渲染

刷新窗口

c 复制代码
	void updateWindow()
	{
	    // 开始双缓冲
	    BeginBatchDraw();
	    // 绘制背景图:实现背景图片切换,实现小草动态图
	    static int timecnt = 0;
	    if (timecnt < 20)
	    {
	        putimage(0, 0, &g_imgBg[0]);
	    }
	    else
	    {
	        putimage(0, 0, &g_imgBg[1]);
	    }
	    timecnt++;
	    if (timecnt == 40)
	        timecnt = 0;
	    // 绘制图形块
	    for (int i = 0; i < g_Max_layer; i++)
	    {
	        for (int k = 0; g_Maps[i][k]; k++)
	        {
	            struct block *p = g_Maps[i][k];
	            IMAGE *img = &g_imgBlocks[p->type - 1][p->top];
	            putimagePNG(p->x, p->y, img);
	        }
	    }
	    // 绘制羊槽
	    for (int i = 0; i < 7; i++)
	    {
	        if (store[i])
	        {
	            int x = 26 + i * 64.7;
	            int y = 778;
	            putimagePNG(x, y, &g_imgBlocks[store[i] - 1][1]);
	        }
	    }
	    // 结束双缓冲
	    EndBatchDraw();
	}

五、游戏交互

检测用户输入

c 复制代码
	bool userClick()
	{
	    ExMessage msg;
	    if (peekmessage(&msg) && msg.message == WM_LBUTTONDOWN)
	    {
	        for (int layer = g_Max_layer - 1; layer >= 0; layer--)
	        {
	            for (int k = 0; g_Maps[layer][k]; k++)
	            {
	                struct block *p = g_Maps[layer][k];
	                if (p->type &&
	                    msg.x > p->x && msg.x < p->x + BLOCK_WIDTH &&
	                    msg.y > p->y && msg.y < p->y + BLOCK_HEIGHT)
	                {
	                    clickedBlock = p;
	                    return p->top;
	                }
	            }
	        }
	    }
	    return false;
	}

处理用户点击后工作

c 复制代码
	void work()
	{
	    clearBlock(clickedBlock);
	    int i = 0;
	    for (; store[i] && i < 7; i++)
	        ;
	    if (i < 7)
	    {
	        store[i] = clickedBlock->type;
	    }
	    else
	    {
	        GemaStatus = GAME_STATUS_LOSE;
	    }
	    // 如果有三个一样的则消除
	    int cnt = 0;
	    for (int i = 0; i < 7; i++)
	    {
	        if (store[i] == clickedBlock->type)
	        {
	            cnt++;
	        }
	    }
	    if (cnt == 3)
	    {
	        for (int i = 0; i < 7; i++)
	        {
	            if (store[i] == clickedBlock->type)
	            {
	                store[i] = 0;
	            }
	        }
	        // 重新排序
	        int j = 0;
	        for (int i = 0; i < 7; i++)
	        {
	            if (store[i] != 0)
	            {
	                store[j] = store[i];
	                j++;
	            }
	        }
	        for (; j < 7; j++)
	        {
	            store[j] = 0;
	        }
	    }
	    clickedBlock->type = 0;
	    setTops();
	}

六、游戏状态控制

c 复制代码
	// 游戏状态
	#define GAME_STATUS_INIT 0
	#define GAME_STATUS_LEVEL1 1
	#define GAME_STATUS_LEVEL2 2
	#define GAME_STATUS_LOSE 3
	#define GAME_STATUS_WIN 4
	int GemaStatus = GAME_STATUS_INIT; // 0为初始化 1为第1关    2 为第2关   3为失败   4 为胜制
	//省略.......其它代码
	    while (true)
	    {
	        switch (GemaStatus)
	        {
	        case GAME_STATUS_INIT:
	        {
	            GemaStatus = GAME_STATUS_LEVEL1;
	        }
	        break;
	        case GAME_STATUS_LEVEL1:
	        {
	            if (isWin())
	            {
	                GemaStatus = GAME_STATUS_LEVEL2;
	            }
	        }
	        break;
	        case GAME_STATUS_LEVEL2:
	        {
	            if (isWin())
	            {
	                GemaStatus = GAME_STATUS_WIN;
	            }
	        }
	        break;
	        case GAME_STATUS_LOSE:
	        {
	            putimage(0, 0, &g_imgLoseBg);
	        }
	        break;
	        case GAME_STATUS_WIN:
	        {
	            putimage(0, 0, &g_imgWinBg);
	        }
	        break;
	        default:
	            break;
	        }
	    }

七、帧率控制

c 复制代码
	
	   while (true)
	    {
	        clock_t start_Time = clock(); // 记录帧开始时间
			//省略.......其它代码
	        // 计算本帧已用时间
	        clock_t cost_time = clock() - start_Time;
	        // 如果本帧绘制用时少于目标时间,则休眠剩余时间
	        if (cost_time < FRAME_INTERVAL)
	            Sleep(FRAME_INTERVAL - cost_time);
	    }
相关推荐
云帆小二2 小时前
从开发语言出发如何选择学习考试系统
开发语言·学习
我不会插花弄玉2 小时前
排序【由浅入深-数据结构】
c语言·数据结构
光泽雨2 小时前
python学习基础
开发语言·数据库·python
百***06013 小时前
python爬虫——爬取全年天气数据并做可视化分析
开发语言·爬虫·python
jghhh013 小时前
基于幅度的和差测角程序
开发语言·matlab
fruge3 小时前
自制浏览器插件:实现网页内容高亮、自动整理收藏夹功能
开发语言·前端·javascript
No0d1es3 小时前
电子学会青少年软件编程(C/C++)六级等级考试真题试卷(2025年9月)
c语言·c++·算法·青少年编程·图形化编程·六级
Knox_Lai4 小时前
数据结构与算法学习(0)-常见数据结构和算法
c语言·数据结构·学习·算法
曹牧4 小时前
Java中处理URL转义并下载PDF文件
java·开发语言·pdf
未来之窗软件服务4 小时前
幽冥大陆(二十二)dark语言智慧农业电子秤读取——东方仙盟炼气期
开发语言·windows·golang·东方仙盟·东方仙盟sdk