贪吃蛇游戏在c++++中实现的核心在于构建游戏逻辑、图形界面绘制和键盘输入处理。1. 游戏基本结构包括蛇(由坐标点组成)、食物(随机生成)和游戏区域(控制台边界)。2. 数据结构使用std::vector<std::pair<int, int>>存储蛇的身体,std::pair<int, int>表示食物坐标,枚举类型direction定义移动方向。3. 图形界面通过字符绘制实现,如#表示墙壁,@表示蛇身,$表示食物,并使用system("cls")或system("clear")清空屏幕。4. 蛇的移动逻辑是根据方向更新蛇头位置并重新插入头部,若吃到食物则保留尾部以增加长度,否则移除尾部。5. 键盘输入处理使用非阻塞方式,windows下为_kbhit()和_getch(),同时限制反向移动防止蛇撞到自己。6. 游戏循环持续更新画面、处理输入并控制速度。7. 优化方面可加入障碍物和道具,如x表示障碍物,!表示加速道具,并扩展得分系统与元素生成逻辑。

贪吃蛇游戏的核心在于构建游戏逻辑、绘制图形界面(即使是控制台的简单图形),以及处理键盘输入。C++是完全可以胜任这些任务的。

首先,我们需要明确游戏的基本组成部分:蛇、食物、游戏区域。蛇由一系列坐标点组成,食物是随机生成的坐标点,游戏区域则是控制台的边界。

解决方案
立即学习“C++免费学习笔记(深入)”;
数据结构设计:

