C或C++项目实战之贪吃蛇

2023-11-12

  1. 编译环境:VS2017(VS其他版本皆可),EasyX图形库
  2. 编程语言:c/c++
  3. 当前版本:snakeGame1.0
  4. 修改时间:2019/6/13
  5. 项目组成:
    5.1 头文件:snake\snake.h,
    5.2 源文件:main.cpp, snake\snake.cpp,
    5.3 资源文件:1.mp3, jinbi.jpg, jinbi.mp3, siwang.mp3,

一、头文件:snake\snake.h

#pragma once

/*
 * 贪吃蛇头文件
 */

#include <time.h>
#include <conio.h>
#include <graphics.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")

//蛇的状态,U:上; D:下; L:左; R:右.
constexpr auto U = 1;
constexpr auto D = 2;
constexpr auto L = 3;
constexpr auto R = 4;

//蛇类型
struct snake
{
	int				x, y;		//坐标
	int				color;		//颜色 
	struct snake*	next;		//下一节蛇身
};

//贪吃蛇游戏类
class snakeGame
{
public:
	//全局变量
	HWND hWnd;				//窗口句柄
	//IMAGE bk;				//背景图片变量
	int score;				//金币
	int add;				//单价
	int grade;				//难度等级
	int sleeptime;			//每次运行的时间间隔
	int endGamestatus;		//游戏结束的情况,1:撞到墙; 2:咬到自己; 3:主动退出游戏.
	int status;				//蛇的状态
	snake *head, *food;		//蛇头指针和食物指针
	snake *q;				//遍历蛇用到的指针
	IMAGE jinbi;			//金币图片

	//函数声明
	snakeGame(int score = 0, int add = 10, int grade = 1, 
		int sleeptime = 150, int endGamestatus = 0);	//拷贝构造函数
	void initGame();		//游戏初始化
	void drawGame();		//绘制游戏界面
	void ctolGame();		//游戏控制
	void initSnake();		//蛇身初始化
	void creatMap();		//创建地图
	void createFood();		//随机出现食物
	void snakeMove();		//蛇移动
	int endGame();			//游戏结束
	int snakeMain();		//贪吃蛇主函数
};

二、源文件:main.cpp

#include "snake\snake.h"

int main()
{
	snakeGame Snake;
	Snake.snakeMain();
	return 0;
}

三、源文件:snake\snake.cpp

#include "snake.h"

/*
 * 贪吃蛇游戏函数定义
 */

//拷贝构造函数
snakeGame::snakeGame(int score, int add, int grade, int sleeptime, int endGamestatus)
{
	this->score = score;
	this->add = add;
	this->grade = grade;
	this->sleeptime = sleeptime;
	this->endGamestatus = endGamestatus;
}

 //游戏初始化
void snakeGame::initGame()
{
	//创建地图
	creatMap();

	//蛇身初始化
	initSnake();

	//创建食物
	createFood();

	//加载背景音乐
	mciSendString("open snake\\1.mp3", NULL, NULL, NULL);
	//循环播放背景音乐
	mciSendString("play snake\\1.mp3 repeat", NULL, NULL, NULL);
	//加载金币图片
	loadimage(&jinbi, "snake\\jinbi.jpg", 20, 20, true);
}

