C++ 适合新手的贪吃蛇小项目
这是我的第一个C项目虽然很简短 但写完还是蛮有成就感的1.设计思路如何设计蛇身可以看作一个双端队列队头是蛇头队尾为蛇通过出入队来控制蛇身。如何移动蛇身可以简化为只有头和尾动中间的部分并不需要移动。控制光标移动打印新蛇头删除旧蛇尾即可。如何检测碰撞因为程序很小可以设置一个数组记录每个坐标是否已有实体每次移动检测蛇头的坐标。2.可能遇到的问题打印格式错乱该项目在终端中运行windows终端默认大小为80*40而地图为120*40可能需要重新设置终端的显示大小和缓冲区大小。输入时注意是否超过缓冲区大小如果超过会导致一些意外的错误。比如终端大小80*40缓冲区120*40你每行输入100个字符可能开始几行显示正常但后面可能会出现如直接跳过输入的错误。坐标错乱坐标是从(0,0)开始如果程序开始之前终端有其他输入会导致坐标错乱。最好先使用cls清空终端。无法自动的移动问题_getch()是阻塞式输入会一直等待用户输入期间暂停程序的运行。使用_kbhit()它会检测是否有待输入内容如果无就返回不会阻塞程序运行。3.代码展示#pragma once #include iostream #include deque #include windows.h #include ctime #include vector #include conio.h #include algorithm using namespace std; struct Snake { char image; // 用于表示蛇身体的图标 short x, y; // 坐标 }; class snakeGame { private: enum MapSize { height 40, // x width 120 // y }; // 地图尺寸行高40列宽120 HANDLE hout; // 控制台输出句柄用于光标操作 COORD pos; // 光标位置的结构题 char dir; // 蛇头移动方向 double speed 300; // 移动速度 dequeSnake snake; // 双端队列队头为蛇头队尾为蛇尾 short food_x, food_y; // 食物的坐标 int score 0; // 得分 // 不要用bool其在c中位压缩1bit一个bool无法取元素地址且访问慢 vectorchar maptag; // 时间换空间标记地图坐标0表示安全1表示墙或蛇身 public: snakeGame(); // 构造函数 void printMap(); // 创建地图 void displayInfo(); // 显示得分速度蛇长 void gotoxy(short x, short y); // 将控制台光标移动到(x,y)处 void HideCursor(); // 隐藏光标让画面更干净 void initSnake(); // 初始化蛇身 void printSnakeHead(); // 打印蛇头 int WrongLocation(); // 判断食物生产位置是否和蛇身冲突 void createFood(); // 生产食物 void clearSnaketail(Snake tail); // 擦除蛇尾用空格覆盖 void judgeCrash(const Snake ); // 检测蛇头是否撞墙或与蛇身重叠 void foodEaten(); // 当蛇吃到食物加分加速生产新食物 void userInput(); // 处理用户输入 };#include snake.h void snakeGame::gotoxy(short x, short y) { // STD_OUTPUT_HANDLE 申请操作标准输出设备的权限 // GetStdHandle 是系统给的句柄后面队屏幕的操作需要使用这个通行证 hout GetStdHandle(STD_OUTPUT_HANDLE); pos {x, y}; // SetConsoleCursorPosition是Windows系统提供的底层移动函数 // hout告诉系统哪个设备pos告诉系统将光标放在哪个坐标 SetConsoleCursorPosition(hout, pos); } void snakeGame::displayInfo() { // 使用固定的两行显示信息 gotoxy(0, height 3); cout 速度: speed ms ; cout 得分: score ; cout 蛇长: snake.size() ; } void snakeGame::printMap() { // height 40,width 120 // 注意终端尺寸不要超出了不然会显示错误 maptag.assign(height * width, 0); short i; for (i 0; i width; i) { cout #; maptag[static_castsize_t(i)] 1; // 标记格子被占用 } cout i; for (i 1; i height - 1; i) { gotoxy(0, i); // 光标移到(0,i) cout #; maptag[static_castsize_t(i * width)] 1; gotoxy(width - 1, i); cout # i; maptag[static_castsize_t((i 1) * width - 1)] 1; } gotoxy(0, height - 1); int temp (height - 1) * width; for (i 0; i width; i) { cout #; maptag[static_castsize_t(temp i)] 1; } cout i; cout \n贪吃蛇: 1.按方向键开始游戏 2. * 代表食物 3.空格暂停游戏\n 4.按\v\加快速度 5. 按\b\减慢速度\n; } void snakeGame::HideCursor() { HANDLE handle GetStdHandle(STD_OUTPUT_HANDLE); // 获取屏幕控制许可 CONSOLE_CURSOR_INFO CursorInfo; // 创建一个光标信息体变量存放光标 GetConsoleCursorInfo(handle, CursorInfo); // 用句柄去系统那将当前光标取出来存放到CursorInfo里 CursorInfo.bVisible false; // 光标不可见 SetConsoleCursorInfo(handle, CursorInfo); // 把修改后的光标信息写回系统让设置生效 } void snakeGame::initSnake() { // 初始化蛇身并打印 snake.push_front({, width / 2, height / 2}); maptag[height / 2 * width width / 2] 1; gotoxy(width / 2, height / 2); cout ; for (short i 0; i 2; i) { short x width / 2; short y static_castshort(height / 2 i 1); snake.push_back({, x, y}); maptag[static_castsize_t(y * width x)] 1; gotoxy(x, y); cout ; } } void snakeGame::printSnakeHead() { // 蛇移动只用处理蛇头和蛇尾其余部分无需处理 auto iter snake.begin(); gotoxy(iter-x, iter-y); cout iter-image; // 新蛇头 iter; gotoxy(iter-x, iter-y); cout (iter-image ); // 原来的蛇头变蛇身重新打印 } int snakeGame::WrongLocation() { if (maptag[static_castsize_t(food_x food_y * width)] 1) return 1; return 0; } void snakeGame::createFood() { do { food_x static_castshort(rand() % (width - 2) 2); food_y static_castshort(rand() % (height - 2) 2); } while (WrongLocation()); gotoxy(food_x, food_y); cout *; } void snakeGame::clearSnaketail(Snake tail) { // 用空格覆盖蛇尾而非清屏避免了闪烁 gotoxy(tail.x, tail.y); cout ; maptag[static_castsize_t(tail.y * width tail.x)] 0; } void snakeGame::judgeCrash(const Snake s) { // 检查是否碰撞 if (maptag[static_castsize_t(s.y * width s.x)] 1) { gotoxy(width / 2 - 10, height / 2); cout 游戏结束你的分数是 score 分(回车继续) endl; dir static_castchar(_getch()); runtime_error quit(游戏结束正常退出); throw quit; } } void snakeGame::foodEaten() { speed max(speed*0.8, 100.0); score; createFood(); } void snakeGame::userInput() { char ch; switch (ch static_castchar(_getch())) // 输入控制带反向检测 { case W: case w: if (dir ! s) dir w; break; case S: case s: if (dir ! w) dir s; break; case A: case a: if (dir ! d) dir a; break; case D: case d: if (dir ! a) dir d; break; case V: case v: speed max(speed * 0.9, 100.0); displayInfo(); break; case B: case b: speed * 1.5; displayInfo(); break; case : gotoxy(width / 2, height); cout 游戏已暂停任意键继续; _getch(); gotoxy(width / 2, height); cout ; break; default: break; } } snakeGame::snakeGame() { system(mode con cols128 lines64); // 设置终端大小 system(cls); // 清空屏幕 HideCursor(); // 隐藏光标 srand(static_castunsigned int(time(NULL))); // 随机种子 maptag.assign(width * height, 0); // 初始化maptag Snake head, tail; // 蛇头和蛇尾 printMap(); // 打印地图 initSnake(); // 初始化蛇身 head snake.front(); // 蛇头 tail snake.back(); // 蛇尾 dir w; // 默认初始向上移动 createFood(); // 创建食物 while (true) { // _getch()是阻塞式输入程序等待用户输入在此期间程序会暂停执行 // _kbhit()检查缓冲区是否有等待输入的流如果没有就马上返回不会阻塞程序执行。 if (_kbhit()) { userInput(); // 处理用户输入 } if (dir s) // 更改蛇头坐标 { // 如果新头不合法游戏就结束所以直接修改原蛇头图标没有影响(只是修改无打印) snake.front().image ; head.y; } else if (dir w) { snake.front().image ; --head.y; } else if (dir a) { snake.front().image ; --head.x; } else if (dir d) { snake.front().image ; head.x; } // 判断是否撞墙或吃到自己 try { judgeCrash(head); // 这里的得用新的head因为snake.front()坐标处maptag肯定是1 } catch (runtime_error quitSignal) { throw quitSignal; } // 更新蛇头 snake.push_front(head); // 新蛇头入队 maptag[static_castsize_t(head.y * width head.x)] 1; printSnakeHead(); // 依据是否吃到食物更新蛇尾 if (head.x food_x head.y food_y) { foodEaten(); displayInfo(); } else { clearSnaketail(tail); // 没吃到食物就删除蛇尾 snake.pop_back(); // 尾元素出队 tail snake.back(); // 新蛇尾 } // 添加延迟不然蛇移动过快 Sleep(static_castDWORD(speed)); } }#include iostream #include snake.h int main() { try { snakeGame game; } catch (runtime_error gameEnd) { // 结束 system(cls); cout gameEnd.what(); getch(); } return 0; }

