前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >贪吃蛇小游戏

贪吃蛇小游戏

作者头像
大忽悠爱学习
发布2021-03-04 10:34:12
4160
发布2021-03-04 10:34:12
举报
文章被收录于专栏:c++与qt学习

游戏截图:

在这里插入图片描述
在这里插入图片描述

源码如下:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<Windows.h>
#include<ctime>
#include<conio.h>
enum { height = 30, width = 60 };
//蛇的偏移量
//全局函数--默认值为0
int offset_x;
int offset_y;
//记录蛇尾的位置---方便将移动后的蛇尾变成空格
int end_x;
int end_y;
//检测头尾是否构成循环,一旦构成循环,那么因为蛇头先出现在蛇尾的位置,覆盖掉原来的蛇尾,然后在更新后,把蛇尾的位置变成了空格,造成蛇头消失的bug
int isRool;
//无键盘按下,默认向右移动
char ch = 'd';
//记录前一次按下的键
char prveCh = 'd';
//得分
int score = 0;
//刷新时间
int sleepTime = 300;
//当前速度
int speed = 300;
struct Body 
{
	//蛇身的坐标
	int x;
	int y;
};
struct Snake 
{
	//结构体嵌套结构体
	//蛇身最大长度
	struct Body body[(width-2)*(height-2)];
	//蛇的长度
	int size;
}snake;//定义一个全局变量
struct Food 
{
	int x;
	int y;
}food;
//画墙
void initWall();
//光标定位
void gotoxy(int x, int y);
//隐藏光标
VOID HideConsoleCursor();
//初始化蛇
void initSnake();
//初始化食物
void initFood();
//更新显示
void upgrate();
//实现蛇的移动
void moveSnake();
//蛇吃到食物
void snakeEatFood();
//死亡检测
void checkDead();
//游戏结束  1是撞墙   2是撞自身
void gameOver(int mode);
//设置控制台输出文本颜色
void setTextColor(int num);
int main()
{
	HideConsoleCursor();
	initWall();
	initSnake();
	initFood();
	//当蛇身碰到墙,停止前进
	while (snake.body[0].x>=1&& snake.body[0].x<=58&& snake.body[0].y>=1&& snake.body[0].y<=28)
	{
		checkDead();
		moveSnake();
		upgrate();
		snakeEatFood();
		Sleep(sleepTime);
	}
	gameOver(1);
	return 0;
}
//画墙
void initWall()
{
	//画墙---看做一个二维数组--行和列
	for (int i = 0; i < height; i++)
	{
		for (int j = 0; j < width; j++)
		{
			if (i == 0 || j == 0 || i == height - 1 || j == width - 1)
			{
				printf("*");
			}
			else {
				printf(" ");
			}
		}
		if(i==5)
		printf("                   贪吃蛇大作战");
		if(i==8)
		printf("                     AWSD操作");
		if (i == 11)
		printf("                  游戏制作人:大忽悠");
		printf("\n");
	}
}
//光标定位
void gotoxy(int x, int y)
{
	
	COORD coord = { x,y };
	//1.获取窗口输出句柄
	HANDLE handle=GetStdHandle ( STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(handle, coord);
}
//隐藏光标
VOID HideConsoleCursor() 
{
	CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),
		&cursor_info);
}
//初始化蛇
void initSnake() 
{
    //设计初始化蛇身为3段
	snake.size = 3;
	//设置初始的蛇位置
	snake.body[2].x = width/2 - 2;
	snake.body[2].y = height/2;
	snake.body[1].x = width/2 - 1;
	snake.body[1].y = height/2 ;
	snake.body[0].x = width/2 ;
	snake.body[0].y = height/2;
}
//初始化食物
void initFood()
{
	//播撒随机数种子
	srand((size_t)time(NULL));
	while (1)
	{
		//判断食物是否与身体重合
		bool flag = true;
		food.x = rand() % (width - 2) + 1; //x轴上食物出现的范围:1~58
		food.y = rand() % (height - 2) + 1;//y轴上食物出现的随机范围:1~28
		//判断每次食物的出现坐标是否与蛇的身体有重合,如果有重合,让食物重新再生成一次,直到不与身体重合
		for (int i = 0; i < snake.size; i++)
		{
			//当食物与蛇身一节身体产生重合时就退出后续身体比对,让食物重新生成一次
			if (snake.body[i].x == food.x && snake.body[i].y == food.y)
			{
				flag = false;
				break;
			}
		}
		//如果没有重合,那么此次食物生成没有问题,不用重新生成
		if (flag == true)
		{
			break;
		}
	}
}
//更新显示
void upgrate()
{
	for (int i = 0; i < snake.size; i++)
	{
		//将光标移动
		gotoxy(snake.body[i].x, snake.body[i].y);
		if (i == 0)
		{
			printf("@");
		}
		else
		{
			printf("#");
		}
			 
	}
	gotoxy(food.x, food.y);
	printf("X");
	if (end_x != 0 && end_y != 0)
	{
		gotoxy(end_x, end_y);
		printf(" ");
	}
	//如果构成循环,就将被空格的蛇头,重新显示出来
	if (isRool)
	{
		gotoxy(snake.body[0].x, snake.body[0].y);
		printf("@");
	}
	//显示分数
	gotoxy(82,14);
	printf("分数:%d", score);
	gotoxy(80, 17);
	printf("当前速度:%d", speed);

}
//实现蛇的移动
void moveSnake()
{
	//如果有键盘按下,默认值失效
	if (_kbhit())//有键盘按下为真,没键盘按下没假
	{
		ch = _getch();
	 }
	//解决按下a再按下d,蛇直接死亡的冲突的问题
	if (prveCh == 'd' && ch == 'a' || prveCh == 'w' && ch == 's' || prveCh == 'a' && ch == 'd' || prveCh == 's' && ch == 'w')
	{
		ch = prveCh;
	}
	else 
	{
		prveCh = ch;
	}
	//键盘按下,改变偏移量
	switch (ch)
	{
	case 'a':
		offset_x = -1;
		offset_y = 0;
		break;
	case 'd':
		offset_x = 1;
		offset_y = 0;
		break;
	case 'w':
		offset_x = 0;
		offset_y = -1;
		break;
	case 's':
		offset_x = 0;
		offset_y = 1;
		break;
	default:
		break;
	}
	//记录蛇尾的位置
	end_x = snake.body[snake.size-1].x;
	end_y = snake.body[snake.size - 1].y;
	//要从尾节点开始往前移动,不然先移动走了蛇头,蛇头后的节点就找不到蛇头了
	for (int i =snake.size-1;i>0;i--)
	{
		//从蛇尾开始一个个往前移动,到蛇头结束
		snake.body[i].x = snake.body[i - 1]. x;
		snake.body[i].y = snake.body[i - 1].y;
	}
	//移动蛇头
	snake.body[0].x += offset_x;
	snake.body[0].y += offset_y;
	//判断是否构成循环
	if (snake.body[0].x == end_x && snake.body[0].y == end_y)
	{
		isRool = 1;
	}
	else
	{
		isRool = 0;
	}
}
//蛇吃到食物
void snakeEatFood()
{
	//蛇头碰到食物
	if (snake.body[0].x == food.x && snake.body[0].y == food.y)
	{
		//蛇身长度加1
		snake.size++;
		//食物位置重新初始化
		initFood();
		//每次吃到食物,分数加100
		score += 100;
		//每次吃到食物,刷新时间减少10
		sleepTime-= 10;
		//当前速度加10
		speed += 10;
	}
}
//死亡检测
void checkDead()
{
	//两种情况
	//1.撞墙 2.撞自身

	//2.撞自身
	//检测蛇的身体是否与蛇身相碰撞
	for (int i = 1; i < snake.size ; i++)
	{
		if (snake.body[0].x == snake.body[i].x && snake.body[0].y == snake.body[i].y)
		{
			gameOver(2);
		}
	}
} 
//游戏结束  1是撞墙   2是撞自身
void gameOver(int mode)
{
	if (mode == 2)
	{
		gotoxy(snake.body[0].x, snake.body[0].y);
		printf(" ");
		system("cls");
		gotoxy(45, 10);
		printf("游戏结束,大侠请重新来过\n");
		gotoxy(45, 12);
		system("pause");
		exit(0);
	}
	//撞墙
	system("cls");
	gotoxy(45, 10);
	printf("游戏结束,大侠请重新来过\n");
	gotoxy(45, 12);
	system("pause");
	exit(0);
}
//设置控制台输出文本颜色
void setTextColor(int num)
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(handle, num);
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/02/24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 游戏截图:
  • 源码如下:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档