//绘制游戏界面
void snakeGame::drawGame()
{
	char mon[32] = { NULL };		//金币
	char vel[32] = { NULL };		//速度
	char dif[32] = { NULL };		//困难
	char one[32] = { NULL };		//单价

	BeginBatchDraw();

	setfillcolor(RGB(195, 195, 195));		//边框颜色
	solidrectangle(0, 0, 680, 680);
	setfillcolor(RGB(128, 255, 0));			//背景颜色
	solidrectangle(20, 20, 660, 660);
	setfillcolor(RGB(0, 0, 255));			//网格颜色
	for (int i = 40; i <= 640; i += 20)
		for (int j = 40; j <= 640; j += 20)
			solidcircle(i, j, 1);

	//绘制蛇身
	q = head;
	setfillcolor(YELLOW);
	solidcircle(q->x + 10, q->y + 10, 10);	//蛇头 
	q = q->next;
	while (q != NULL)
	{
		setfillcolor(q->color);
		solidcircle(q->x + 10, q->y + 10, 10);	//蛇身  
		q = q->next;
	}

	//绘制食物
	putimage(food->x, food->y, &jinbi);

	//当前信息
	setfillcolor(RGB(0, 0, 0));		//信息区背景颜色
	solidrectangle(680, 0, 1020, 680);
	setbkcolor(RGB(0, 0, 0));		//字体背景颜色
	_itoa_s(score, mon, 10);
	_itoa_s((10000 / sleeptime), vel, 10);
	_itoa_s((300 - sleeptime) / 30, dif, 10);
	_itoa_s(add, one, 10);
	setcolor(RGB(255, 255, 255));	//字体颜色
	outtextxy(730, 10, "金币:"); outtextxy(775, 10, mon);
	outtextxy(730, 30, "速度:"); outtextxy(775, 30, vel);
	outtextxy(730, 60, "难度:"); outtextxy(775, 60, dif);
	outtextxy(730, 80, "单价:"); outtextxy(775, 80, one);

	//说明界面
	outtextxy(700, 150, "不能穿墙,不能咬到自己!");
	outtextxy(700, 200, "控制方向:");
	outtextxy(800, 200, "↑↓←→");
	outtextxy(700, 250, "加速:F1");
	outtextxy(780, 250, "减速:F2");
	outtextxy(700, 270, "退出:Esc");
	outtextxy(780, 270, "暂停:Space");
	EndBatchDraw();
}

//游戏控制
void snakeGame::ctolGame()
{
	if (GetAsyncKeyState(VK_UP) && status != D)
	{	//上
		status = U;
	}
	else if (GetAsyncKeyState(VK_DOWN) && status != U)
	{	//下
		status = D;
	}
	else if (GetAsyncKeyState(VK_LEFT) && status != R)
	{	//左
		status = L;
	}
	else if (GetAsyncKeyState(VK_RIGHT) && status != L)
	{	//右
		status = R;
	}
	else if (GetAsyncKeyState(VK_SPACE))
	{	//暂停
		while (1)
		{
			Sleep(300);
			if (GetAsyncKeyState(VK_SPACE))
			{	//再次按空格键退出死循环
				break;
			}
		}
	}
	else if (GetAsyncKeyState(VK_ESCAPE))
	{	//退出
		while (1)
		{	//松手检测
			if (!GetAsyncKeyState(VK_ESCAPE))
			{	//松开退出游戏
				endGamestatus = 3;
				endGame();
				break;
			}
		}

	}
	else if (GetAsyncKeyState(VK_F1))
	{	//加速
		while (1)
		{
			if (!GetAsyncKeyState(VK_F1))
			{	//松手检测
				if (sleeptime > 60)
				{	//速度不能太快
					sleeptime = sleeptime - 30;
					add = add + 2;
				}
				break;
			}
		}
	}
	else if (GetAsyncKeyState(VK_F2))
	{	//减速
		while (1)
		{
			if (!GetAsyncKeyState(VK_F2))
			{	//松手检测
				if (sleeptime < 270)
				{	//单价不能小于0
					sleeptime = sleeptime + 30;
					add = add - 2;
				}
				break;
			}
		}

	}
	Sleep(sleeptime);
	snakeMove();
}

//蛇身初始化
void snakeGame::initSnake()
{
	snake *tail;		//蛇尾指针
	int i;

	//从蛇尾开始,头插法,以x,y设定开始的位置
	tail = (snake*)malloc(sizeof(snake));
	tail->x = 200;
	tail->y = 40;
	tail->color = RGB(255, 0, 0);
	tail->next = NULL;

	//初始长度为4
	for (i = 1; i <= 4; i++)
	{
		head = (snake*)malloc(sizeof(snake));
		head->next = tail;
		head->x = 200 + 20 * i;
		head->y = 40;
		head->color = RGB(255, 0, 0);
		tail = head;
	}

	//蛇移动方向向右
	status = R;
}

//创建地图
void snakeGame::creatMap()
{
	hWnd = initgraph(1020, 680);	//做窗口

	//欢迎界面
	MessageBox(hWnd, "欢迎来到贪吃蛇游戏!", "帅气的龙少提示你:", MB_OK);
	outtextxy(320, 260, "用↑.↓.←.→分别控制蛇的移动, F1 为加速,F2为减速");
	outtextxy(360, 280, "加速将能得到更高的分数");
	getch();
	cleardevice();
}

