Linux C++ 贪吃蛇游戏 -- 方向键控制蛇移动

1. 代码

#include <iostream>
#include <ncurses.h>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <thread>

using namespace std;

// 定义方向
enum class Direction { UP, DOWN, LEFT, RIGHT };

class SnakeGame {
public:
    SnakeGame(int width, int height) : width(width), height(height), score(0), gameover(false) {
        srand(time(nullptr));
        initscr(); // 初始化终端
        keypad(stdscr, true); // 启用键盘输入
        noecho(); // 关闭回显
        nodelay(stdscr, true); // 非阻塞模式
        curs_set(0); // 隐藏光标
        getmaxyx(stdscr, max_y, max_x);
        window = newwin(height, width, (max_y - height) / 2, (max_x - width) / 2);
        box(window, 0, 0); // 绘制窗口边框
        refresh();
        wrefresh(window);
        generateFood();
        snake.push_back(make_pair(height / 2, width / 2)); // 初始化贪吃蛇位置
        drawSnake();
    }

    ~SnakeGame() {
        delwin(window);
        endwin();
    }

    void run() {
        // 游戏循环
        while (!gameover) {
            int ch = getch();
            handleInput(ch);
            moveSnake();
            checkCollision();
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
        showGameOver();
    }

private:
    int width, height;
    int score;
    bool gameover;
    int max_x, max_y;
    WINDOW *window;
    vector<pair<int, int>> snake;
    pair<int, int> food;
    Direction direction = Direction::RIGHT;

    void generateFood() {
        do {
            food.first = rand() % (height - 2) + 1;
            food.second = rand() % (width - 2) + 1;
        } while (isSnakeCell(food.first, food.second));
        mvwaddch(window, food.first, food.second, '@');
        refresh();
        wrefresh(window);
    }

    void drawSnake() {
        for (const auto& cell : snake) {
            mvwaddch(window, cell.first, cell.second, '#');
        }
        refresh();
        wrefresh(window);
    }

    void moveSnake() {
        pair<int, int> head = snake.front();
        pair<int, int> newHead = head;

        switch (direction) {
            case Direction::UP:
                newHead.first--;
                break;
            case Direction::DOWN:
                newHead.first++;
                break;
            case Direction::LEFT:
                newHead.second--;
                break;
            case Direction::RIGHT:
                newHead.second++;
                break;
        }

        snake.insert(snake.begin(), newHead);
        mvwaddch(window, newHead.first, newHead.second, '#');
        refresh();
        wrefresh(window);

        if (newHead != food) {
            mvwaddch(window, snake.back().first, snake.back().second, ' ');
            snake.pop_back();
        } else {
            score++;
            generateFood();
        }
    }

    void handleInput(int ch) {
        switch (ch) {
            case KEY_UP:
                if (direction != Direction::DOWN) {
                    direction = Direction::UP;
                }
                break;
            case KEY_DOWN:
                if (direction != Direction::UP) {
                    direction = Direction::DOWN;
                }
                break;
            case KEY_LEFT:
                if (direction != Direction::RIGHT) {
                    direction = Direction::LEFT;
                }
                break;
            case KEY_RIGHT:
                if (direction != Direction::LEFT) {
                    direction = Direction::RIGHT;
                }
                break;
        }
    }

    void checkCollision() {
        pair<int, int> head = snake.front();

        // 检查是否撞墙
        if (head.first == 0 || head.first == height - 1 || head.second == 0 || head.second == width - 1) {
            gameover = true;
            return;
        }

        // 检查是否撞到自己的身体
        for (size_t i = 1; i < snake.size(); i++) {
            if (snake[i] == head) {
                gameover = true;
                return;
            }
        }
    }

    void showGameOver() {
        clear();
        string gameOverText = "Game Over!";
        mvprintw(max_y / 2, (max_x - gameOverText.length()) / 2, gameOverText.c_str());
        string scoreText = "Score: " + to_string(score);
        mvprintw(max_y / 2 + 1, (max_x - scoreText.length()) / 2, scoreText.c_str());
        refresh();
        getch();
    }

    bool isSnakeCell(int row, int col) {
        for (const auto& cell : snake) {
            if (cell.first == row && cell.second == col) {
                return true;
            }
        }
        return false;
    }
};

int main() {
    SnakeGame game(40, 20);
    game.run();
    return 0;
}

2. 编译命令

alfred@ubuntu:~/c_learning/d_cplusplus_learning$ g++ -std=c++11 snake.cpp -o snake -lncurses

3. 运行游戏,使用方向键 ↑ ↓ ← → 上下左右控制蛇移动

alfred@ubuntu:~/c_learning/d_cplusplus_learning$ ./snake

4. 调整蛇移动的速度

修改延时时间100,单位为ms,数字越小,移动越快,修改完后重新编译,运行

std::this_thread::sleep_for(std::chrono::milliseconds(100));

相关推荐

  1. Linux C++ 贪吃游戏 -- 方向控制移动

    2023-12-09 02:16:02       57 阅读
  2. 控制台游戏制作——贪吃

    2023-12-09 02:16:02       19 阅读
  3. 贪吃游戏

    2023-12-09 02:16:02       54 阅读
  4. 贪吃游戏

    2023-12-09 02:16:02       47 阅读
  5. 贪吃游戏

    2023-12-09 02:16:02       47 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-09 02:16:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-09 02:16:02       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-09 02:16:02       82 阅读
  4. Python语言-面向对象

    2023-12-09 02:16:02       91 阅读

热门阅读

  1. SkyPile-150B 数据下载地址

    2023-12-09 02:16:02       54 阅读
  2. Spring中拦截WebSecurityConfigurerAdapter和Aop拦截区分

    2023-12-09 02:16:02       60 阅读
  3. 计算三位数每位上数字的和

    2023-12-09 02:16:02       57 阅读
  4. 理想中的PC端剪切板工具,应该有哪些功能?

    2023-12-09 02:16:02       67 阅读
  5. QT 中 线程池 (备查)

    2023-12-09 02:16:02       67 阅读
  6. Copilot使用指南:提升编程效率的智能助手

    2023-12-09 02:16:02       89 阅读
  7. NTP时钟同步服务器(校时服务器)技术参数分享

    2023-12-09 02:16:02       52 阅读
  8. v-model和:model的区别

    2023-12-09 02:16:02       54 阅读