C语言实战 - 贪吃蛇(图形界面)

news2024/11/29 16:29:32
  • 由于本人精力有限,暂时先把素材和代码放上,等以后有空再补教程。

目录

效果预览

准备工作

EasyX图形库

音频素材

代码编写

Transfer.h文件

game.cpp文件

main.c文件


效果预览

先来看一下最终成品效果

贪吃蛇图形界面

准备工作

EasyX图形库

这个贪吃蛇项目是基于EasyX图形库写的,所以需要安装一个easy图像库,官方下载地址如下:

EasyX Graphics Library for C++https://easyx.cn/

音频素材

CSDN资源下载地址:贪吃蛇素材文件(图片+音频)-C文档类资源-CSDN文库

PS:如果遇到非会员下载不了的情况可以私信或者在评论区留言,作者再想办法。

代码编写

  • Transfer.h文件


//头文件
#pragma once
#include<stdio.h>
#include<graphics.h>
#include<easyx.h>
#include<windows.h>
#include<conio.h>
#include<stdlib.h>
#include<time.h>
#include<mmsystem.h>//包含多媒体设备接口头文件
#pragma comment(lib,"winmm.lib")//加载静态库

//类型定义
typedef struct snake_coor {//蛇的坐标
	int x;
	int y;
}COOR;
typedef enum dir {//蛇的方向
	up, down, left, right,stop
}DIR;
typedef  struct snake_information {//蛇的信息
	COOR coor[1000]={0};
	int length=0;
	int state=0;
	DIR direction;
}INF;
typedef struct food_coor {//食物坐标
	int x=0;
	int y=0;
}FOOD;

//函数声明
void button(int x, int y, int len, int wid, 
const char* text,int chg1,int chg2);				//按钮函数
int menu();											//菜单界面
void background();									//游戏背景
void snake_Initialization();						//初始化蛇
void snkae_key();									//按键控制
void snake_move();									//蛇的移动
void snake_draw();									//蛇的绘制
void food_draw();									//画出食物
void food_coor();									//食物坐标
void judge();										//判断函数
void game();										//游戏函数
  • game.cpp文件

#include"Transfer.h"
INF snake;				//蛇的定义
FOOD food;				//定义食物

