【C语言】贪吃蛇小游戏 丨源码+解析

发布于:2025-06-18 ⋅ 阅读:(21) ⋅ 点赞:(0)

代码说明与要点

1. 核心数据结构

  • 游戏区域​:使用二维字符数组board[WIDTH][HEIGHT]表示
  • 蛇体​:蛇头用Position结构,蛇身用Position数组存储
  • 方向控制​:枚举类型Direction管理移动方向

2. 关键函数功能

函数 功能 复习要点
initGame() 初始化游戏状态 边界生成、蛇初始位置、食物生成
drawGame() 渲染游戏界面 使用system("cls")清屏实现动画效果
controlInput() 处理键盘输入 _kbhit()_getch()的非阻塞输入处理
updateGame() 更新游戏逻辑 蛇身移动算法、碰撞检测、吃食物判定
generateFood() 随机生成食物 确保食物不在墙上或蛇身上

3. 核心算法实现

  • 蛇身移动​:从尾部向前逐节更新位置
  • 碰撞检测​:
    • 墙壁碰撞:检查坐标是否在边界内
    • 自身碰撞:遍历蛇身坐标比对
  • 食物生成​:使用rand()在合法区域随机生成

4. 编译运行说明

  1. 环境要求​:Windows系统 + 支持conio.h的编译器(如GCC/MinGW)
  2. 编译命令​:
    gcc snake_game.c -o snake.exe
  3. 控制方式​:
    • WASD键控制方向
    • X键退出游戏
    • 吃到食物($)得分,撞墙或自身游戏结束

5. 扩展建议

  1. 难度分级​:通过修改Sleep()参数调整游戏速度
  2. 高分记录​:添加文件I/O保存历史最高分
  3. 游戏暂停​:增加空格键暂停功能
  4. 视觉效果​:使用Windows API添加颜色支持

游戏完整演示:蛇初始长度3分,通过吃食物增加长度和分数,移动速度恒定150ms/帧。

游戏结束显示最终得分

此实现包含了贪吃蛇的核心逻辑,代码结构清晰,适合学习游戏循环设计、状态管理和控制台交互编程。复习时可重点关注游戏状态机转换蛇身移动算法的实现细节。

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>   // 键盘输入处理
#include <windows.h> // 控制台操作和延时
#include <time.h>    // 随机数种子
#include <stdbool.h> // 布尔类型支持

// 游戏区域尺寸
#define WIDTH 40
#define HEIGHT 20

// 游戏元素符号
#define BLANK ' '
#define WALL '#'
#define SNAKE_HEAD '@'
#define SNAKE_BODY 'o'
#define FOOD '$'

// 方向控制
enum Direction { STOP = 0, LEFT, RIGHT, UP, DOWN };
enum GameState { RUNNING, GAME_OVER, WIN };

// 坐标结构
struct Position {
    int x;
    int y;
};

// 全局游戏状态
int score = 0;
int snakeLength = 3;
enum Direction dir = RIGHT;
enum GameState state = RUNNING;
struct Position head;
struct Position body[WIDTH * HEIGHT];
struct Position food;
char board[WIDTH][HEIGHT];

// 函数声明
void initGame();
void drawGame();
void updateGame();
void controlInput();
void generateFood();
bool checkCollision();
void gameOver();

int main() {
    srand((unsigned int)time(NULL)); // 随机数种子
    initGame();
    
    while (state == RUNNING) {
        drawGame();
        controlInput();
        updateGame();
        Sleep(150); // 控制游戏速度
    }
    
    if (state == GAME_OVER) {
        gameOver();
    }
    return 0;
}

// 初始化游戏
void initGame() {
    // 初始化游戏区域
    for (int x = 0; x < WIDTH; x++) {
        for (int y = 0; y < HEIGHT; y++) {
            if (x == 0 || x == WIDTH - 1 || y == 0 || y == HEIGHT - 1) {
                board[x][y] = WALL; // 边界墙
            } else {
                board[x][y] = BLANK; // 空白区域
            }
        }
    }
    
    // 初始化蛇位置(居中)
    head.x = WIDTH / 2;
    head.y = HEIGHT / 2;
    board[head.x][head.y] = SNAKE_HEAD;
    
    // 初始化蛇身
    for (int i = 0; i < snakeLength; i++) {
        body[i].x = head.x - i - 1;
        body[i].y = head.y;
        board[body[i].x][body[i].y] = SNAKE_BODY;
    }
    
    // 生成第一个食物
    generateFood();
}

// 绘制游戏界面
void drawGame() {
    system("cls"); // 清屏
    
    // 绘制游戏区域
    for (int y = 0; y < HEIGHT; y++) {
        for (int x = 0; x < WIDTH; x++) {
            printf("%c", board[x][y]);
        }
        printf("\n");
    }
    
    // 显示分数
    printf("Score: %d\n", score);
    printf("Controls: WASD to move, X to quit\n");
}

// 处理用户输入
void controlInput() {
    if (_kbhit()) { // 检测键盘输入
        switch (_getch()) {
            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': state = GAME_OVER; break;
        }
    }
}

// 生成食物
void generateFood() {
    int x, y;
    do {
        x = rand() % (WIDTH - 2) + 1;
        y = rand() % (HEIGHT - 2) + 1;
    } while (board[x][y] != BLANK); // 确保位置为空
    
    food.x = x;
    food.y = y;
    board[x][y] = FOOD;
}

// 更新游戏状态
void updateGame() {
    // 保存旧尾部位置
    struct Position prevTail = body[snakeLength - 1];
    
    // 移动蛇身(从尾部向前更新)
    for (int i = snakeLength - 1; i > 0; i--) {
        body[i] = body[i - 1];
        board[body[i].x][body[i].y] = SNAKE_BODY;
    }
    body[0] = head; // 新的第一节身体
    
    // 根据方向移动蛇头
    switch (dir) {
        case UP:    head.y--; break;
        case DOWN:  head.y++; break;
        case LEFT:  head.x--; break;
        case RIGHT: head.x++; break;
    }
    
    // 检测碰撞
    if (checkCollision()) {
        state = GAME_OVER;
        return;
    }
    
    // 检查是否吃到食物
    if (head.x == food.x && head.y == food.y) {
        score += 10;
        snakeLength++;
        board[prevTail.x][prevTail.y] = SNAKE_BODY; // 保留尾部
        generateFood();
    } else {
        // 清除旧尾部
        board[prevTail.x][prevTail.y] = BLANK;
    }
    
    // 更新蛇头位置
    board[head.x][head.y] = SNAKE_HEAD;
}

// 碰撞检测
bool checkCollision() {
    // 撞墙检测
    if (head.x <= 0 || head.x >= WIDTH - 1 || 
        head.y <= 0 || head.y >= HEIGHT - 1) {
        return true;
    }
    
    // 撞自身检测
    for (int i = 0; i < snakeLength; i++) {
        if (head.x == body[i].x && head.y == body[i].y) {
            return true;
        }
    }
    
    return false;
}

// 游戏结束处理
void gameOver() {
    system("cls");
    printf("========================\n");
    printf("      GAME OVER!\n");
    printf("   Final Score: %d\n", score);
    printf("========================\n");
    printf("Press any key to exit...");
    _getch(); // 等待按键退出
}

资源推荐:

C/C++学习交流君羊 << 点击加入

C/C++教程

C/C++学习路线,就业咨询,技术提升


网站公告

今日签到

点亮在社区的每一天
去签到