VSCode零依赖C++控制台贪吃蛇完整源码

Vibe Coding 使用 AI 回答

代码问题:

帮我用c++写一个贪吃蛇小游戏,能够在visual studio code上运行的,不用下载任何其他东西的

代码解决方案:

好的,这是一个使用 C++ 编写的贪吃蛇小游戏,可以在 Visual Studio Code 上运行,并且不需要下载任何额外的库。它利用了控制台的特性来实现图形界面。

功能:

  • 贪吃蛇移动
  • 吃食物增长
  • 碰到墙壁或自身死亡
  • 计分
  • 简单的游戏结束界面

如何在 Visual Studio Code 中运行:

  1. 安装 MinGW (C++ 编译器):

    • 如果你还没有安装 C++ 编译器,Visual Studio Code 无法直接编译 C++ 代码。最常见和推荐的方式是安装 MinGW-w64。
    • 访问 MinGW-w64 官网:https://www.mingw-w64.org/doku.php/download
    • 下载并运行安装程序。在安装过程中,确保勾选 "posix" 线程模型和 "seh" 异常处理(对于 64 位系统)。
    • 将 MinGW 的 bin 目录添加到系统的 PATH 环境变量中。通常是 C:\MinGW\binC:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-mingw-w64-v10.0.0\mingw64\bin (路径可能因版本而异)。
    • 打开一个新的命令提示符或 PowerShell 窗口,输入 g++ --version,如果显示版本信息,则表示安装成功。
  2. 在 Visual Studio Code 中创建文件:

    • 打开 Visual Studio Code。
    • 创建一个新文件夹(例如 snake_game)。
    • 在该文件夹中创建一个名为 main.cpp 的文件。
  3. 复制代码:

    • 将下面的 C++ 代码复制并粘贴到 main.cpp 文件中。
  4. 配置任务 (Tasks.json):

    • 按下 Ctrl + Shift + P (或 Cmd + Shift + P 在 macOS 上) 打开命令面板。
    • 输入 "Tasks: Configure Default Build Task" 并选择它。
    • 选择 "Create tasks.json file from template"。
    • 选择 "Others"。
    • tasks.json 文件中的内容替换为以下内容,这将配置 VS Code 使用 MinGW 的 g++ 编译器来编译和运行你的代码:
    {
        "version": "2.0.0",
        "tasks": [
            {
                "label": "build and run",
                "type": "shell",
                "command": "g++",
                "args": [
                    "main.cpp",
                    "-o",
                    "snake.exe", // 输出可执行文件名为 snake.exe
                    "-std=c++11", // 使用 C++11 标准
                    "-Wall",      // 开启所有警告
                    "-Wextra",    // 开启额外警告
                    "-g"          // 生成调试信息
                ],
                "group": {
                    "kind": "build",
                    "isDefault": true
                },
                "presentation": {
                    "reveal": "always",
                    "panel": "new"
                },
                "problemMatcher": {
                    "owner": "cpp",
                    "fileLocation": [
                        "relative",
                        "${workspaceFolder}"
                    ],
                    "pattern": {
                        "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
                        "file": 1,
                        "line": 2,
                        "column": 3,
                        "severity": 4,
                        "message": 5
                    }
                },
                "postBuildTask": {
                    "command": "${workspaceFolder}/snake.exe" // 编译后运行可执行文件
                }
            }
        ]
    }
    
  5. 运行游戏:

    • 保存 main.cpptasks.json 文件。
    • 按下 Ctrl + Shift + B (或 Cmd + Shift + B 在 macOS 上) 来运行 "build and run" 任务。
    • 一个新的终端窗口将在 VS Code 中打开,并显示游戏。

C++ 代码 (main.cpp):

#include <iostream>
#include <vector>
#include <conio.h> // 用于 _kbhit 和 _getch,Windows 特有
#include <windows.h> // 用于 Sleep 和 SetConsoleCursorPosition,Windows 特有
#include <ctime>     // 用于随机数种子
#include <cstdlib>   // 用于 rand 和 srand

