c++贪吃蛇(可优化)

· · 休闲·娱乐

到dev-c++上运行,其中一半用豆包写的

#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <conio.h>
#include <windows.h>

using namespace std;

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

// 定义坐标结构体
struct Point {
    int x, y;
    Point(int _x = 0, int _y = 0) : x(_x), y(_y) {}
};

// 定义食物结构体,包含位置和对应的字母
struct Food {
    Point pos;
    char letter;
    Food(int x, int y, char l) : pos(x, y), letter(l) {}
};

// 定义蛇类
class Snake {
private:
    vector<Point> body;
    vector<char> bodyLetters;  // 新增:存储蛇身体各部分对应的字母
    Direction dir;
    bool alive;
    int score;

public:
    Snake(int x, int y) {
        body.push_back(Point(x, y));
        bodyLetters.push_back('O');  // 蛇头用大写 O 表示
        dir = RIGHT;
        alive = true;
        score = 0;
    }

    void changeDirection(Direction newDir) {
        if ((dir == UP && newDir != DOWN) ||
            (dir == DOWN && newDir != UP) ||
            (dir == LEFT && newDir != RIGHT) ||
            (dir == RIGHT && newDir != LEFT)) {
            dir = newDir;
        }
    }

    void move() {
        Point head = body.front();
        switch (dir) {
        case UP: head.y--; break;
        case DOWN: head.y++; break;
        case LEFT: head.x--; break;
        case RIGHT: head.x++; break;
        }
        body.insert(body.begin(), head);
        bodyLetters.insert(bodyLetters.begin(), 'O');  // 新的蛇头是大写 O
        body.pop_back();
        bodyLetters.pop_back();
    }

    void grow(char letter) {
        Point tail = body.back();
        body.push_back(tail);
        bodyLetters.push_back(letter);  // 增长的身体使用吃到的字母
        score++;
    }

    Point getHead() const {
        return body.front();
    }

    vector<Point> getBody() const {
        return body;
    }

    vector<char> getBodyLetters() const {
        return bodyLetters;
    }

    bool isAlive() const {
        return alive;
    }

    int getScore() const {
        return score;
    }

    void checkCollision(int width, int height, vector<Food>& foods) {
        Point head = getHead();
        // 检查边界碰撞
        if (head.x <= 0 || head.x >= width - 1 || head.y <= 0 || head.y >= height - 1) {
            alive = false;
            return;
        }
        // 检查身体碰撞
        for (size_t i = 1; i < body.size(); i++) {
            if (head.x == body[i].x && head.y == body[i].y) {
                // 去除重叠部分
                body.erase(body.begin() + i, body.end());
                bodyLetters.erase(bodyLetters.begin() + i, bodyLetters.end());
                break;
            }
        }
        // 检查食物碰撞
        for (size_t i = 0; i < foods.size(); i++) {
            if (head.x == foods[i].pos.x && head.y == foods[i].pos.y) {
                grow(foods[i].letter);
                foods.erase(foods.begin() + i);
                break;
            }
        }
    }
};

// 生成随机食物
Food generateFood(int width, int height, const vector<Point>& snakeBody, const vector<Food>& existingFoods) {
    Point foodPos;
    bool valid;
    char randomLetter = 'a' + rand() % 26;  // 生成随机小写字母
    do {
        valid = true;
        foodPos.x = rand() % (width - 2) + 1;
        foodPos.y = rand() % (height - 2) + 1;
        // 检查是否与蛇身体或现有食物重叠
        for (size_t i = 0; i < snakeBody.size(); i++) {
            if (foodPos.x == snakeBody[i].x && foodPos.y == snakeBody[i].y) {
                valid = false;
                break;
            }
        }
        if (valid) {
            for (size_t i = 0; i < existingFoods.size(); i++) {
                if (foodPos.x == existingFoods[i].pos.x && foodPos.y == existingFoods[i].pos.y) {
                    valid = false;
                    break;
                }
            }
        }
    } while (!valid);
    return Food(foodPos.x, foodPos.y, randomLetter);
}

// 清屏函数
void clearScreen() {
    HANDLE hOut;
    COORD Position;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    Position.X = 0;
    Position.Y = 0;
    SetConsoleCursorPosition(hOut, Position);
}

// 绘制游戏界面
void draw(int width, int height, const Snake& snake, const vector<Food>& foods) {
    clearScreen();
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            if (x == 0 || x == width - 1 || y == 0 || y == height - 1) {
                cout << '#';
            } else {
                bool isSnake = false;
                const vector<Point> snakeBody = snake.getBody();
                const vector<char> snakeLetters = snake.getBodyLetters();
                for (size_t i = 0; i < snakeBody.size(); i++) {
                    if (snakeBody[i].x == x && snakeBody[i].y == y) {
                        cout << snakeLetters[i];
                        isSnake = true;
                        break;
                    }
                }
                if (!isSnake) {
                    bool isFood = false;
                    for (size_t i = 0; i < foods.size(); i++) {
                        if (foods[i].pos.x == x && foods[i].pos.y == y) {
                            cout << foods[i].letter;
                            isFood = true;
                            break;
                        }
                    }
                    if (!isFood) {
                        cout << '.';
                    }
                }
            }
        }
        cout << endl;
    }
    cout << "Score: " << snake.getScore() << endl;
}

int main() {
    srand(time(NULL));
    const int width = 20;
    const int height = 20;
    Snake snake(width / 2, height / 2);
    vector<Food> foods;

    // 初始化 5 个食物
    for (int i = 0; i < 5; i++) {
        foods.push_back(generateFood(width, height, snake.getBody(), foods));
    }

    while (snake.isAlive()) {
        if (_kbhit()) {
            char ch = _getch();
            switch (ch) {
            case 'w': snake.changeDirection(UP); break;
            case 's': snake.changeDirection(DOWN); break;
            case 'a': snake.changeDirection(LEFT); break;
            case 'd': snake.changeDirection(RIGHT); break;
            }
        }
        snake.move();
        snake.checkCollision(width, height, foods);
        // 确保始终有 5 个食物
        while (foods.size() < 5) {
            foods.push_back(generateFood(width, height, snake.getBody(), foods));
        }
        draw(width, height, snake, foods);
        Sleep(100);
    }

    cout << "Game Over! Final Score: " << snake.getScore() << endl;
    return 0;
}

如果你感兴趣的话也可以看看我的其他作品

扫雷

乒乓球游戏

口袋奇兵

逃离后室游戏

可以点个赞吗