通过C语言设计的贪吃蛇游戏(控制台终端)
一、项目介绍
当前通过控制台终端实现一个贪吃蛇小游戏,实现游戏的绘制、更新、控制等功能。
二、实现效果
三、完整代码
下面贴出的代码在Windows系统上编译运行,需要使用conio.h头文件中的getch()函数来获取键盘输入,用于控制蛇的移动。可以通过按下’w’、‘s’、‘a’、'd’四个键来分别控制蛇的向上、向下、向左、向右移动。同时还有一个暂停函数Pause(),用于控制蛇的移动速度,可以根据需要调整暂停时间。
设计思路:
程序定义了一些常量,包括游戏界面的宽度和高度、不同状态下的符号表示等,并在全局变量中定义了蛇头、蛇身、食物等的位置、得分、长度、行进方向等参数。同时还定义了一个二维字符数组board,用于表示整个游戏界面。
在InitGame()函数中进行游戏初始化,设置游戏界面的边框、蛇头、蛇身、随机生成食物等操作。
DrawGame()函数用于绘制游戏画面,将board数组中的字符逐行输出,并在末尾输出得分。UpdateGame()函数用于更新游戏状态,包括蛇的移动、游戏结束判断等。CheckGameOver()函数用于检查游戏是否结束,包括墙壁碰撞、蛇身碰撞、得分达到上限等情况。GenerateFood()函数用于随机生成食物位置,调用rand()函数获取随机数并进行判断。Move()函数用于蛇的移动,根据当前行进方向进行移动。Control()函数用于用户操作,读取键盘输入并更新蛇的行进方向。Pause()函数用于控制游戏速度,通过调用Sleep()函数控制暂停时间。GameOver()函数用于输出最终得分和游戏结束信息,并直接退出程序。
#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;elseboard[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); //直接退出程序
}
相关文章:

通过C语言设计的贪吃蛇游戏(控制台终端)
一、项目介绍 当前通过控制台终端实现一个贪吃蛇小游戏,实现游戏的绘制、更新、控制等功能。 二、实现效果 三、完整代码 下面贴出的代码在Windows系统上编译运行,需要使用conio.h头文件中的getch()函数来获取键盘输入,用于控制蛇的移动。…...

c++实现Qt信号和槽机制
文章目录 简介信号槽信号与槽的连接 特点观察者模式定义观察者模式结构图 实现简单的信号和槽 简介 信号槽机制与Windows下消息机制类似,消息机制是基于回调函数,Qt中用信号与槽来代替函数指针,使程序更安全简洁。 信号和槽机制是 Qt 的核心…...

【Linux】五、进程
一、冯诺依曼体系结构 存储器:指的是内存; 输入设备:键盘、摄像头、话筒,磁盘,网卡; 输出设备:显示器、音响、磁盘、网卡; 中央处理器(CPU):运算器…...

使用 OpenCV 和 Python 卡通化图像-附源码
介绍 在本文中,我们将构建一个有趣的应用程序,它将卡通化提供给它的图像。为了构建这个卡通化器应用程序,我们将使用 python 和 OpenCV。这是机器学习令人兴奋的应用之一。在构建此应用程序时,我们还将了解如何使用 easygui、Tkinter 等库。在这里,您必须选择图像,然后应…...

GitLab不同角色对应的权限
Owner(拥有者): 拥有者是项目或组的创建者,拥有最高级别的权限。他们可以添加、删除项目成员,修改项目设置,管理访问权限,并进行项目转让。在组级别,他们还可以添加或删除子组和项目…...

手写一个简易的布隆过滤器
1.什么是布隆过滤器 布隆过滤器(Bloom Filter)是1970年由布隆(人名)提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,…...

阿里云快速部署开发环境 (Apache + Mysql8.0)
本文章的内容截取于云服务器管理控制台提供的安装步骤,再整合前人思路而成,文章末端会提供原文连接 ApacheMysql 8.0部署MySQL数据库(Linux)步骤一:安装MySQL步骤二:配置MySQL步骤三:远程访问My…...