相关新闻

前端性能优化实战:从Lighthouse核心指标到自动化监控

前端性能优化实战:从Lighthouse核心指标到自动化监控

1. 项目概述:为什么我们需要一个“灯塔”来照亮前端性能?如果你是一名前端开发者,或者正在负责一个Web产品的用户体验,那么你一定对“页面加载慢”、“交互卡顿”、“用户流失率高”这些词不陌生。在追求极致用户体验的今天&#…

2026/8/2 7:07:10 阅读更多 →
胶原蛋白护肤品怎么选、怎么用、和谁搭效果好? 一张表全说清楚

胶原蛋白护肤品怎么选、怎么用、和谁搭效果好? 一张表全说清楚

2026/8/2 7:06:10 阅读更多 →
Code Alpaca 代码指令数据集微调:Sequence Length 设为 2048 的依据与实践(附实验代码)

Code Alpaca 代码指令数据集微调:Sequence Length 设为 2048 的依据与实践(附实验代码)

Code Alpaca 代码指令数据集微调:Sequence Length 设为 2048 的依据与实践(附实验代码) 一、引言 在微调大语言模型(尤其是代码生成任务)时,序列长度(Sequence Length) 是一个关键…

2026/8/2 7:06:10 阅读更多 →

最新新闻

ESP32-S3驱动1.51寸透明OLED:从SPI连接到NTP时钟的完整实践

