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