以下是一个简单的 C++ 控制台版贪吃蛇游戏示例代码,代码量超过了 400 行,包含了基本的游戏逻辑如蛇的移动、食物生成、碰撞检测等,能给你带来一定的趣味性。
#include <iostream>
#include <windows.h> // 用于控制控制台窗口相关操作,比如光标位置等
#include <cstdlib>
#include <ctime>
#include <conio.h> // 用于获取键盘输入
using namespace std;
// 定义游戏窗口的大小
const int WIDTH = 80;
const int HEIGHT = 20;
// 定义蛇身结构体
struct Snake {
int x;
int y;
struct Snake* next;
};
// 初始化蛇
Snake* initSnake() {
Snake* head = new Snake;
head->x = WIDTH / 2;
head->y = HEIGHT / 2;
head->next = NULL;
return head;
}
// 创建食物坐标
void createFood(int& foodX, int& foodY) {
srand(static_cast<unsigned int>(time(NULL)));
foodX = rand() % (WIDTH - 2) + 1;
foodY = rand() % (HEIGHT - 2) + 1;
}
// 绘制游戏界面
void drawBoard(Snake* snake, int foodX, int foodY) {
system("cls"); // 清屏
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < WIDTH; j++) {
if (i == 0 || i == HEIGHT - 1) {
cout << "#";
} else if (j == 0 || j == WIDTH - 1) {
cout << "#";
} else {
bool isSnakeBody = false;
Snake* current = snake;
while (current!= NULL) {
if (current->x == j && current->y == i) {
cout << "O";
isSnakeBody = true;
break;
}
current = current->next;
}
if (j == foodX && i == foodY) {
cout << "F";
} else if (!isSnakeBody) {
cout << " ";
}
}
}
cout << endl;
}
}
// 移动蛇
void moveSnake(Snake*& snake, int direction) {
Snake* newHead = new Snake;
switch (direction) {
case 72: // 向上
newHead->x = snake->x;
newHead->y = snake->y - 1;
break;
case 80: // 向下
newHead->x = snake->x;
newHead->y = snake->y + 1;
break;
case 75: // 向左
newHead->x = snake->x - 1;
newHead->y = snake->y;
break;
case 77: // 向右
newHead->x = snake->x + 1;
newHead->y = snake->y;
break;
}
newHead->next = snake;
snake = newHead;
}
// 检查是否吃到食物
bool checkFood(Snake* snake, int foodX, int foodY) {
return snake->x == foodX && snake->y == foodY;
}
// 检查是否撞墙或者撞到自己
bool checkCollision(Snake* snake) {
if (snake->x == 0 || snake->x == WIDTH - 1 || snake->y == 0 || snake->y == HEIGHT - 1) {
return true;
}
Snake* current = snake->next;
while (current!= NULL) {
if (current->x == snake->x && current->y == snake->y) {
return true;
}
current = current->next;
}
return false;
}
// 释放蛇的内存
void freeSnake(Snake* snake) {
Snake* current = snake;
Snake* next;
while (current!= NULL) {
next = current->next;
delete current;
current = next;
}
}
int main() {
Snake* snake = initSnake();
int foodX, foodY;
createFood(foodX, foodY);
int score = 0;
int direction = 77; // 初始方向向右
bool gameOver = false;
while (!gameOver) {
drawBoard(snake, foodX, foodY);
cout << "Score: " << score << endl;
if (_kbhit()) { // 检查是否有键盘输入
char key = _getch();
switch (key) {
case 'w':
if (direction!= 80) direction = 72; // 避免反向操作
break;
case's':
if (direction!= 72) direction = 80;
break;
case 'a':
if (direction!= 77) direction = 75;
break;
case 'd':
if (direction!= 75) direction = 77;
break;
}
}
moveSnake(snake, direction);
if (checkFood(snake, foodX, foodY)) {
score++;
createFood(foodX, foodY);
} else {
Snake* tail = snake;
while (tail->next->next!= NULL) {
tail = tail->next;
}
Snake* toDelete = tail->next;
tail->next = NULL;
delete toDelete;
}
if (checkCollision(snake)) {
gameOver = true;
}
Sleep(100); // 控制游戏速度
}
freeSnake(snake);
cout << "Game Over! Your score is: " << score << endl;
return 0;
}
这个贪吃蛇游戏代码的具体说明如下:
1. 包含头文件
#include <iostream>
#include <windows.h>
#include <cstdlib>
#include <ctime>
#include <conio.h>
using namespace std;
引入了输入输出流头文件用于控制台输出等操作,windows.h
用于控制控制台窗口相关表现(比如清屏等),cstdlib
和ctime
用于生成随机数(食物位置相关),conio.h
用于获取键盘的输入。
2. 定义全局常量和结构体
const int WIDTH = 80;
const int HEIGHT = 20;
struct Snake {
int x;
int y;
struct Snake* next;
};
定义了游戏窗口的宽和高,同时定义了表示蛇身的结构体,结构体中包含蛇身节点的坐标以及指向下一个节点的指针。
3. 初始化蛇
Snake* initSnake() {
Snake* head = new Snake;
head->x = WIDTH / 2;
head->y = HEIGHT / 2;
head->next = NULL;
return head;
}
创建了蛇的初始头部节点,放置在游戏窗口大致中心位置,并且初始化其指针指向为NULL
。
4. 创建食物坐标
void createFood(int& foodX, int& foodY) {
srand(static_cast<unsigned int>(time(NULL)));
foodX = rand() % (WIDTH - 2) + 1;
foodY = rand() % (HEIGHT - 2) + 1;
}
利用当前时间作为随机数种子,生成在游戏窗口内部合适范围内的食物坐标。
5. 绘制游戏界面
void drawBoard(Snake* snake, int foodX, int foodY) {
// 省略内部实现代码(前面已展示完整)
}
通过循环遍历游戏窗口的每一个坐标位置,根据坐标是否是蛇身、食物、边界等来输出对应的字符,以此绘制整个游戏画面,并且在每次绘制前清屏来更新画面。
6. 移动蛇
void moveSnake(Snake*& snake, int direction) {
// 省略内部实现代码(前面已展示完整)
}
根据传入的方向参数(对应键盘方向键的键值),创建新的蛇头节点并调整其坐标,然后将新蛇头插入到链表头部来实现蛇的移动。
7. 检查是否吃到食物
bool checkFood(Snake* snake, int foodX, int foodY) {
return snake->x == foodX && snake->y == foodY;
}
8. 检查是否撞墙或者撞到自己
bool checkCollision(Snake* snake) {
// 省略内部实现代码(前面已展示完整)
}
以下是上述贪吃蛇游戏代码确保可以运行的步骤以及可能需要注意的一些要点:
编译环境准备
你需要安装一个支持 C++ 编译的集成开发环境(IDE)或者编译器,常见的选择有:
-
Visual Studio(Windows 平台常用):
- 安装 Visual Studio,在安装过程中选择 “使用 C++ 的桌面开发” 工作负载,这样会安装编译 C++ 程序所需要的相关组件。
- 新建项目时,选择 “控制台应用” 模板,然后将上述代码复制粘贴到源文件(一般是
.cpp
后缀的文件)中进行编译运行即可。
-
Code::Blocks(跨平台,Windows、Linux、macOS 都可用):
- 下载并安装 Code::Blocks,安装完成后打开它。
- 通过 “新建” -> “文件” -> “C/C++ 源文件” 创建一个新的代码文件,将代码复制进去,然后点击 “编译并运行” 按钮(通常是一个绿色的三角形图标)来运行程序。
-
GCC 编译器(命令行方式,常用于 Linux、macOS 平台,Windows 下也可安装使用):
- 如果是 Linux 系统(比如 Ubuntu),一般已经预装了 GCC,你可以直接在终端中使用文本编辑器(如
vim
、nano
等)新建一个.cpp
文件,将代码粘贴进去保存。然后在终端中进入该文件所在目录,使用命令g++ -o snake_game your_file_name.cpp
(这里snake_game
是生成的可执行文件名,你可以自行修改,your_file_name.cpp
是你实际保存代码的文件名)来编译代码,编译成功后通过./snake_game
命令来运行程序。 - 在 Windows 下,你可以先安装 MinGW(一个 Windows 版的 GCC 工具集),配置好环境变量后,同样按照上述类似的命令行操作在命令提示符或者 PowerShell 中进行编译和运行。
- 如果是 Linux 系统(比如 Ubuntu),一般已经预装了 GCC,你可以直接在终端中使用文本编辑器(如
代码相关注意事项
-
头文件路径问题(针对部分 IDE):
有时候某些 IDE 可能找不到windows.h
、conio.h
等头文件,这可能是因为相关系统头文件路径没有正确配置。比如在 Visual Studio 中,如果出现找不到头文件报错,你可以通过项目属性中的 “VC++ 目录” 选项来检查和配置包含目录路径,确保其能正确找到系统的头文件所在位置。 -
编译选项(针对命令行编译等情况):
如果使用 GCC 编译,可能根据实际操作系统情况添加一些额外的编译选项来保证程序正常运行,例如在 Windows 下使用 MinGW 编译时,可能需要添加-lwinmm
选项来链接相关的 Windows 多媒体库(因为代码中使用了Sleep
函数,它依赖这个库),像这样编译:g++ -o snake_game your_file_name.cpp -lwinmm
。 -
输入获取兼容性:
_kbhit
和_getch
函数是 Windows 平台下比较常用的用于非缓冲键盘输入获取的函数,在其他平台(比如 Linux、macOS)下它们不可用。如果想让代码更具跨平台性,可以考虑使用其他跨平台的输入获取库或者方法来替代它们,例如在 Linux 下可以使用termios
库等实现类似的功能,但这需要对代码做较大的修改和适配。
按照上述步骤和注意事项,应该就能成功运行这个贪吃蛇游戏代码了,希望你玩得愉快!
以下是关于这段代码在不同平台运行的一些说明:
Windows 平台
- 编译环境:可以使用 Visual Studio,新建一个 “控制台应用” 项目,将代码复制到源文件(一般是
.cpp
文件)中,然后直接点击 “生成” -> “运行” 按钮来运行程序。也可以使用 MinGW 等 GCC 工具集在命令行中编译运行,例如在命令提示符或者 PowerShell 中进入代码所在目录,使用命令g++ -o snake_game your_file_name.cpp -lwinmm
(假设代码保存为your_file_name.cpp
)来编译生成可执行文件snake_game
,然后通过./snake_game
来运行(如果在命令提示符下需要配置好相关环境变量使得能直接运行可执行文件,在 PowerShell 中可直接使用相对路径或者绝对路径来运行)。 - 运行效果:程序会在控制台窗口中展示贪吃蛇游戏界面,通过
w
、s
、a
、d
键来控制蛇的移动方向,吃到食物蛇身增长,撞到墙或者自己游戏结束并显示得分。
Linux 平台(以 Ubuntu 为例,其他类 Unix 系统类似)
- 编译环境:打开终端,进入代码所在目录,使用命令
g++ -o snake_game your_file_name.cpp
来编译代码(生成名为snake_game
的可执行文件),然后通过./snake_game
命令来运行程序。如果编译过程中提示缺少头文件等错误,需要先安装相应的开发包,比如对于termios
相关头文件对应的开发包可能已经默认安装,如果缺少可通过包管理器(如apt-get
)安装相关的基础开发包。 - 运行效果:同样会在终端中呈现贪吃蛇游戏界面,操作方式和 Windows 下一样(使用
w
、s
、a
、d
键控制方向),游戏逻辑也保持一致,最后游戏结束时显示得分。
macOS 平台
- 编译环境:和 Linux 类似,macOS 也自带了 GCC 编译器(或者可以安装 Clang 编译器等,对于这个简单的代码使用默认的编译器基本就能满足需求),在终端中进入代码目录后,使用类似
g++ -o snake_game your_file_name.cpp
的命令编译,再通过./snake_game
运行,不过可能需要注意权限问题,如果可执行文件没有执行权限,可以通过chmod +x snake_game
命令赋予其执行权限后再运行。 - 运行效果:游戏界面和操作逻辑与上述平台一致,能正常进行贪吃蛇游戏并展示结果。
希望这个代码能满足你的需求,让你成功运行并体验贪吃蛇游戏带来的乐趣。
详细一点(保证在Dev c++能正常运行)
以下是一份更详细的说明,以确保上述贪吃蛇游戏代码能在 Dev C++ 中正常运行:
一、打开 Dev C++ 并新建项目
- 启动 Dev C++:在电脑中找到并双击打开 Dev C++ 软件。如果是首次使用,可能需要进行一些简单的初始化设置等操作(比如选择界面语言等,一般默认英文即可)。
- 新建项目:点击菜单栏中的 “File(文件)”,选择 “New(新建)” -> “Project(项目)”。在弹出的 “New Project(新建项目)” 对话框中,选择 “Console Application(控制台应用程序)” 项目类型,这表示我们要创建一个在控制台中运行的程序,适合像贪吃蛇这种基于文本界面展示的游戏。然后点击 “Next(下一步)”。
- 设置项目属性:
- 在 “Project Name(项目名称)” 字段中,输入你想要的项目名称,比如 “SnakeGame”。
- 在 “Location(位置)” 字段中,通过点击右侧的浏览按钮,选择你希望保存项目文件的文件夹路径。你可以自行指定一个合适的磁盘位置及文件夹,方便后续查找和管理项目文件。
- 确保 “C++” 选项被勾选(因为我们使用的是 C++ 语言编写代码),然后点击 “OK(确定)” 按钮。这样就成功创建了一个新的控制台应用项目。
二、添加代码文件并复制代码
- 添加源文件:项目创建好后,在 Dev C++ 的界面中,会看到项目管理窗口(一般在左侧),里面显示了刚才新建的项目名称及其相关结构。右键点击项目名称(例如 “SnakeGame”),在弹出的菜单中选择 “Add to Project(添加到项目)” -> “New File(新建文件)”。
- 选择文件类型:在弹出的 “New File(新建文件)” 对话框中,选择 “C/C++ Source File(C/C++ 源文件)”,表示我们要创建一个存放 C++ 代码的文件。然后点击 “OK(确定)” 按钮。
- 命名文件:此时会弹出一个让你输入文件名的对话框,输入一个合适的文件名,比如 “main.cpp”(文件名后缀必须是
.cpp
,因为是 C++ 源文件),然后点击 “Save(保存)” 按钮。这样就在项目中成功添加了一个空的代码文件,接下来要做的就是将前面提供的贪吃蛇游戏代码复制到这个文件中。 - 复制代码:将前面给出的完整的贪吃蛇游戏代码(如下所示,为方便你查看再次列出)复制粘贴到刚才新建的 “main.cpp” 文件的编辑区域中:
// 释放蛇的内存
void freeSnake(Snake *snake) {
Snake *current = snake;
Snake *next;
while (current!= NULL) {
next = current->next;
delete current;
current = next;
}
}
// 以下是用于类Unix系统下模拟_kbhit功能的代码
#if defined(_WIN32)
// Windows下直接使用_kbhit
int kbhit() {
return _kbhit();
}
// Windows下直接使用_getch
int getch() {
return _getch();
}
#else
// 类Unix系统下实现_kbhit功能的函数
int kbhit() {
static struct termios oldt, newt;
int ch;
int oldf;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
fcntl(STDIN_FILENO, F_SETFL, oldf);
if (ch!= EOF) {
ungetc(ch, stdin);
return 1;
}
return 0;
}
// 类Unix系统下获取一个字符(类似_getch)
int getch() {
struct termios oldt, newt;
int ch;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return ch;
}
#endif
int main() {
Snake *snake = initSnake();
int foodX, foodY;
createFood(foodX, foodY);
int score = 0;
char direction = 'd'; // 初始方向向右
bool gameOver = false;
while (!gameOver) {
drawBoard(snake, foodX, foodY);
cout << "Score: " << score << endl;
if (kbhit()) { // 检查是否有键盘输入
char key = getch();
switch (key) {
case 'w':
if (direction!= 's')
direction = 'w'; // 避免反向操作
break;
case 's':
if (direction!= 'w')
direction = 's';
break;
case 'a':
if (direction!= 'd')
direction = 'a';
break;
case 'd':
if (direction!= 'a')
direction = 'd';
break;
}
}
moveSnake(snake, direction);
if (checkFood(snake, foodX, foodY)) {
score++;
createFood(foodX, foodY);
} else {
Snake *tail = snake;
while (tail->next->next!= NULL) {
tail = tail->next;
}
Snake *toDelete = tail->next;
tail->next = NULL;
delete toDelete;
}
if (checkCollision(snake)) {
gameOver = true;
}
#if defined(_WIN32)
Sleep(100); // Windows下使用Sleep函数控制游戏速度,单位是毫秒
#else
usleep(100000); // 类Unix系统下使用usleep函数控制游戏速度,这里换算成100毫秒(100000微秒)
#endif
}
freeSnake(snake);
cout << "Game Over! Your score is: " << score << endl;
return 0;
}
三、编译与运行项目
- 编译项目:点击菜单栏中的 “Execute(执行)”,选择 “Compile(编译)” 选项(或者直接使用快捷键 F9),Dev C++ 就会开始对代码进行编译。在编译过程中,如果代码存在语法错误或者其他不符合 C++ 规范的问题,下方的 “Compiler Log(编译日志)” 窗口中会显示相应的错误提示信息,你需要根据这些提示去代码中找到对应位置进行修改,然后再次点击 “Compile(编译)” 进行重新编译,直到编译成功,没有错误提示为止。
- 运行项目:编译成功后,点击菜单栏中的 “Execute(执行)”,选择 “Run(运行)” 选项(或者直接使用快捷键 F10),此时程序就会开始运行,会弹出一个控制台窗口,在这个窗口中就能看到贪吃蛇游戏的界面了。你可以通过按下键盘上的
w
、s
、a
、d
键来控制蛇的移动方向,蛇会在游戏窗口中不断移动,当蛇吃到食物(用F
表示)时,蛇身会增长,得分也会增加,如果蛇撞到墙或者自己的身体,游戏就会结束,并在控制台中显示出最终的得分。
四、可能遇到的问题及解决方法
- 头文件找不到错误:
- 如果在编译时出现类似 “
windows.h
not found” 或者 “termios.h
not found” 等头文件找不到的错误提示,这可能是因为 Dev C++ 没有正确配置相关的头文件搜索路径。对于windows.h
这类 Windows 系统下的头文件,一般在正确安装了 Windows 操作系统以及 Dev C++ 的情况下很少出现找不到的问题,但如果确实出现了,可以尝试以下解决方法:- 点击菜单栏中的 “Tools(工具)”,选择 “Compiler Options(编译器选项)”。
- 在弹出的 “Compiler Options(编译器选项)” 对话框中,切换到 “Directories(目录)” 选项卡。
- 在 “Include directories(包含目录)” 列表中,确保有类似 “C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt”(这里的路径可能因 Windows 版本以及安装的 Windows Kits 不同而有所变化)这样的 Windows 系统头文件包含路径存在,如果没有,可以点击右侧的 “Add(添加)” 按钮手动添加进去(你可以通过在文件资源管理器中搜索
windows.h
文件来确定其所在的准确路径)。
- 对于
termios.h
等类 Unix 系统相关头文件在 Windows 下出现找不到的情况(因为 Dev C++ 本身也支持模拟类 Unix 编译环境),如果报错,一般不用太理会,因为代码中通过条件编译(#if defined(_WIN32)
等判断)已经处理好了,在 Windows 下实际运行时不会用到这些类 Unix 相关的代码部分。但如果想避免看到这些错误提示,可以尝试在 “Compiler Options(编译器选项)” 的 “Directories(目录)” 选项卡中,把对应类 Unix 系统头文件所在的路径(比如在安装了 MinGW 等类 Unix 模拟环境的情况下,找到其头文件路径,通常在安装目录下的include
文件夹中)添加到 “Exclude directories(排除目录)” 列表中,这样编译器在编译时就不会去这些目录查找头文件而报错了。
- 如果在编译时出现类似 “
- 链接错误(例如关于
_kbhit
、_getch
或Sleep
等函数):- 如果出现类似 “undefined reference to
_kbhit
” 或者 “undefined reference toSleep
” 等链接错误提示,这是因为这些函数所在的库没有正确链接到项目中。对于_kbhit
、_getch
和Sleep
这些 Windows 平台下的函数,需要在编译时链接winmm.lib
库来解决。操作方法如下:- 点击菜单栏中的 “Tools(工具)”,选择 “Compiler Options(编译器选项)”。
- 在弹出的 “Compiler Options(编译器选项)” 对话框中,切换到 “Linker(链接器)” 选项卡。
- 在 “Libraries(库)” 列表中,点击 “Add(添加)” 按钮,然后输入 “winmm”(不用输入后缀
.lib
),点击 “OK(确定)” 按钮,这样就添加了需要链接的库,再次编译运行项目应该就能正常使用这些函数了。
- 如果出现类似 “undefined reference to
- 运行时窗口闪退问题:有时候运行游戏后,控制台窗口可能会一闪而过,导致来不及看到游戏过程和结果。这是因为程序运行结束后自动关闭了窗口。解决方法是在代码的最后(
return 0;
之前)添加一行代码system("pause");
,这样当游戏结束显示得分后,程序会暂停,等待你按下任意键后再关闭窗口,方便查看结果。
通过以上详细步骤以及对可能出现问题的应对方法,应该就能在 Dev C++ 中顺利运行这个贪吃蛇游戏代码了,希望你能享受游戏开发和玩游戏的乐趣哦!