通过C语言设计的贪吃蛇游戏(控制台终端)

一、项目介绍

当前通过控制台终端实现一个贪吃蛇小游戏,实现游戏的绘制、更新、控制等功能。

二、实现效果

image-20230618211315514

image-20230618211408842

三、完整代码

下面贴出的代码在Windows系统上编译运行,需要使用conio.h头文件中的getch()函数来获取键盘输入,用于控制蛇的移动。可以通过按下’w’、‘s’、‘a’、'd’四个键来分别控制蛇的向上、向下、向左、向右移动。同时还有一个暂停函数Pause(),用于控制蛇的移动速度,可以根据需要调整暂停时间。

设计思路:

程序定义了一些常量,包括游戏界面的宽度和高度、不同状态下的符号表示等,并在全局变量中定义了蛇头、蛇身、食物等的位置、得分、长度、行进方向等参数。同时还定义了一个二维字符数组board,用于表示整个游戏界面。

在InitGame()函数中进行游戏初始化,设置游戏界面的边框、蛇头、蛇身、随机生成食物等操作。

DrawGame()函数用于绘制游戏画面,将board数组中的字符逐行输出,并在末尾输出得分。UpdateGame()函数用于更新游戏状态,包括蛇的移动、游戏结束判断等。CheckGameOver()函数用于检查游戏是否结束,包括墙壁碰撞、蛇身碰撞、得分达到上限等情况。GenerateFood()函数用于随机生成食物位置,调用rand()函数获取随机数并进行判断。Move()函数用于蛇的移动,根据当前行进方向进行移动。Control()函数用于用户操作,读取键盘输入并更新蛇的行进方向。Pause()函数用于控制游戏速度,通过调用Sleep()函数控制暂停时间。GameOver()函数用于输出最终得分和游戏结束信息,并直接退出程序。

image-20230618211229060

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>  //需要使用getch()函数
#include <time.h>   //需要使用time()函数
#include <Windows.h>


#define WIDTH 40    //游戏界面宽度
#define HEIGHT 20   //游戏界面高度

//定义符号常量,表示各种不同的状态
#define BLANK ' '   //空白
#define WALL '*'    //墙壁
#define SNAKEHEAD '@'  //蛇头
#define SNAKEBODY 'o'  //蛇身
#define FOOD '$'    //食物

//定义坐标结构体
struct Position
{
	int x;    //横坐标
	int y;    //纵坐标
};

//定义枚举类型,表示游戏状态
enum GameState
{
	Over = -1,   //游戏结束
	Running = 0, //游戏进行中
	Win = 1      //游戏胜利
};

int score = 0;   //得分
struct Position head;   //蛇头位置
struct Position body[WIDTH * HEIGHT];  //蛇身位置
struct Position food;   //食物位置
char board[WIDTH][HEIGHT];   //游戏界面
int length = 3;     //蛇身长度,初始为3
int direction = 0;  //蛇的行进方向,0表示向右,1表示向下,2表示向左,3表示向上

//函数声明
void InitGame();    //初始化游戏界面和蛇的初始位置
void DrawGame();    //绘制游戏画面
void UpdateGame();  //更新游戏状态
enum GameState CheckGameOver();  //检查游戏是否结束
void GenerateFood();   //生成随机食物
void Move();     //蛇的移动
void Control();  //用户操作,控制蛇的移动
void Pause();    //游戏暂停
void GameOver(); //游戏结束

int main()
{
	srand(time(NULL));   //用当前时间作为随机数种子,使每次运行的随机食物位置不同
	InitGame();   //初始化游戏
	DrawGame();   //绘制游戏画面
	while (1)
	{
		UpdateGame();  //更新游戏
		DrawGame();    //绘制游戏画面
		Control();     //用户操作,控制蛇的移动
		Pause();       //游戏暂停     
	}
	return 0;
}

