用 C++ 类来写贪吃蛇:Snake 类管身体和移动,主函数管输入和渲染。顺便体会 deque 双端队列为什么天生适合当蛇身。

1. Snake 类与 deque

蛇身用 deque<Pos> 存,头在 front。移动 = 新头插前、吃到食物不弹尾就变长。方向用枚举防止"直接反向":

#include <iostream>
#include <deque>
using namespace std;

struct Pos { int x, y; };
enum Dir { UP, DOWN, LEFT, RIGHT };

class Snake {
    deque<Pos> body;
    Dir dir = RIGHT;
public:
    Snake() { body.push_back({5, 5}); body.push_back({4, 5}); body.push_back({3, 5}); }
    Pos head() const { return body.front(); }
    void setDir(Dir d) {
        if ((d == UP && dir != DOWN) || (d == DOWN && dir != UP) ||
            (d == LEFT && dir != RIGHT) || (d == RIGHT && dir != LEFT)) dir = d;
    }
    void move(bool grow) {
        Pos h = head(), n = h;
        if (dir == UP) n.y--;
        else if (dir == DOWN) n.y++;
        else if (dir == LEFT) n.x--;
        else n.x++;
        body.push_front(n);
        if (!grow) body.pop_back();
    }
    bool hits(const Pos &p) const {
        for (auto &s : body) if (s.x == p.x && s.y == p.y) return true;
        return false;
    }
};

2. 食物与主循环

食物随机生成,避开蛇身。每步:读方向键 → 判断是否吃到食物 → 移动 → 检查撞墙/撞自己:

const int W = 20, H = 12;
Snake snake;
Pos food;
int score = 0;

void place_food() {
    do { food = {rand() % W, rand() % H}; }
    while (snake.hits(food));
}

int main() {
    srand((unsigned)time(NULL));
    place_food();
    char key;
    while (true) {
        // 绘制 + 读键 + 移动 + 判定(见完整代码)
        Pos nh = snake.head();
        if (nh.x < 0 || nh.x >= W || nh.y < 0 || nh.y >= H) { cout << "撞墙!\n"; break; }
    }
}

3. 完整代码

#include <iostream>
#include <deque>
#include <cstdlib>
#include <ctime>
using namespace std;

struct Pos { int x, y; };
enum Dir { UP, DOWN, LEFT, RIGHT };

class Snake {
    deque<Pos> body;
    Dir dir = RIGHT;
public:
    Snake() { body.push_back({5, 5}); body.push_back({4, 5}); body.push_back({3, 5}); }
    Pos head() const { return body.front(); }
    void setDir(Dir d) {
        if ((d == UP && dir != DOWN) || (d == DOWN && dir != UP) ||
            (d == LEFT && dir != RIGHT) || (d == RIGHT && dir != LEFT)) dir = d;
    }
    void move(bool grow) {
        Pos h = head(), n = h;
        if (dir == UP) n.y--;
        else if (dir == DOWN) n.y++;
        else if (dir == LEFT) n.x--;
        else n.x++;
        body.push_front(n);
        if (!grow) body.pop_back();
    }
    bool hits(const Pos &p) const {
        for (auto &s : body) if (s.x == p.x && s.y == p.y) return true;
        return false;
    }
    int len() const { return (int)body.size(); }
};

const int W = 20, H = 12;
Snake snake;
Pos food;
int score = 0;

void place_food() {
    do { food = {rand() % W, rand() % H}; }
    while (snake.hits(food));
}

void draw() {
    system("clear");   // Windows: system("cls")
    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            Pos p = {x, y};
            if (p.x == food.x && p.y == food.y) cout << "F";
            else if (snake.hits(p)) cout << "S";
            else cout << ".";
        }
        cout << "\n";
    }
    cout << "分数 " << score << "  wasd移动 q退出\n";
}

int main() {
    srand((unsigned)time(NULL));
    place_food();
    char key;
    while (true) {
        draw();
        cin >> key;
        if (key == 'q') break;
        if (key == 'w') snake.setDir(UP);
        else if (key == 's') snake.setDir(DOWN);
        else if (key == 'a') snake.setDir(LEFT);
        else if (key == 'd') snake.setDir(RIGHT);
        Pos h = snake.head();
        bool grow = false;
        snake.move(grow);
        Pos nh = snake.head();
        if (nh.x < 0 || nh.x >= W || nh.y < 0 || nh.y >= H) { cout << "撞墙,游戏结束\n"; break; }
        if (snake.hits(nh) && !(nh.x == h.x && nh.y == h.y) && snake.len() > 1) {
            cout << "咬到自己,游戏结束\n"; break;
        }
        if (nh.x == food.x && nh.y == food.y) {
            snake.move(true);   // 变长
            score += 10;
            place_food();
        }
    }
    return 0;
}

4. 运行与常见问题

保存为 snake.cpp,g++ snake.cpp -o snake 后运行。常见问题:①吃食物没变长——先判断是否吃到,再 move(true) 补一次;②不能掉头——方向锁在 setDir 里判断;③自撞误判——新头与旧头重合时不算撞。

💡 改进方向:①自动下落(非阻塞输入);②障碍物关卡;③最高分存档;④穿墙模式;⑤道具。