void button(int x,int y,int len,int wid,const char* text,int chg1,int chg2)
{
	//图形部分
	setlinecolor(TRANSPARENT);
	setfillcolor(YELLOW);
	setlinecolor(BROWN);
	fillroundrect(x, y, x + len, y + wid,20,20);

	//文字部分
	char text_trans[50];			
	strcpy_s(text_trans, text);
	setbkmode(TRANSPARENT);
	settextstyle(30, 0, "华文行楷");
	settextcolor(BLACK);
	int x_end = x+chg1;
	int y_end = y+chg2;
	outtextxy(x_end,y_end, text_trans);
}
int menu()//菜单
{
	//播放背景音乐
	mciSendString("play ./menu_bgm.mp3 repeat", 0, 0, 0);			
	cleardevice();
	//右边区域
	HRGN words_area = CreateRectRgn(680, 0, 900, 580);
	setcliprgn(words_area);
	IMAGE pic_left;
	loadimage(&pic_left, "./background_other.jpg", 0, 0);
	putimage(680, 0, &pic_left);
	RECT words{ 700, 150, 850, 400 };
	DeleteObject(words_area);
	//左边区域
	HRGN menu_area = CreateRectRgn(0, 0, 680, 580);
	setcliprgn(menu_area);
	IMAGE background_menu;
	loadimage(&background_menu, "./background_menu.jpg", 0, 0);
	putimage(0, 0, &background_menu);	
	button(260, 80, 160, 50, "开始游戏",25,10);
	button(260, 200, 160, 50, "退出游戏", 25, 10);
	//鼠标选择
	MOUSEMSG click;
	while (1)
	{
		if (MouseHit())
		{
			click = GetMouseMsg();										//获取鼠标信息
			if (click.uMsg == WM_LBUTTONDOWN)							//按下左键时
			{
			//第一个按钮
			if (click.x >= 260 && click.x <= 420 && click.y >= 80 && click.y <= 130)		
				{
				mciSendString("stop ./menu_bgm.mp3",0, 0, 0);			//停止菜单背景音乐
				mciSendString("play click_sound.mp3", 0, 0, 0);			//点击音效
				mciSendString("play ./game_bgm.mp3 repeat", 0, 0, 0);	//播放游戏背景音乐
				return 1;
				}
			//第二个按钮
			if (click.x >= 260 && click.x <= 420 && click.y >= 200 && click.y <= 250)		
				{
				mciSendString("stop ./menu_bgm.mp3", 0, 0, 0);			//停止菜单背景音乐
				mciSendString("play click_sound.mp3", 0, 0, 0);			//点击音效				
				return 0;
				}
			}
		}
	}
	return 0;
}
void background()
{
	cleardevice();
	//右边图片
	HRGN words_area = CreateRectRgn(680, 0, 900, 580);
	setcliprgn(words_area);
	IMAGE pic_left;
	loadimage(&pic_left, "./background_right.jpg", 0, 0);
	putimage(680, 0, &pic_left);
	//右边文字
	settextstyle(18, 0, "宋体");
	settextcolor(BLACK);
	setbkmode(TRANSPARENT);
	outtextxy(690, 500, "退出:Esc    暂停:Space");
	//得分区域
	settextstyle(40, 0, "微软雅黑"); 
	settextcolor(BLUE);
	setbkmode(TRANSPARENT); 
	char grade[50]; 
	sprintf_s(grade ,"%d" ,snake.length - 3);
	outtextxy(790, 344, grade); 
	//释放空间
	DeleteObject(words_area); 
	//游戏区域
	HRGN game_area = CreateRectRgn(0, 0, 680, 580);
	setcliprgn(game_area);
	IMAGE background_menu;
	loadimage(&background_menu, "./background_left.jpg", 0, 0);
	putimage(0, 0, &background_menu);
}
void snake_Initialization()
{
	//初始化长度
	snake.length = 3;
	//初始化蛇头
	snake.coor[0].x = 320;
	snake.coor[0].y = 250;
	//初始化蛇身
	snake.coor[1].x = 310;
	snake.coor[1].y = 250;
	//初始化蛇尾
	snake.coor[2].x = 300;
	snake.coor[2].y = 250;
	//初始化食物坐标
	food.x = (rand() % 69) * 10;
	food.y = (rand() % 56) * 10;
	//初始化方向
	snake.direction = right;
}
void snake_draw()
{
	int i = 0, j = 0;
	for (i = 0; i < snake.length; i++)
	{
			//线条颜色
			setlinecolor(YELLOW);
			//蛇身颜色
			if (i!=0&&i!=snake.length-1)
			{
				setfillcolor(RGB(51,255,88));			
				fillrectangle(snake.coor[i].x, snake.coor[i].y, snake.coor[i].x + 10, snake.coor[i].y + 10);
			}
			//蛇头颜色
			if (i == 0)
			{
				setfillcolor(RGB(31,100,255));				
				fillrectangle(snake.coor[i].x, snake.coor[i].y, snake.coor[i].x + 10, snake.coor[i].y + 10);
			}
			//蛇尾颜色
			if (i == snake.length - 1)
			{
				setfillcolor(RGB(159,255,213)); 			
				fillrectangle(snake.coor[i].x, snake.coor[i].y, snake.coor[i].x + 10, snake.coor[i].y + 10);
			}				
	}
}
void snkae_key()
{
	char get;
	//获取键盘内容
	printf("2");
	if (_kbhit())
	{
		printf("3");
		get = _getch();
		printf("1");
		if ( (get == 'W' || get =='w') && snake.direction != down)
		{
			snake.direction = up;			//上 --- W
		}
		if ( (get == 'A' || get == 'a') && snake.direction != right)
		{
			snake.direction = left;			//左 --- A 
		}
		if ((get == 'S' || get == 's') && snake.direction != up)
		{
			snake.direction = down;			//下 --- S
		}
		if ((get == 'D' || get == 'd') && snake.direction != left)
		{
			snake.direction = right;		//右 --- D
		}
		if (get == ' ')						
		{
			system("pause");			    //暂停 - Space
		}
		if (get == 27)
		{
			exit(0);						//退出 - Esc
		}
		if (get == 72 && snake.direction != down)
		{
			snake.direction = up;			//上					
		}
		if (get == 80 && snake.direction != up)
		{
			snake.direction = down;			//下					
		}
		if (get == 75 && snake.direction != right)
		{
			snake.direction = left;			//左					
		}
		if (get == 77 && snake.direction != left)
		{
			snake.direction = right;		//右					
		}

	}
}
void snake_move()
{
	//蛇身坐标前移
	for (int i = snake.length - 2; i >= 0; i--)
	{
		snake.coor[i + 1].x = snake.coor[i].x;
		snake.coor[i + 1].y = snake.coor[i].y;
	}
	//蛇头坐标移动
	if (snake.direction==up)//上
	{
		snake.coor[0].y -= 10;		
	}
	if (snake.direction == down)//下
	{
		snake.coor[0].y += 10;
	}
	if (snake.direction == left)//左
	{
		snake.coor[0].x -= 10;
	}
	if (snake.direction == right)//右
	{
		snake.coor[0].x += 10;
	}	
	//画出新的蛇
	snake_draw();
}
void food_draw()
{
		setfillcolor(RGB(255,0,0));			
		solidrectangle(food.x, food.y, food.x + 10, food.y + 10);
}
void food_coor()
{
		int x, y;
		x = ((rand() % 66) +1) * 10; 
		y = ((rand() % 56) +1) * 10; 
		//食物不能与蛇身重合
		for (int i = 0;( x==snake.coor[i].x  && y == snake.coor[i].y); i++)
		{
			x = ((rand() % 66) + 1) * 10;
			y = ((rand() % 56) + 1) * 10;
		}
		food.x = x;
		food.y = y;
}
void judge()
{
		HWND result= GetHWnd();
		int out;
		char grade[50];
		//判断吃否吃到食物
		if (snake.coor[0].x == food.x&& snake.coor[0].y == food.y)
		{
			mciSendString("open ./eat_sound.mp3", 0, 0, 0);	//食物音效
			mciSendString("play eat_sound.mp3", 0, 0, 0);	//食物音效
			food_coor();			
			snake.length++;
		}
		//判断是否撞墙
		if (snake.direction == up && snake.coor[0].y <=10 )
		{
			mciSendString("play death_sound.mp3", 0, 0, 0);			//播死亡音效
			mciSendString("stop ./game_bgm.mp3", 0, 0, 0);			//停止游戏背景音乐
			sprintf_s(grade, "分数:%d", snake.length - 3);			
			out = MessageBox(result, grade, "游戏结束",MB_DEFBUTTON1);
			snake.state = 1;
		}
		if (snake.direction == down && snake.coor[0].y >=560  )
		{
			mciSendString("play death_sound.mp3", 0, 0, 0);			//播死亡音效 
			mciSendString("stop ./game_bgm.mp3", 0, 0, 0);			//停止游戏背景音乐
			sprintf_s(grade, "分数:%d", snake.length - 3);
			out = MessageBox(result, grade, "游戏结束", MB_DEFBUTTON1);
			snake.state = 1;
		}
		if (snake.direction == left && snake.coor[0].x<=10  )
		{
			mciSendString("play death_sound.mp3", 0, 0, 0);			//播死亡音效
			mciSendString("stop ./game_bgm.mp3", 0, 0, 0);			//停止游戏背景音乐
			sprintf_s(grade, "分数:%d", snake.length - 3);
			out = MessageBox(result, grade, "游戏结束", MB_DEFBUTTON1);
			snake.state = 1;
		}
		if (snake.direction == right && snake.coor[0].x>=660 )
		{
			mciSendString("play death_sound.mp3", 0, 0, 0);			//播死亡音效
			mciSendString("stop ./game_bgm.mp3", 0, 0, 0);			//停止游戏背景音乐
			sprintf_s(grade, "分数:%d", snake.length - 3);
			out = MessageBox(result, grade, "游戏结束", MB_DEFBUTTON1);
			snake.state = 1;
		}
		//判断是否撞到蛇身
		for (int i = 1; i < snake.length; i++)
		{
		if (snake.coor[0].x == snake.coor[i].x && snake.coor[0].y == snake.coor[i].y)
			{
			mciSendString("play ./death_sound.mp3", 0, 0, 0);		//播死亡音效
			mciSendString("stop ./game_bgm.mp3", 0, 0, 0);			//停止游戏背景音乐	
			sprintf_s(grade, "分数:%d", snake.length - 3);
			out = MessageBox(result, grade, "游戏结束", MB_DEFBUTTON1);
			snake.state = 1;
			}
		}
}
void game()
{	
	int m, n;
	snake_Initialization();			//初始化蛇
	while (snake.state != 1)		//进入循环
	{								//
	BeginBatchDraw();				//开始批量绘图
	background();					//游戏背景
	food_draw();					//画食物
	snake_move();					//蛇移动
	m = 180 - (snake.length - 3);	//控制速度变化
	n = (m >= 10) ? (m) : (10);		//控制速度变化
	Sleep(n);						//休眠 - 控制速度
	EndBatchDraw();					//结束批量绘图
	snkae_key();					//按键检测
	judge();						//进行判断
	}								//

}
  • main.c文件