//初始化游戏界面和蛇的初始位置
void InitGame()
{
	for (int i = 0; i < WIDTH; i++)
	{
		for (int j = 0; j < HEIGHT; j++)
		{
			if (i == 0 || j == 0 || i == WIDTH - 1 || j == HEIGHT - 1) //设置墙壁
				board[i][j] = WALL;
			else
				board[i][j] = BLANK;    //其他为空白
		}
	}

	//初始化蛇的位置,由一个蛇头和两节身体组成,初始位置在游戏界面的中心
	head.x = WIDTH / 2;
	head.y = HEIGHT / 2;
	board[head.x][head.y] = SNAKEHEAD;

	body[0].x = head.x - 1;
	body[0].y = head.y;
	board[body[0].x][body[0].y] = SNAKEBODY;

	body[1].x = head.x - 2;
	body[1].y = head.y;
	board[body[1].x][body[1].y] = SNAKEBODY;

	GenerateFood();   //生成随机食物
}

//绘制游戏画面
void DrawGame()
{
	system("cls");   //清屏,避免前一帧的内容残留

	for (int i = 0; i < HEIGHT; i++)
	{
		for (int j = 0; j < WIDTH; j++)
		{
			printf("%c", board[j][i]);  //输出一个字符
		}
		printf("\n");    //每行输出完后,换行
	}

	printf("Score: %d\n", score);   //输出得分
}

//更新游戏状态
void UpdateGame()
{
	Move();   //蛇的移动
	enum GameState state = CheckGameOver();  //检查游戏是否结束
	if (state != Running)  //如果游戏结束,则进行相应操作
	{
		GameOver();
	}
}

//检查游戏是否结束
enum GameState CheckGameOver()
{
	//蛇头碰到墙壁,游戏结束
	if (board[head.x][head.y] == WALL)
		return Over;

	//蛇头碰到蛇身,游戏结束
	for (int i = 0; i < length; i++)
	{
		if (head.x == body[i].x && head.y == body[i].y)
			return Over;
	}

	//吃到食物后,更新分数和蛇的长度,并生成新的食物
	if (head.x == food.x && head.y == food.y)
	{
		score += 10;
		length++;
		GenerateFood();
	}

	//蛇的长度达到游戏界面总格子数减去墙壁的个数,也就是蛇填满游戏界面,游戏胜利
	if (length == (WIDTH - 2) * (HEIGHT - 2) - 4)
		return Win;

	return Running;   //游戏继续进行
}

//生成随机食物
void GenerateFood()
{
	int x, y;
	do
	{
		x = rand() % (WIDTH - 2) + 1;    //随机x坐标,排除在边框上的墙壁位置
		y = rand() % (HEIGHT - 2) + 1;   //随机y坐标,排除在边框上的墙壁位置
	} while (board[x][y] != BLANK);   //如果随机到的位置不为空白,则重新随机
	food.x = x;
	food.y = y;
	board[x][y] = FOOD;  //在随机位置生成食物
}

//蛇的移动
void Move()
{
	//更新蛇身的位置,从后往前移动
	for (int i = length - 1; i > 0; i--)
	{
		body[i].x = body[i - 1].x;
		body[i].y = body[i - 1].y;
		board[body[i].x][body[i].y] = SNAKEBODY;
	}

	//更新蛇头的位置
	switch (direction)   //根据蛇头行进方向进行移动
	{
	case 0:  //向右
		head.x++;
		break;
	case 1:  //向下
		head.y++;
		break;
	case 2:  //向左
		head.x--;
		break;
	case 3:  //向上
		head.y--;
		break;
	}
	board[head.x][head.y] = SNAKEHEAD;   //更新蛇头位置
	board[body[length - 1].x][body[length - 1].y] = BLANK;  //清除蛇尾
}

//用户操作,控制蛇的移动
void Control()
{
	if (kbhit())   //如果有按键按下
	{
		char ch = getch();   //获取按键字符
		switch (ch)
		{
		case 'w':
			if (direction != 1)  //避免蛇头掉头
				direction = 3;
			break;
		case 's':
			if (direction != 3)
				direction = 1;
			break;
		case 'a':
			if (direction != 0)
				direction = 2;
			break;
		case 'd':
			if (direction != 2)
				direction = 0;
			break;
		case 'q':
			GameOver();  //按下'q'键退出游戏
			break;
		}
	}
}

