C++ 适合新手的贪吃蛇小项目

发布时间:2026/8/2 7:07:06

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; }

相关新闻