侧边栏的打开与收起
侧边栏的打开与收起 <template><div class"box"><div class"sideBar" :class"showBox ? : controller-box-hide"><div class"showBnt" click"showBox!showBox"><i class"el-icon-arrow-r…...

贝叶斯学习
贝叶斯 贝叶斯学习的背景贝叶斯定理举例 概览选择假设— MAPMAP举例 选择假设 — 极大似然 MLML 举例: 抛硬币问题 极大似然 & 最小二乘Nave Bayesian Classifier (朴素贝叶斯分类器)举例1:词义消歧 (Word Sense Disambiguation)举例 2: 垃圾邮件过滤 从垃圾邮件…...

Java并发系列之六:CountDownLatch
CountDownLatch作为开发中最常用的组件,今天我们来聊聊它的作用以及内部构造。 首先尝试用一句话对CountDownLatch进行概括: CountDownLatch基于AQS,它实现了闩锁,在开发中可以将其用作任务计数器。 若想要较为系统地去理解这些特性ÿ…...

24数据结构-图的基本概念与存储结构
目录 第六章 图6.1 图的基本概念知识回顾 6.2 图的储存结构(邻接矩阵法)1. 数组表示法(1) 有向图,无向图的邻接矩阵 2. 定义邻接矩阵的结构3. 定义图的结构4. 构造图G5. 特点 第六章 图 6.1 图的基本概念 图是一种非线性结构 图的特点&am…...

自然语言处理学习笔记(三)————HanLP安装与使用
目录 1.HanLP安装 2.HanLP使用 (1)预下载 (2)测试 (3)命令行 (4)测试样例 3.pyhanlp可视化 4. HanLP词性表 1.HanLP安装 HanLP的 Python接口由 pyhanlp包提供,其安装…...

CS 144 Lab Five -- the network interface
CS 144 Lab Five -- the network interface TCP报文的数据传输方式地址解析协议 ARPARP攻击科普 Network Interface 具体实现测试tcp_ip_ethernet.ccTCPOverIPv4OverEthernetAdapterTCPOverIPv4OverEthernetSpongeSocket通信过程 对应课程视频: 【计算机网络】 斯坦福大学CS144…...

Mecha
一、Mecha Mecha 是一个开源的多云 Kubernetes 管理平台,旨在简化和统一在多个云提供商上运行 Kubernetes 集群的管理和操作。它是由阿里巴巴集团开发和维护的项目。 Mecha 的主要目标是提供一个统一的界面和工具,使用户能够更轻松地在不同的云提供商上…...

Apache RocketMQ之集成RocketMQ_MQTT 安装部署协议
Apache RocketMQ 安装说明 安装步骤 参考快速开始 https://rocketmq.apache.org/zh/docs/quickStart/01quickstart 安装可视化rocketmq_dashboard下载地址 https://rocketmq.apache.org/zh/docs/4.x/deployment/03Dashboard/ 安装rocketmq_mqtt https://rocketmq.apache.o…...

Oracle多行数据合并为一行数据,并将列数据转为字段名
Oracle多行数据合并为一行数据 实现查询效果原数据 方式一:MAX()数据效果SQL 方式二:LISTAGG()数据效果 方式三:WM_CONCAT()数据效果 实现查询效果 原数据 FZPROJECTVALUE1电脑$16001手机$121导管$12电脑$22手机$22 方式一:MAX…...

MySQL5.7 与 MariaDB10.1 审计插件兼容性验证
这是一篇关于发现 MariaDB 审计插件导致 MySQL 发生 crash 后,展开适配验证并进行故障处理的文章。 作者:官永强 爱可生DBA 团队成员,擅长 MySQL 运维方面的技能。热爱学习新知识,亦是个爱打游戏的宅男。 本文来源:原创…...

PyTorch Lightning教程五:Debug调试
如果遇到了这样一个问题,当一次训练模型花了好几天,结果突然在验证或测试的时候崩掉了,这个时候其实是很奔溃的,主要还是由于没有提前知道哪些时候会出现什么问题,本节会引入Lightning的Debug方案 1.fast_dev_run参数 …...