//游戏暂停
void Pause()
{
	Sleep(150);   //每次循环暂停一段时间,控制蛇的移动速度
}

//游戏结束
void GameOver()
{
	system("cls");   //清屏,输出最终得分和游戏结束信息
	printf("Game over!\n");
	printf("Your score: %d\n", score);
	exit(0);  //直接退出程序
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

word转pdf两种方式(免费+收费)

一、免费方式 优点&#xff1a;1、免费&#xff1b;2、在众多免费中挑选出的转换效果相对较好&#xff0c;并且不用像openOffice那样安装服务 缺点&#xff1a;1、对字体支持没有很好&#xff0c;需要安装字体库或者使用宋体&#xff08;对宋体支持很好&#xff09;2、对于使…

如何使用大模型处理生活繁琐的工作

如果每封电子邮件、每个带有订单、发票、投诉、录用请求或工作申请的 PDF 都可以翻译成机器可读的数据&#xff0c;会怎样&#xff1f;然后可以由 ERP / CRM / LMS / TMS 自动处理吗&#xff1f;无需编程特殊接口。 听起来很神奇&#xff1f;它确实有一些魔力。但最近已成为可…

PtahDAO:全球首个DAO治理资产信托计划的金融平台

金融科技是当今世界最具创新力和影响力的领域之一&#xff0c;区块链技术作为金融科技的核心驱动力&#xff0c;正在颠覆传统的金融模式&#xff0c;为全球用户提供更加普惠、便捷、安全的金融服务。在这个变革的浪潮中&#xff0c;PtahDAO&#xff08;普塔道&#xff09;作为全…

系列二、IOC基本概念和底层原理

一、IOC基本概念 控制反转&#xff1a;把对象创建和对象之间的调用过程&#xff0c;交给Spring进行管理&#xff1b;使用IOC的目的&#xff1a;减低耦合度&#xff1b; 二、IOC底层原理 xml解析 工厂模式 反射 2.1、图解IOC底层原理 # 第一步&#xff1a;xml配置文件&am…

K8s的详细介绍

1.编写yaml文件的方式 2.yaml里面的内容介绍 Pod实现机制&#xff1a;&#xff08;1&#xff09;共享网络&#xff08;2&#xff09;共享存储 共享网络:通过Pause容器&#xff0c;把其他业务容器加入到Pause容器里面&#xff0c;让所有业务容器在同一个名称空间中&#xff0c;…

【CHI】(六)独占访问

AMBA5 CHI Architecture Specification IssueF 1. overview 独占访问的原则是&#xff0c;执行独占序列的逻辑处理器&#xff08;LP&#xff09;执行以下操作&#xff1a; 对一个地址执行exclusive load。计算要存储到该位置的新值。对该地址进行exclusive store。 支持对可…

mysql-数据库-创建列表

一.创建列表 1..首先&#xff0c;进入mysql数据库 -->mysql -uroot -p 2. 其次&#xff0c;mysql默认的数据库类型为mydb&#xff0c;这时候&#xff0c;就得查看现在使用的类型 mysql> select database(); 3. 如果创建的类型不同&#xff0c;则使用create database …

Vue如何定义router-link的颜色样式

今天在使用Vue的时候碰到了想改样式却改不了的情况 <ul> <li>xxxxx</li> <li><router-link to"/wisdom" active-class"ative">xxxxx</router-link></li> <li><router-link to"/MyLogin" act…

【宝藏系列】几款好用的 Spring Boot 内置工具类

【宝藏系列】几款好用的 Spring Boot 内置工具类 文章目录 【宝藏系列】几款好用的 Spring Boot 内置工具类断言对象字符串集合文件资源IO 流反射AOP&#x1f349;文末推荐【深入浅出Java虚拟机】 断言 断言是一个逻辑判断&#xff0c;用于检查不应该发生的情况 Assert 关键字…

【深度学习】Transformer,Self-Attention,Multi-Head Attention

必读文章&#xff1a; https://blog.csdn.net/qq_37541097/article/details/117691873 论文名&#xff1a;Attention Is All You Need 文章目录 1、Self-Attention 自注意力机制2、Multi-Head Attention 1、Self-Attention 自注意力机制 Query&#xff08;Q&#xff09;表示当…

SpringBoot3 整合Prometheus + Grafana

通过Prometheus Grafana对线上应用进行观测、监控、预警… 健康状况【组件状态、存活状态】Health运行指标【cpu、内存、垃圾回收、吞吐量、响应成功率…】Metrics… 1. SpringBoot Actuator 1. 基本使用 1. 场景引入 <dependency><groupId>org.springframew…

【LeetCode】剑指 Offer Ⅱ 第2章:数组(8道题) -- Java Version

题库链接&#xff1a;https://leetcode.cn/problem-list/e8X3pBZi/ 题目解决方案剑指 Offer II 006. 排序数组中两个数字之和双指针&#xff08;异向&#xff09; ⭐剑指 Offer II 007. 数组中和为 0 的三个数排序 双指针&#xff08;异向&#xff09; ⭐剑指 Offer II 008. 和…

常见历史漏洞之Thinkphp

常见历史漏洞之Thinkphp 一、介绍二、Thinkphp历史漏洞三、Thinkphp特征发现四、批量漏洞检测五、漏洞总结六、5.0.23版本案例演示 一、介绍 Thinkphp是一种开源框架。是一个由国人开发的支持windows/Unix/Linux等服务器环境的轻量级PHP开发框架。很多cms就是基于thinkphp二次开…

java程序打包成exe在无java环境执行

最近写了个小工具&#xff0c;但是java写的&#xff0c;给朋友用的时候不能直接用&#xff0c;因此学习了一下java打包成exe。 众所周知&#xff0c;java需要jvm环境&#xff0c;所以打包的时候需要把稍微轻一点的jre打包进去。接下来是详细步骤。 java程序打包成jar 这个在…

vue2-vue实例挂载的过程

1、思考 new Vue()这个过程中究竟做了什么&#xff1f;过程中是如何完成数据的绑定&#xff0c;又是如何将数据渲染到视图的等等。 2、分析 首先找到vue的构造函数。 源码位置&#xff1a;/src/core/instance/index.js options是用户传递过来的配置项&#xff0c;如data、meth…

项目实战 — 消息队列(4){消息持久化}

目录 一、消息存储格式设计 &#x1f345; 1、queue_data.txt&#xff1a;保存消息的内容 &#x1f345; 2、queue_stat.txt&#xff1a;保存消息的统计信息 二、消息序列化 三、自定义异常类 四、创建MessageFileManger类 &#x1f345; 1、约定消息文件所在的目录和文件名…

高级web前端开发工程师岗位的具体内容概述(合集)

高级web前端开发工程师岗位的具体内容概述1 职责&#xff1a; 1、负责前端页面开发和维护&#xff0c;并根据需求优化产品性能、用户体验、交互效果及各种主流浏览器以及各类型移动客户端的兼容适配工作; 2、配合产品经理和UI设计师&#xff0c;通过各种前端技术手段&#xf…

Liunx环境下git的详细使用(gitee版)

Liunx环境下git的详细使用&#xff08;gitee版&#xff09; 1.git是什么2.git操作2.1在gitee创建一个仓库2.2.gitignore2.3.git 3.git三板斧3.1add3.2 commit3.3push 4.git其他命令4.1查看当前仓库状态4.2查看提交日志4.3修改git里面文件名称4.4删除文件4.5修改远端仓库内容 1.…

Git报错合集

本文记录了笔者在使用 github 过程中遇到的问题&#xff0c;仅供个人使用。 目录 Could not resolve hostlocal changes to the following files would be overwritten by mergeTLS connection was non-properly terminatedUpdates were rejected because the remote contains …