std::vector<std::pair<int, int>>存储蛇的身体,每个pair<int, int>代表一个坐标。std::pair<int, int>存储食物的坐标。enum Direction { UP, DOWN, LEFT, RIGHT }表示蛇的移动方向。游戏区域绘制:
system("cls")(Windows)或system("clear")(Linux/macOS)清空控制台。#表示墙壁。@表示蛇的身体。$表示食物。蛇的移动逻辑:
snake向量的头部。snake向量的尾部,保持蛇的长度不变。键盘输入处理:
_kbhit()和_getch(),或者Linux/macOS下的ncurses库。游戏循环:
Sleep()(Windows)或usleep()(Linux/macOS)控制游戏速度。#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <conio.h> // Windows
#include <thread>
#include <chrono>
using namespace std;
enum Direction { UP, DOWN, LEFT, RIGHT };
int main() {
// 游戏参数
int width = 20;
int height = 10;
vector<pair<int, int>> snake = {{width / 2, height / 2}}; // 初始蛇的位置
pair<int, int> food;
Direction dir = RIGHT;
bool gameOver = false;
// 初始化随机数种子
srand(time(0));
// 生成食物
auto generateFood = [&]() {
food.first = rand() % width;
food.second = rand() % height;
// 确保食物不在蛇的身体里
for (auto &segment : snake) {
if (food == segment) {
generateFood();
return;
}
}
};
generateFood();
// 游戏循环
while (!gameOver) {
// 绘制游戏区域
system("cls"); // 清空屏幕 (Windows)
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
if (i == 0 || i == height - 1 || j == 0 || j == width - 1) {
cout << "#";
} else if (i == food.second && j == food.first) {
cout << "$";
} else {
bool isSnakeBody = false;
for (auto &segment : snake) {
if (segment.first == j && segment.second == i) {
cout << "@";
isSnakeBody = true;
break;
}
}
if (!isSnakeBody) {
cout << " ";
}
}
}
cout << endl;
}
// 处理键盘输入
if (_kbhit()) {
char key = _getch();
switch (key) {
case 'w': if (dir != DOWN) dir = UP; break;
case 's': if (dir != UP) dir = DOWN; break;
case 'a': if (dir != RIGHT) dir = LEFT; break;
case 'd': if (dir != LEFT) dir = RIGHT; break;
case 'x': gameOver = true; break; // 退出游戏
}
}
// 更新蛇的位置
int headX = snake[0].first;
int headY = snake[0].second;
switch (dir) {
case UP: headY--; break;
case DOWN: headY++; break;
case LEFT: headX--; break;
case RIGHT: headX++; break;
}
// 检查是否撞墙
if (headX < 1 || headX >= width - 1 || headY < 1 || headY >= height - 1) {
gameOver = true;
break;
}
// 检查是否撞到自己
for (size_t i = 1; i < snake.size(); ++i) {
if (headX == snake[i].first && headY == snake[i].second) {
gameOver = true;
break;
}
}
if (gameOver) break;
// 更新蛇的身体
snake.insert(snake.begin(), {headX, headY});
// 检查是否吃到食物
if (headX == food.first && headY == food.second) {
generateFood(); // 生成新的食物
} else {
snake.pop_back(); // 移除蛇尾
}
// 控制游戏速度
this_thread::sleep_for(chrono::milliseconds(100));
}
cout << "游戏结束!" << endl;
return 0;
}这个代码展示了最基本的功能。请注意,这只是一个非常基础的实现,可能存在一些bug,例如蛇可以瞬间反向移动导致撞到自己。
防止蛇瞬间反向移动的关键在于,在更新蛇的移动方向时,要避免将方向设置为当前方向的完全相反方向。例如,如果蛇当前向右移动,则不允许立即将方向设置为向左移动。
修改键盘输入处理部分的代码:
// 处理键盘输入
if (_kbhit()) {
char key = _getch();
switch (key) {
case 'w': if (dir != DOWN) dir = UP; break;
case 's': if (dir != UP) dir = DOWN; break;
case 'a': if (dir != RIGHT) dir = LEFT; break;
case 'd': if (dir != LEFT) dir = RIGHT; break;
case 'x': gameOver = true; break; // 退出游戏
}
}要在控制台中显示更丰富的图形,例如使用不同的颜色或字符,你需要使用特定的API,这通常依赖于操作系统。
Windows:
在Windows下,你可以使用Windows.h头文件中的函数来控制控制台的颜色。
SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttributes): 这个函数可以设置控制台文本的颜色和背景色。#include <iostream>
#include <windows.h>
using namespace std;
int main() {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// 设置文本颜色为绿色
SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN);
cout << "This is green text." << endl;
// 设置文本颜色为红色,背景色为蓝色
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | BACKGROUND_BLUE);
cout << "This is red text with blue background." << endl;
// 恢复默认颜色
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
cout << "This is default color." << endl;
return 0;
}Linux/macOS:
在Linux和macOS下,你可以使用ANSI转义码来控制控制台的颜色和样式。ANSI转义码是一些特殊的字符序列,可以嵌入到文本中,用于控制终端的行为。
\033[31m表示设置文本颜色为红色,\033[42m表示设置背景色为绿色。\033[0m表示重置所有颜色和样式为默认值。#include <iostream>
using namespace std;
int main() {
// 设置文本颜色为绿色
cout << "\033[32mThis is green text.\033[0m" << endl;
// 设置文本颜色为红色,背景色为蓝色
cout << "\033[31m\033[44mThis is red text with blue background.\033[0m" << endl;
// 恢复默认颜色
cout << "This is default color." << endl;
return 0;
}障碍物:
std::vector<std::pair<int, int>>存储障碍物的坐标。X表示。加速道具:
std::pair<int, int>存储加速道具的坐标。!表示。Sleep()或usleep()的延时时间。int speed = 100;,然后this_thread::sleep_for(chrono::milliseconds(speed));,吃到加速道具时,减小speed的值,道具效果结束时,恢复speed的值。随机生成:
rand() % width和rand() % height生成随机坐标。#include <iostream> #include <vector> #include <cstdlib> #include <ctime> #include <conio.h> // Windows #include <thread> #include <chrono> #include <random>
using namespace std;
enum Direction { UP, DOWN, LEFT, RIGHT };
int main() { // 游戏参数 int width = 20; int height = 10; vector<pair<int, int>> snake = {{width / 2, height / 2}}; // 初始蛇的位置 pair<int, int> food; Direction dir = RIGHT; bool gameOver = false; int score = 0; int speed = 100; // 初始速度,毫秒 vector<pair<int, int>> obstacles;
// 随机数生成器
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> distribW(1, width - 2); // 排除边界
uniform_int_distribution<> distribH(1, height - 2); // 排除边界
// 初始化随机数种子
srand(time(0));
// 生成食物
auto generateFood = [&]() {
food.first = distribW(gen);
food.second = distribH(gen);
// 确保食物不在蛇的身体里
for (auto &segment : snake) {
if (food == segment) {
generateFood();
return;
}
}
for (auto &obstacle : obstacles) {
if (food == obstacle) {
generateFood();
return;
}
}
};
generateFood();
// 生成障碍物
auto generateObstacles = [&]() {
obstacles.clear();
int numObstacles = 3;
for (int i = 0; i < numObstacles; ++i) {
pair<int, int> obstacle;
obstacle.first = distribW(gen);
obstacle.second = distribH(gen);
// 确保障碍物不在蛇的身体里或食物的位置
bool valid = true;
for (auto &segment : snake) {
if (obstacle == segment) {
valid = false;
break;
}
}
if (obstacle == food) valid = false;
if (valid) {
obstacles.push_back(obstacle);
} else {
i--; // 重新生成
}
}
};
generateObstacles();
// 游戏循环
while (!gameOver) {
// 绘制游戏区域
system("cls"); // 清空屏幕 (Windows)
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
if (i == 0 || i == height - 1 || j == 0 || j == width - 1) {
cout << "#";
} else if (i == food.second && j == food.first) {
cout << "$";
} else {
bool isSnakeBody = false;
for (auto &segment : snake) {
if (segment.first == j && segment.second == i) {
cout << "@";
isSnakeBody = true;
break;
}
}
if (isSnakeBody) continue;
bool isObstacle = false;
for (auto &obstacle : obstacles) {
if (obstacle.first == j && obstacle.second == i) {
cout << "X";
isObstacle = true;
break;
}
}
if (isObstacle) continue;
cout << " ";
}
}
cout << endl;
}
// 显示得分
cout << "得分: " << score << endl;
// 处理键盘输入
if (_kbhit()) {
char key = _getch();
switch (key) {
case 'w': if (dir != DOWN) dir = UP; break;
case 's': if (dir != UP) dir = DOWN; break;
case 'a': if (dir != RIGHT) dir = LEFT; break;
case 'd': if (dir != LEFT) dir = RIGHT; break;
case 'x': gameOver = true; break; // 退出游戏
}
}
// 更新蛇的位置
int headX = snake[0].first;
int headY = snake[0].second;
switch (dir) {
case UP: headY--; break;
case DOWN: headY++; break;
case LEFT: headX--; break;
case RIGHT: headX++; break;
}
// 检查是否撞墙
if (headX < 1 || headX >= width - 1 || headY < 1 || headY >= height - 1) {
gameOver = true;
break;
}
// 检查是否撞到自己
for (size_t i = 1; i < snake.size(); ++i) {
if (headX == snake[i].first && headY == snake[i].second) {
gameOver = true;
break;
}
}
// 检查是否撞到障碍物
for (auto &obstacle : obstacles) {
if (headX == obstacle.first && headY == obstacle.second) {
gameOver = true;
break;
}
}
if (gameOver) break;
// 更新蛇的身体
snake.insert(snake.begin(), {headX, headY});
// 检查是否吃到食物
if (headX == food.first && headY == food.second) {
generateFood(); // 生成新的食物
generateObstacles(); // 生成新的障碍物
score += 10;
} else {
snake.pop_back(); // 移除蛇尾
}
// 控制游戏速度
this_thread::sleep_for(chrono::milliseconds(speed));
}
cout << "游戏结束! 得分: " << score << endl;
return 0;}
以上就是怎样用C++制作贪吃蛇游戏 控制台图形和键盘控制的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号