#include"Transfer.h"

extern INF snake;	
int main()
{
	//打开音乐
	mciSendString("open ./click_sound.mp3", 0, 0, 0);
	mciSendString("open ./death_sound.mp3", 0, 0, 0);
	mciSendString("open ./eat_sound.mp3", 0, 0, 0);
	mciSendString("open ./menu_bgm.mp3", 0, 0, 0);
	mciSendString("open ./game_bgm.mp3", 0, 0, 0);
	//设置随机数
	srand((unsigned)time(NULL));
	//设置画面大小
	initgraph(900, 580, 0);
	int choice;
	while (1)
	{
		choice = menu();
		if ( choice == 1 )//进入游戏
		{	
			game();
			if (snake.state == 1)
				snake.state = 0;
		}
		if ( choice == 0 )//退出游戏
		{	
			exit(0);
		}
	}
	getchar();
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/523785.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[230513] TPO72 | 2022年托福阅读真题第1/36篇 | 10:45

Invading Algae 目录 Invading Algae 全文 题目 Paragraph 1 P1 段落大意 问题1 Paragraph 2 P2 段落大意 问题2 *问题3* Paragraph 3 P3 段落大意 问题4 Paragraph 4 P4 段落大意 Paragraph 5 P5 段落大意 *问题5* *问题6* 问题7 问题8 问题9…

【计算机组成原理】第二章 运算方法和运算器

系列文章目录 第一章 计算系统概论 第二章 运算方法和运算器 第三章 多层次的存储器 第四章 指令系统 第五章 中央处理器 第六章 总线系统 第七章 外围设备 第八章 输入输出系统 文章目录 系列文章目录第一章 计算系统概论 **第二章 运算方法和运算器** 第三章 多层次的存储器…

C++移动构造函数

一、背景 拷贝构造函数又分为浅拷贝和深拷贝&#xff1a; 浅拷贝&#xff1a;当类中有指针时&#xff0c;直接复制&#xff0c;会使多个指针指向同一块内存&#xff0c;导致重复析构 深拷贝&#xff1a;每次都是重新赋值一份&#xff0c;这种方法内存消耗较大 因此C就提供…

一觉醒来Chat gpt就被淘汰了

目录 什么是Auto GPT&#xff1f; 与其他语言生成模型相比&#xff0c;Auto GPT具有以下优点 Auto GPT的能力 Auto GPT的能力非常强大&#xff0c;它可以应用于各种文本生成场景&#xff0c;包括但不限于以下几个方面 Auto GPT的历史 马斯克说&#xff1a;“ChatGPT 好得吓…

【C++从0到王者】第三站:类和对象(中)赋值运算符重载

文章目录 一、运算符重载1.运算符重载的使用2.运算符重载的注意事项 二、赋值运算符重载1.复制拷贝与拷贝构造2.赋值运算符重载的格式3.赋值运算符重载的实现4.赋值运算符重载的注意事项 一、运算符重载 1.运算符重载的使用 当我们实现一个日期类的时候&#xff0c;我们有时候…

一个*泰NL18-20漏电保护器的拆解

一个*泰NL18-20漏电保护器的拆解&#xff0c;购买很早了&#xff0c;损坏&#xff0c;按test按钮无动作&#xff0c;昨天用一个雷*的63A漏保替换了。 NL18-20的电流只有20A。显然不适合现在的运用了。而且是无灭弧装置&#xff0c;所以分断能力有限。 好奇&#xff0c;拆开来看…

C++PrimerPlus第四章编程题

编程题 题目总览 编程题题解 题目要求输入四次信息&#xff0c;有四次交互的输入&#xff08;in&#xff09;&#xff0c;最后在一口气列举出来。同时对于firstname与lastname进行了拼接&#xff0c;而且对于输入的成绩进行降级操作。同时对于名字name的要求是可以输入多个单词…

使用Flink MySQL cdc分别sink到ES、Kafka、Hudi

环境说明 [flink-1.13.1-bin-scala_2.11.tgz](https://archive.apache.org/dist/flink/flink-1.13.1/flink-1.13.1-bin-scala_2.11.tgz)[hadoop-2.7.3.tar.gz](https://archive.apache.org/dist/hadoop/common/hadoop-2.7.3/hadoop-2.7.3.tar.gz)[flink-cdc-connectors](https:…

【Base64】前后端图片交互(2)

使用Base64去处理前后端图片交互 一、Base64编码介绍二、java.util.Base64 介绍源码分析编码译码 三、使用 Base64 前后端图片交互&#xff08;实操&#xff09;四、效果展示五、总结 绪论&#xff1a;在此之前小编发过一次前后端交互处理的方式&#xff1a;前后端图片交互的简…

深度学习之图像分类(三):VGGNet

系列文章目录 本专栏介绍基于深度学习进行图像识别的经典和前沿模型&#xff0c;将持续更新&#xff0c;包括不仅限于&#xff1a;AlexNet&#xff0c; ZFNet&#xff0c;VGG&#xff0c;GoogLeNet&#xff0c;ResNet&#xff0c;DenseNet&#xff0c;SENet&#xff0c;Mobile…

Windows磁盘空间不够,发现DriverStore文件夹特别大

正想安装一个新的VS2022&#xff0c;但是发现C盘的空间已经不足&#xff0c; 显示为红色了&#xff0c;这样不能安装。只好找一下C盘的空间为什么不足了&#xff0c;后来发现有一个目录特别大&#xff0c;这个目录就是DriverStore文件夹。由于电脑已经运行5年了&#xff0c;也…

Java的线程

介绍线程 线程是系统调度的最小单元&#xff0c;一个进程可以包含多个线程&#xff0c;线程是负责执行二进制指令的。 每个线程有自己的程序计数器、栈&#xff08;Stack&#xff09;、寄存器&#xff08;Register&#xff09;、本地存储&#xff08;Thread Local&#xff09…

Linux的基本权限

基本权限 1.权限的概念2.Linux上的用户分类2.1. 如何切换用户&#xff1f; 3.Linux的权限管理3.1. 文件访问者的分类&#xff08;人&#xff09;3.2.文件类型和访问权限&#xff08;文件属性&#xff09;3.2.1. 文件类型3.2.2. 基本权限 3.3. 文件权限值的表示方法3.3.1. 字符表…

Mac中idea快捷键(Keymap->macOS)

背景&#xff1a; mac&#xff1a;MacBook Pro&#xff08;13英寸&#xff0c;M2&#xff0c;2022年&#xff09; 系统版本&#xff1a;12.4 idea快捷键配置&#xff1a;本文快捷键设置基于macOS&#xff08;Keymap->macOS&#xff09; 一、常用快捷键 1.commandF 在当前…

java类和对象2

文章目录 一、Java实例变量和类变量二、Java实例方法和类方法三、Java方法重载四、Java this关键字五、Java包六、Java import语句七、Java访问权限八、Java基本类型的类封装九、Java jar文件总结 一、Java实例变量和类变量 实例变量和类变量的定义 在声明成员变量时&#xf…

微信云开发之云函数小例子

环境 微信开发者工具 Stable 1.06.2303220云开发控制台 v1.5.47 概述 云函数即在云端&#xff08;服务器端&#xff09;运行的函数&#xff0c;代码运行在云端Node.js中。我们可以使用云函数SDK中提供的数据库和存储API进行数据库和存储的操作。 云函数的独特优势在于与微信…

centos,搭建ftp服务;vsftpd

安装vsftpd 使用yum安装vsftpd&#xff1a; yum install -y vsftpd 配置vsftpd 编辑vsftpd配置文件&#xff1a; vim /etc/vsftpd/vsftpd.conf 以下是一些常见的配置项&#xff1a; anonymous_enableNO local_enableYES write_enableYES local_umask022 dirmessage_enableYE…

职场新人必备:10个写进备忘录的职场tips

作为职场新人&#xff0c;如何快速适应、获得成长和提升自己&#xff0c;是每个人都面临的挑战。在这个竞争激烈的职场中&#xff0c;拥有一些实用的职场tips&#xff0c;可以帮助你更好地应对各种挑战&#xff0c;获得成功。在本文中&#xff0c;我们将分享10个写进备忘录的职…

es8388 驱动详解

音频的基本框架 分为三个部分&#xff1a; 1&#xff09; 整体的绿框&#xff0c;为machine&#xff0c;例如你的PC等&#xff0c;负责图中 “线”的部分的关联&#xff0c;及黄色连接器的管理。也就是说不属于 paltform和codec管理的部分&#xff0c;都划归machine管理。 对应…

【Python socket】零基础也能轻松掌握的学习路线与参考资料

Python socket是Python程序语言中与网络编程密切相关的库之一&#xff0c;可以让程序员在网络世界中建立服务和客户端之间的连接。Python socket提供了一系列关键的概念和方法&#xff0c;让用户能够轻松地构建基于网络的程序&#xff0c;如基于TCP和UDP的应用程序。学习Python…