末流211无科研保研经验分享
文章目录 个人背景夏令营哈工大威海西工大光电北航软院北邮计算机中科大科学岛 预推免东南软件北航计算机 写在最后心路历程寄语 个人背景 院校:末流211专业背景:计算机科学与技术排名:夏令营7 / 126,预推免3 / 126英语ÿ…...

日期选择器多选换行
<el-form-item label"日期选择"><div class"multi-date-picker"><div class"date-item"><span class"dateIcon"><el-icon><Calendar /></el-icon></span><span class"dateIt…...

NodeJS原型链污染ctfshow_nodejs
文章目录 NodeJS原型链污染&ctfshow_nodejs前言0x01.原型与原型链0x02.prototype和__proto__分别是什么?0x03.原型链继承不同对象的原型链* 0x04.原型链污染原理0x05.merge()导致原型链污染0x06.ejs模板引擎RCEejs模板引擎另一处rce 0x07.jade模板引擎RCE【ctfs…...

18. SpringBoot 如何在 POM 中引入本地 JAR 包
❤️ 个人主页:水滴技术 🌸 订阅专栏:成功解决 BUG 合集 🚀 支持水滴:点赞👍 收藏⭐ 留言💬 Spring Boot 是一种基于 Spring 框架的轻量级应用程序开发框架,它提供了快速开发应用程…...

vue2-$nextTick有什么作用?
1、$nextTick是什么? 官方定义:在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM。 解释:Vue在更新DOM时是异步执行的,当数据发生变化时,Vue将开启一个异步更新的队…...

python自动收集粘贴板
win10的粘贴板可以用“winV”查看: 每次复制都相当于入栈一个字符串,粘贴相当于获取栈顶。 但是系统自带的这个粘贴板貌似不能一键导出,所以我写了个python代码完成这个功能: import pyperclip import timetmp while True:txt…...

Vue3_语法糖—— <script setup>以及unplugin-auto-import自动引入插件
<script setup>import { ref , onMounted} from vue;let obj ref({a: 1,b: 2,}); let changeObj ()>{console.log(obj)obj.value.c 3 //ref写法}onMounted(()>{console.log(obj)})</script> 里面的代码会被编译成组件 setup() 函数的内容。 相当于 <…...

2023-08-06力扣做过了的题
链接: 剑指 Offer 30. 包含min函数的栈 题意: 如题 解: 初级算法里做过的题 优化是存储和min的差值使得只需要n的栈和一个int min 实际代码: #include<bits/stdc.h> using namespace std; class MinStack { public:…...

进程间通信之管道
文章目录 一、管道1. 匿名管道2. 命名管道 进程具有独立性,因此进程间通信的前提是两个进程能看到同一份资源 一、管道 对于进程打开的内存文件,操作系统是以引用计数的方式创建的 file 结构体,如果让两个进程与同一个 file 结构体关联&…...

f12 CSS网页调试_css样式被划了黑线怎么办
我的问题是这样的 class加上去了,但是样式不生效,此时可能是样式被其他样式覆盖了, 解决方案就是 给颜色后边添加一个!important...

vue-制作自动滚动效果
第一步:下载 可以查看官方地址chenxuan0000 npm i vue-seamless-scroll -save 第二步:引用 import vueSeamlessScroll from "vue-seamless-scroll";//注册components: {vueSeamlessScroll,}, 第三步:使用 <vue-seamless…...

[国产MCU]-BL602-开发实例-DMA数据传输
DMA数据传输 文章目录 DMA数据传输1、DMA介绍2、DMA驱动API介绍3、DMA使用示例DMA(Direct Memory Access)是一种内存存取技术,可以独立地直接读写系统内存,而不需处理器介入处理。 在同等程度的处理器负担下,DMA是一种快速的数据传送方式。 BL602的DMA控制器有4组独立专用通…...