ESP32-S3驱动1.51寸透明OLED:从SPI连接到NTP时钟的完整实践

1. 项目缘起:为什么是透明OLED?最近在捣鼓一个桌面小摆件,想做一个既有科技感又不占地方的时间/信息显示器。市面上常见的0.96寸、1.3寸OLED屏虽然效果不错,但总感觉黑乎乎的一块贴在桌面上,有点“堵”。直到我发现了1…

2026/8/2 7:54:29 阅读更多 →
驾驶视角道路缺陷检测数据集训练及应用 YOLOv26 训练道路缺陷检测数据集|3类2128张YOLO格式

驾驶视角道路缺陷检测数据集训练及应用 YOLOv26 训练道路缺陷检测数据集|3类2128张YOLO格式

智慧驾驶道路缺陷检测科研专用】道路缺陷检测数据集|3类2128张YOLO格式 【数据集规格】 • 文件:待定(下单后自动发送具体文件) • 格式:标准YOLO txt标注,附完整data.yaml,解压即用 • 规模…

2026/8/2 7:54:29 阅读更多 →
深度学习基于 YOLO 飞机表面缺陷智能检测系统 飞机表面缺陷检测数据集

深度学习基于 YOLO 飞机表面缺陷智能检测系统 飞机表面缺陷检测数据集

智慧 缺陷检测- 基于YOLO的飞机表面缺陷智能检测系统【python源码Pyqt5界面数据集训练代码】图片,文件夹,视频摄像头均可 本文使用的飞机表面缺陷 数据集共包含 1250 张图片。 各类标签的数量分别为: Paint Peeling: 2845 Dents or Deformati…

2026/8/2 7:54:29 阅读更多 →
参数优化算法全解析:从梯度下降到贝叶斯优化与自动化调参实战

参数优化算法全解析:从梯度下降到贝叶斯优化与自动化调参实战

1. 项目概述:为什么我们需要参数优化算法? 在任何一个需要模型或系统进行决策的领域,无论是训练一个深度神经网络来识别图像,还是调整一个工业控制系统的PID参数,我们都会遇到一个核心问题:如何找到那一组能…

2026/8/2 7:54:29 阅读更多 →
ECRS分析原则:从流程优化到效率重塑的系统化思维框架

ECRS分析原则:从流程优化到效率重塑的系统化思维框架

1. 项目概述:从“优化”到“重塑”的思维利器 在制造业、服务业乃至日常工作中,我们常常面临一个共同的困境:流程繁琐、效率低下、资源浪费。当你想改进一个环节时,是直接增加人手和设备,还是停下来先审视一下这个环节…

2026/8/2 7:54:29 阅读更多 →
OpenCV模板匹配实战:原理、代码与工业级优化技巧

OpenCV模板匹配实战:原理、代码与工业级优化技巧

1. 从“找茬”到自动化:为什么我们需要模板匹配?如果你玩过“大家来找茬”这类游戏,或者曾经在两张看似相同的图片里费力地寻找那几处细微的不同,那么恭喜你,你已经体验过图像匹配最原始的手动版本。而在工业质检、文档…

2026/8/2 7:53:29 阅读更多 →

日新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/2 0:00:38 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/2 0:00:38 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/2 0:00:38 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/2 0:00:38 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/2 0:00:38 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/2 0:00:38 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/2 6:34:16 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/2 2:47:48 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/2 0:23:22 阅读更多 →