//随机出现食物
void snakeGame::createFood()
{
	snake *food_1;

	//为了防止每次产生的随机数相同,种子设置为time
	srand((unsigned)time(NULL));

	//创建食物
	food_1 = (snake*)malloc(sizeof(snake));
	if (food_1 == NULL) return createFood();

	do
	{	//保证其为10的倍数,使得食物能与蛇头对其
		food_1->x = rand() % 620 + 20;
		food_1->y = rand() % 620 + 20;
	} while ((food_1->x % 20 != 0) || (food_1->y % 20 != 0));
	food_1->color = RGB(rand() % 256, rand() % 256, rand() % 256);

	q = head;
	while (q)
	{
		if (q->x == food_1->x && q->y == food_1->y)
		{	//判断蛇身是否与食物重合
			free(food_1);
			createFood();
			return;
		}
		q = q->next;
	}

	//加载食物
	food = food_1;
}

//蛇前进,上U,下D,左L,右R
void snakeGame::snakeMove()
{
	snake * nexthead = (snake*)malloc(sizeof(snake));
	if (nexthead == NULL) return snakeMove();

	if (status == U)
	{
		nexthead->x = head->x;
		nexthead->y = head->y - 20;
		nexthead->color = RGB(255, 0, 0);
		if (nexthead->x == food->x && nexthead->y == food->y)//如果下一个有食物//
		{
			mciSendString("open snake\\jinbi.mp3 alias media", NULL, NULL, NULL);
			mciSendString("set media time format milliseconds", NULL, NULL, NULL);
			mciSendString("play media from 0", NULL, NULL, NULL);
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q != NULL)
			{
				q = q->next;
			}
			score = score + add;
			createFood();
		}
		else                                               //如果没有食物//
		{
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q->next->next != NULL)
			{
				q = q->next;
			}
			free(q->next);
			q->next = NULL;
		}
	}
	if (status == D)
	{
		nexthead->x = head->x;
		nexthead->y = head->y + 20;
		nexthead->color = RGB(255, 0, 0);
		if (nexthead->x == food->x && nexthead->y == food->y)  //有食物
		{
			mciSendString("open snake\\jinbi.mp3 alias media", NULL, NULL, NULL);
			mciSendString("set media time format milliseconds", NULL, NULL, NULL);
			mciSendString("play media from 0", NULL, NULL, NULL);
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q != NULL)
			{
				q = q->next;
			}
			score = score + add;
			createFood();
		}
		else                               //没有食物
		{
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q->next->next != NULL)
			{
				q = q->next;
			}
			free(q->next);
			q->next = NULL;
		}
	}
	if (status == L)
	{
		nexthead->x = head->x - 20;
		nexthead->y = head->y;
		nexthead->color = RGB(255, 0, 0);
		if (nexthead->x == food->x && nexthead->y == food->y)//有食物
		{
			mciSendString("open snake\\jinbi.mp3 alias media", NULL, NULL, NULL);
			mciSendString("set media time format milliseconds", NULL, NULL, NULL);
			mciSendString("play media from 0", NULL, NULL, NULL);
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q != NULL)
			{
				q = q->next;
			}
			score = score + add;
			createFood();
		}
		else                                //没有食物
		{
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q->next->next != NULL)
			{
				q = q->next;
			}
			free(q->next);
			q->next = NULL;
		}
	}
	if (status == R)
	{
		nexthead->x = head->x + 20;
		nexthead->y = head->y;
		nexthead->color = RGB(255, 0, 0);
		if (nexthead->x == food->x && nexthead->y == food->y)//有食物
		{
			mciSendString("open snake\\jinbi.mp3 alias media", NULL, NULL, NULL);
			mciSendString("set media time format milliseconds", NULL, NULL, NULL);
			mciSendString("play media from 0", NULL, NULL, NULL);
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q != NULL)
			{
				q = q->next;
			}
			score = score + add;
			createFood();
		}
		else                                         //没有食物
		{
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q->next->next != NULL)
			{
				q = q->next;
			}
			free(q->next);
			q->next = NULL;
		}
	}

	//判断蛇是否会咬到自己
	snake *self;
	self = head->next;
	while (self)
	{	//蛇自己指针遍历
		if (self->x == head->x && self->y == head->y)
		{
			endGamestatus = 2;
			endGame();
		}
		self = self->next;
	}

	if (head->x < 20 || head->x > 640 || head->y < 20 || head->y > 640)
	{	//不能穿墙
		endGamestatus = 1;
		endGame();
	}
}