// 游戏区域大小
const int WIDTH = 40;
const int HEIGHT = 20;

// 蛇的结构体
struct SnakeSegment {
    int x, y;
};

// 游戏状态
bool gameOver;
std::vector<SnakeSegment> snake;
SnakeSegment food;
int score;
enum Direction { STOP = 0, LEFT, RIGHT, UP, DOWN };
Direction dir;

// 初始化游戏
void Setup() {
    gameOver = false;
    dir = STOP;
    snake.clear();
    snake.push_back({WIDTH / 2, HEIGHT / 2}); // 蛇头在中心
    score = 0;

    // 随机生成食物位置
    srand(time(NULL));
    food.x = rand() % (WIDTH - 2) + 1; // 避免在边框上生成
    food.y = rand() % (HEIGHT - 2) + 1;
}

// 绘制游戏界面
void Draw() {
    // 清空控制台(简单粗暴,但有效)
    // 对于更平滑的动画,可以只重绘变化的部分,但更复杂
    system("cls"); // Windows

    // 绘制上边框
    for (int i = 0; i < WIDTH + 2; i++)
        std::cout << "#";
    std::cout << std::endl;

    for (int i = 0; i < HEIGHT; i++) {
        for (int j = 0; j < WIDTH + 2; j++) {
            if (j == 0 || j == WIDTH + 1) { // 绘制左右边框
                std::cout << "#";
            } else {
                bool isSnake = false;
                // 绘制蛇身
                for (size_t k = 0; k < snake.size(); k++) {
                    if (snake[k].x == j - 1 && snake[k].y == i) {
                        std::cout << "O"; // 蛇身
                        isSnake = true;
                        break;
                    }
                }
                if (!isSnake) {
                    // 绘制食物
                    if (food.x == j - 1 && food.y == i) {
                        std::cout << "$";
                    } else {
                        std::cout << " "; // 空格
                    }
                }
            }
        }
        std::cout << std::endl;
    }

    // 绘制下边框
    for (int i = 0; i < WIDTH + 2; i++)
        std::cout << "#";
    std::cout << std::endl;

    std::cout << "Score: " << score << std::endl;
}

// 获取用户输入
void Input() {
    if (_kbhit()) { // 检查是否有按键按下
        switch (_getch()) { // 获取按键
            case 'a':
                if (dir != RIGHT) dir = LEFT;
                break;
            case 'd':
                if (dir != LEFT) dir = RIGHT;
                break;
            case 'w':
                if (dir != DOWN) dir = UP;
                break;
            case 's':
                if (dir != UP) dir = DOWN;
                break;
            case 'x':
                gameOver = true; // 按x退出游戏
                break;
        }
    }
}

// 游戏逻辑
void Logic() {
    // 记录前一个蛇身位置
    std::vector<SnakeSegment> prevSnake = snake;

    // 移动蛇头
    switch (dir) {
        case LEFT:
            snake[0].x--;
            break;
        case RIGHT:
            snake[0].x++;
            break;
        case UP:
            snake[0].y--;
            break;
        case DOWN:
            snake[0].y++;
            break;
        default:
            break;
    }

    // 移动蛇身
    for (size_t i = 1; i < snake.size(); i++) {
        snake[i] = prevSnake[i - 1];
    }

    // 检查是否碰到墙壁
    if (snake[0].x < 0 || snake[0].x >= WIDTH || snake[0].y < 0 || snake[0].y >= HEIGHT) {
        gameOver = true;
    }

    // 检查是否碰到自身
    for (size_t i = 1; i < snake.size(); i++) {
        if (snake[0].x == snake[i].x && snake[0].y == snake[i].y) {
            gameOver = true;
        }
    }

    // 检查是否吃到食物
    if (snake[0].x == food.x && snake[0].y == food.y) {
        score += 10;
        // 增加蛇的长度
        snake.push_back(prevSnake.back()); // 在尾部添加一个节
        // 重新生成食物
        food.x = rand() % (WIDTH - 2) + 1;
        food.y = rand() % (HEIGHT - 2) + 1;
        // 确保食物不生成在蛇身上
        for (size_t i = 0; i < snake.size(); i++) {
            if (food.x == snake[i].x && food.y == snake[i].y) {
                food.x = rand() % (WIDTH - 2) + 1;
                food.y = rand() % (HEIGHT - 2) + 1;
                i = 0; // 重新检查所有蛇身
            }
        }
    }
}

