展开菜单
首页 精品内容 本月促销 装机必备 Windows macOS软件 IOS软件 Android AI PDF教程 专题
全部分类

当前位置:

首页 > 编程开发 > C++控制台贪吃蛇制作教程及键盘控制方法

C++控制台贪吃蛇制作教程及键盘控制方法

贪吃蛇游戏在C++中实现的核心在于构建游戏逻辑、图形界面绘制和键盘输入处理。1.游戏基本结构包括蛇(由坐标点组成)、食物(随机生成)和游戏区域(控制台边界)。2.数据结构使用std::vector<std::pair<int,int>>存储蛇的身体,std::pair<int,int>表示食物坐标,枚举类型Direction定义移动方向。3.图形界面通过字符绘制实现,如#表示墙壁,@表示蛇身,$表示食物,并使用system("cls")或system("clear")清

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

怎样用C++制作贪吃蛇游戏 控制台图形和键盘控制

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

怎样用C++制作贪吃蛇游戏 控制台图形和键盘控制

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

怎样用C++制作贪吃蛇游戏 控制台图形和键盘控制

解决方案

  1. 数据结构设计:

    怎样用C++制作贪吃蛇游戏 控制台图形和键盘控制
    • std::vector>存储蛇的身体,每个pair代表一个坐标。
    • std::pair存储食物的坐标。
    • 定义枚举类型enum Direction { UP, DOWN, LEFT, RIGHT }表示蛇的移动方向。
  2. 游戏区域绘制:

    • 使用system("cls")(Windows)或system("clear")(Linux/macOS)清空控制台。
    • 循环输出字符来绘制游戏区域的边界,例如用#表示墙壁。
    • 遍历蛇的身体,用@表示蛇的身体。
    • $表示食物。
  3. 蛇的移动逻辑:

    • 根据当前方向更新蛇头的位置。
    • 将新的蛇头位置添加到snake向量的头部。
    • 如果蛇头吃到了食物,则食物重新生成,否则移除snake向量的尾部,保持蛇的长度不变。
    • 检查蛇头是否撞到墙壁或自己的身体,如果是,则游戏结束。
  4. 键盘输入处理:

    • 使用非阻塞的键盘输入方式,例如Windows下的_kbhit()_getch(),或者Linux/macOS下的ncurses库。
    • 根据按键更新蛇的移动方向。
  5. 游戏循环:

    • 在一个循环中,不断地绘制游戏区域、更新蛇的位置、处理键盘输入。
    • 使用Sleep()(Windows)或usleep()(Linux/macOS)控制游戏速度。
#include 
#include 
#include 
#include 
#include  // Windows
#include 
#include 

using namespace std;

enum Direction { UP, DOWN, LEFT, RIGHT };

int main() {
    // 游戏参数
    int width = 20;
    int height = 10;
    vector> snake = {{width / 2, height / 2}}; // 初始蛇的位置
    pair 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 
#include 

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 

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

如何为贪吃蛇添加更多的游戏元素,例如障碍物、加速道具等?

  1. 障碍物:

    • std::vector>存储障碍物的坐标。
    • 在游戏区域绘制时,将障碍物绘制出来,例如用X表示。
    • 在蛇移动时,检查蛇头是否撞到障碍物,如果是,则游戏结束。
    • 随机生成障碍物,但要避免障碍物出现在蛇的初始位置或食物的位置。
  2. 加速道具:

    • std::pair存储加速道具的坐标。
    • 在游戏区域绘制时,将加速道具绘制出来,例如用!表示。
    • 当蛇吃到加速道具时,增加蛇的移动速度,例如减少Sleep()usleep()的延时时间。
    • 设置加速道具的持续时间,在持续时间结束后,恢复蛇的正常速度。
    • 可以添加一个变量来控制蛇的速度,例如int speed = 100;,然后this_thread::sleep_for(chrono::milliseconds(speed));,吃到加速道具时,减小speed的值,道具效果结束时,恢复speed的值。
  3. 随机生成:

    • 使用rand() % widthrand() % height生成随机坐标。
    • 确保新生成的游戏元素(障碍物、食物、加速道具)不会出现在蛇的身体里。
    • 可以设置生成概率,例如每隔一段时间生成一个障碍物或加速道具。
      #include 
      #include 
      #include 
      #include 
      #include  // Windows
      #include 
      #include 
      #include 

using namespace std;

enum Direction { UP, DOWN, LEFT, RIGHT };

int main() { // 游戏参数 int width = 20; int height = 10; vector> snake = {{width / 2, height / 2}}; // 初始蛇的位置 pair food; Direction dir = RIGHT; bool gameOver = false; int score = 0; int speed = 100; // 初始速度,毫秒 vector> 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 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++
相关文章 更多
精品专题 更多
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

IOS软件

正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

AI

正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

PDF教程

PDF教程适合刚接触PDF文件的用户,本文整理PDF打开、编辑、转换、合并、压缩等常见基础操作。通过这些教程可以快速了解PDF文件怎么处理,解决办公、学习和资料科整理中的常见问题。使用极轻PDF可在线完成多种PDF操作,适合新手快速上手。

Mac软件 更多
灵活计算器
灵活计算器

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

赤友清理大师
赤友清理大师

赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

图几
图几

图几是一款适用于 macOS 的截图、标注与美化工具,支持离线操作保障隐私。界面整理和高频系统操作被放到一起考虑,桌面或窗口内容一多时,管理起来会更省心。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Menuist
Menuist

Menuist 是一款面向 macOS 的 Finder 右键菜单增强工具,主要用来补充新建文件、快捷导航等常用操作,让日常文件管理和访问路径时更高效、更顺手。

Mole
Mole

Mole 是一款专为 Mac 设计的深度清理优化工具,涵盖缓存清理、应用管理及实时状态监控等功能。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

WINDOWS 更多
Windows 10
Windows 10

Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

傲梅轻松备份
傲梅轻松备份

傲梅轻松备份是一款专业易用的数据备份软件,为重要数据提供安全保障。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

Wise Folder Hider Pro
Wise Folder Hider Pro

Wise Folder Hider Pro 是一款专业级文件和文件夹隐藏加密软件,为私密数据添加多重保护。高频操作更强调就近处理,浏览、整理和跨目录移动文件时,来回切换和重复点击都会少很多。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

PinStack
PinStack

PinStack是一款轻量级的Windows平台剪贴板管理工具,优化您的剪贴板使用体验。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Seer
Seer

Seer是一款在Win平台下的空格键功能增强效率工具,只需轻敲空格键,就能预览几乎任何格式的文件。它更适合把零散的小功能集中起来使用,处理高频琐碎任务时会更省事。