//结束游戏
int snakeGame::endGame()
{
	mciSendString("stop snake\\1.mp3", NULL, NULL, NULL);
	mciSendString("open snake\\siwang.mp3", NULL, NULL, NULL);
	mciSendString("play snake\\siwang.mp3", NULL, NULL, NULL);
	switch (endGamestatus)
	{
	case 1: MessageBox(hWnd, "对不起,您撞到墙了,结束游戏!", "帅气的龙少提示你:", NULL); break;
	case 2: MessageBox(hWnd, "对不起,您咬到自己了,结束游戏!", "帅气的龙少提示你:", NULL); break;
	case 3: MessageBox(hWnd, "您的游戏已经结束了!", "帅气的龙少提示你:", NULL); break;
	}

	closegraph();//关闭图形界面
	exit(0);//退出
}

//贪吃蛇游戏主函数
int snakeGame::snakeMain()
{
	initGame();

	while (1)
	{
		drawGame();
		ctolGame();
	}

	return 0;
}

四、资源文件

1、1.mp3

百度网盘提取码:xpdm

2、jinbi.jpg

百度网盘提取码:pq7b

3、jinbi.mp3

百度网盘提取码:sow8

4、siwang.mp3

百度网盘提取码:xc1n

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C或C++项目实战之贪吃蛇 的相关文章

  • vs2017调用dll文件提示“LNK2019 无法解析的外部符号 “__declspec(dllimport) public: __cdecl ”解决方法

    如题 xff0c 通过vs2017定义的接口生成了dll文件并调用测试结果报错无法解析的外部符号 解决方法 xff1a 在C C 43 43 目录中包含dll对应的头文件 xff0c 库目录包含dll文件 xff0c 如下图所示 然后在链接
  • 【项目实战】spring boot中使用webSocket

    spring boot中使用webSocket 文章目录 spring boot中使用webSocket引入依赖支持配置类接口类前端连接方式前端信息发送方式 引入依赖 需要在基础的spring boot web项目项目中添加下面一个依赖 x
  • win10系统vs2017+1060配置CUDA安装tensorflow-gpu

    笔者最开始安装的是推荐的cuda10后来虽然vs实例能成功运行 xff0c 但是tf的import还是报错 xff0c 后来安装的9 2 xff0c 运行无误 xff0c 各下载链接在文后可自行查看 检查显卡驱动是否为最新版本 非常重要 安
  • LVGL——PC模拟器仿真模拟+VS2017

    目录 LVGL介绍移植说明资源下载环境搭建编译运行 本文只针对当时的LVGL v7 xff0c LVGL迭代过程中变化较大 xff0c 部分接口有可能做调整 本文仅供参考 LVGL介绍 官网 xff1a https lvgl io 官方在线
  • 【无标题】 libtorch C++ vs2017 debug模式可以正确加载模型,release模式错误

    转发 xff1a libtorch C 43 43 vs2017 debug模式可以正确加载模型 xff0c release模式错误 https blog csdn net weixin 43862688 article details 1
  • VS2017使用libcurl,链接错误

    当使用libcurl库出现链接错误 xff0c 如下 1 gt WebSocketMsg obj error LNK2001 unresolved external symbol imp curl global init 1 gt WebS
  • 软件测试电商项目实战(写进简历没问题)

    前言 说实话 在找项目的过程中 我下载过 甚至付费下载过 N多个项目 联系过很多项目的作者 但是绝大部分项目 在我看来 并不适合你拿来练习 它们或多或少都存在着 问题 比如 1 大部分项目是web项目 很难找到app项目 特别是有app安装
  • Linux(CentOS)安装Zookeeper

    前置环境是装好Java环境 然后去zookeeper官网下载 http mirror bit edu cn apache zookeeper 下载好后把压缩包上传到服务器 去到服务器地下解压 tar zxvf apache zookeepe
  • 【C++】教你如何在中秋节给家人们画一个星空

    前言 将至中秋 想必大家都想给自己的家人们一个惊喜吧 今天就手把手地教大家如何用C 和Easyx画一个星空 效果图 一 准备Easyx 首先我们要前往Easyx官网下载安装程序 下载完成后打开程序 并点击 下一步 随后选择你的编辑器并点击
  • SourceTree提交合并流程

    先写提交流程 缓存 提交 获取 拉取 解决冲突 提交 推送 下面和多分支开发合并 先保证 拉取到最新的 把项目切到主分支 鼠标点到被合并分支 右击选中 合并 到当前分支
  • 【机器视觉】——裂纹检测笔记

    目录 传统算法处理裂缝的基本思路 第一种思路 第二种思路 第三种思路 CPP代码 halcon代码 python代码 Matlab代码 深度学习缺陷检测 裂缝检测文献 传统算法处理裂缝的基本思路 第一种思路 1 先转换彩色图为灰度图 2 进
  • MySql 根据身份证号来判别所属省份年龄及性别

    一 背景 新项目要从别的系统迁移用户表信息 老的用户表里的数据有很多不规范的数据 需要通过表里的身份证号获取用户的省份 年龄 性别 二 获取方式 1 通过身份证号获取省份 SELECT CASE LEFT sfzh 2 WHEN 11 TH
  • 基于Tensorflow搭建卷积神经网络CNN(花卉识别)保姆及级教程

    项目介绍 TensorFlow2 X 搭建卷积神经网络 CNN 实现人脸识别 可以识别自己的人脸哦 搭建的卷积神经网络是类似VGG的结构 卷积层与池化层反复堆叠 然后经过全连接层 最后用softmax映射为每个类别的概率 概率最大的即为识别
  • [华为云云服务器评测] 华为云耀云服务器 Java、node环境配置

    系列文章目录 第一章 linux实战 华为云耀云服务器L实例 Java node环境配置 文章目录 系列文章目录 前言 一 任务拆解 二 修改密码 三 配置安全规则 四 远程登录并更新apt 五 安装 配置JDK环境 5 1 安装openj
  • 基于vspd DLL二次开发的虚拟串口工具

    最近项目需要 早期使用com0com做虚拟串口工具的二次开发 但是发现在系统兼容性上存在很多的问题 后来改用vspd 的免费dll做开发 在稳定性和兼容性上确实提升了很多 功能调用非常简单 可以参照如下的demo 库文件的话自行下载和链接
  • Mysql 实战之——读写分离方案

    Linux环境 Centos 6 8 64 bit Mysql 版本 5 1 7 一 准备工作 部署Mysql主从复制 二 使用Amoeba数据库代理来实现读写分离 Amoeba作为数据库代理 以中间件的形式存在 拓扑图如下所示 Amoeb
  • C或C++项目实战之贪吃蛇

    编译环境 VS2017 VS其他版本皆可 EasyX图形库 编程语言 c c 当前版本 snakeGame1 0 修改时间 2019 6 13 项目组成 5 1 头文件 snake snake h 5 2 源文件 main cpp snak
  • 优化(2)——射线检测基础,合批原理

    射线检测 射线响应的方法 首先获取到canvas下所有graphic组件 当前的ui元素是否接收射线 第一个if判断是否绘制到屏幕上 是否勾选RaycastTarget接受射线 是否进行了剔除 第二个if判断点击是否在当前对象上 第三个判断
  • 数据挖掘案例实战:利用LDA主题模型提取京东评论数据(二)

    泰迪智能科技 数据挖掘平台 TipDM数据挖掘平台 最新推出的数据挖掘实战专栏 专栏将数据挖掘理论与项目案例实践相结合 可以让大家获得真实的数据挖掘学习与实践环境 更快 更好的学习数据挖掘知识与积累职业经验 专栏中每四篇文章为一个完整的数据
  • Vue项目的部署(服务器)

    Vue项目的部署 服务器 前几天帮朋友写了一个可以动态查看地点温度的前端项目 目前已经部署上线了 访问链接点这里 服务器是朋友的 倒时候打不开会很正常 说不定又使用服务器玩大数据项目去了 效果图 图一 图二 当然 温度也都是实时跟新的 而且

随机推荐