int main() {
    Setup();
    while (!gameOver) {
        Draw();
        Input();
        Logic();
        Sleep(100); // 控制游戏速度,毫秒
    }

    // 游戏结束界面
    system("cls");
    std::cout << "#########################################" << std::endl;
    std::cout << "#                                       #" << std::endl;
    std::cout << "#           G A M E   O V E R           #" << std::endl;
    std::cout << "#                                       #" << std::endl;
    std::cout << "#           Your Score: " << score << "         #" << std::endl;
    std::cout << "#                                       #" << std::endl;
    std::cout << "#         Press any key to exit         #" << std::endl;
    std::cout << "#                                       #" << std::endl;
    std::cout << "#########################################" << std::endl;
    _getch(); // 等待用户按键退出

    return 0;
}

代码解释:

  • #include <conio.h>#include <windows.h>: 这些是 Windows 特有的头文件。
    • _kbhit(): 检查键盘是否有按键按下,非阻塞。
    • _getch(): 读取按下的字符,不显示在屏幕上,非阻塞。
    • Sleep(): 暂停程序执行一段时间(毫秒)。
    • system("cls"): 清空控制台屏幕(Windows 命令)。
  • WIDTH, HEIGHT: 定义游戏区域的尺寸。
  • SnakeSegment: 结构体,表示蛇的每个身体部分的坐标。
  • gameOver: 布尔变量,控制游戏循环。
  • snake: std::vector<SnakeSegment> 存储蛇的所有身体部分。snake[0] 始终是蛇头。
  • food: SnakeSegment 存储食物的坐标。
  • score: 记录玩家得分。
  • Direction: 枚举类型,表示蛇的移动方向。
  • Setup(): 初始化游戏状态,包括蛇的位置、食物位置、分数等。
  • Draw(): 负责在控制台绘制游戏界面,包括边框、蛇、食物和分数。
  • Input(): 处理用户输入。使用 _kbhit()_getch() 来实现非阻塞的键盘输入,这样游戏就不会因为等待输入而暂停。
  • Logic(): 包含游戏的核心逻辑。
    • 移动蛇头。
    • 根据蛇头的位置移动蛇身。
    • 检查碰撞(墙壁或自身)。
    • 检查是否吃到食物,如果吃到则增加分数、增长蛇身并重新生成食物。
  • main(): 游戏的主循环。
    • 调用 Setup() 初始化。
    • while (!gameOver) 循环中不断调用 Draw(), Input(), Logic()
    • Sleep(100) 控制游戏速度,值越小速度越快。
    • 游戏结束时显示游戏结束界面。

注意事项:

  • 平台依赖性: 这个代码使用了 Windows 特有的 conio.hwindows.h。如果你想在 Linux 或 macOS 上运行,你需要将 _kbhit(), _getch(), Sleep(), system("cls") 替换为相应的跨平台函数或库(例如,对于非阻塞输入可以使用 termios 库,对于清屏可以使用 ANSI 转义序列 \033[2J\033[H,对于延迟可以使用 usleepstd::this_thread::sleep_for)。
  • 图形简陋: 控制台游戏图形非常简陋,只是字符的堆砌。如果需要更丰富的图形,你需要使用专业的图形库(如 SFML, SDL, OpenGL)。
  • 编译速度: g++ main.cpp -o snake.exe 是一个基本的编译命令。tasks.json 中的 args 提供了更多选项,例如 -std=c++11 指定 C++11 标准,-Wall-Wextra 开启所有警告,-g 生成调试信息。

这个版本应该能在你的 Visual Studio Code 环境中顺利运行,祝你玩得开心!