首页 电商直播

C语言实战:从零实现经典贪吃蛇游戏(附源码)

分类:电商直播
字数: (0598)
阅读: (4339)
内容摘要:C语言实战:从零实现经典贪吃蛇游戏(附源码),

作为程序员的我们,小时候一定都玩过贪吃蛇这个经典游戏。今天我们就用 C 语言来重温经典,手把手教你实现一个简单的贪吃蛇游戏。这不仅能帮助你巩固 C 语言基础,还能让你体会到游戏开发的乐趣。

需求分析与设计

在开始编写代码之前,我们需要先明确游戏的需求和整体设计。

C语言实战:从零实现经典贪吃蛇游戏(附源码)
  1. 游戏界面: 使用控制台来模拟游戏界面,用字符来表示蛇、食物和墙壁。
  2. 蛇的移动: 通过读取键盘输入来控制蛇的移动方向。
  3. 食物生成: 随机在游戏界面上生成食物。
  4. 碰撞检测: 检测蛇是否撞到墙壁或者自身。
  5. 游戏逻辑: 根据游戏规则更新游戏状态,例如蛇吃到食物后长度增加,游戏结束等。

底层原理深度剖析

贪吃蛇游戏的核心在于对游戏数据的维护和更新。蛇的身体可以用一个链表来表示,每个节点存储蛇身体的一个坐标。食物的位置可以用两个变量分别存储 x 和 y 坐标。游戏界面的显示可以通过二维数组来实现,每个元素存储该位置上的对象类型(蛇、食物、墙壁、空地)。

C语言实战:从零实现经典贪吃蛇游戏(附源码)

游戏循环

游戏的主循环是游戏的灵魂。在每次循环中,我们需要做以下几件事情:

C语言实战:从零实现经典贪吃蛇游戏(附源码)
  1. 读取用户输入: 使用 getch() 函数(需要包含 conio.h 头文件)来读取用户的键盘输入。
  2. 更新蛇的位置: 根据用户输入的方向,更新蛇的头部位置。同时,删除蛇尾,实现蛇的移动效果。如果蛇吃到了食物,则不删除蛇尾,实现蛇的增长。
  3. 碰撞检测: 检测蛇是否撞到了墙壁或者自身。如果撞到,则游戏结束。
  4. 绘制游戏界面: 根据游戏数据,将游戏界面绘制到控制台上。
  5. 延时: 使用 Sleep() 函数(需要包含 windows.h 头文件,Linux 下可用 usleep())来控制游戏速度。

具体代码实现

下面是代码示例,为了更清晰地展示,我们将代码分为几个部分。

C语言实战:从零实现经典贪吃蛇游戏(附源码)

1. 头文件和宏定义

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>  // 用于 getch()
#include <windows.h> // 用于 Sleep()
#include <time.h>   // 用于随机数生成

#define WIDTH 20  // 游戏界面宽度
#define HEIGHT 15 // 游戏界面高度

2. 数据结构定义

// 蛇的节点
typedef struct SnakeNode {
    int x, y;
    struct SnakeNode* next;
} SnakeNode;

// 全局变量
SnakeNode* snakeHead; // 蛇头指针
int foodX, foodY;     // 食物坐标
int score = 0;        // 游戏得分
bool gameOver = false;   // 游戏结束标志

3. 初始化游戏

void initGame() {
    // 初始化随机数种子
    srand(time(NULL));

    // 初始化蛇
    snakeHead = (SnakeNode*)malloc(sizeof(SnakeNode));
    snakeHead->x = WIDTH / 2;
    snakeHead->y = HEIGHT / 2;
    snakeHead->next = NULL;

    // 初始化食物
    foodX = rand() % WIDTH;
    foodY = rand() % HEIGHT;
}

4. 绘制游戏界面

void drawMap() {
    system("cls"); // 清屏

    // 绘制上边界
    for (int i = 0; i < WIDTH + 2; i++) {
        printf("#");
    }
    printf("\n");

    // 绘制游戏区域
    for (int i = 0; i < HEIGHT; i++) {
        printf("#"); // 左边界
        for (int j = 0; j < WIDTH; j++) {
            if (i == foodY && j == foodX) {
                printf("*"); // 食物
            } else {
                // 检查是否是蛇身体的一部分
                bool isSnake = false;
                SnakeNode* current = snakeHead;
                while (current != NULL) {
                    if (current->x == j && current->y == i) {
                        printf("O"); // 蛇身
                        isSnake = true;
                        break;
                    }
                    current = current->next;
                }

                if (!isSnake) {
                    printf(" "); // 空地
                }
            }
        }
        printf("#\n"); // 右边界
    }

    // 绘制下边界
    for (int i = 0; i < WIDTH + 2; i++) {
        printf("#");
    }
    printf("\n");

    printf("Score: %d\n", score);
}

5. 控制蛇的移动

enum Direction { UP, DOWN, LEFT, RIGHT };
int currentDirection = RIGHT; // 初始方向

void handleInput() {
    if (_kbhit()) { // 检查是否有按键按下
        char key = _getch();
        switch (key) {
            case 'w':
                currentDirection = UP;
                break;
            case 's':
                currentDirection = DOWN;
                break;
            case 'a':
                currentDirection = LEFT;
                break;
            case 'd':
                currentDirection = RIGHT;
                break;
            case 'q': // 退出游戏
                gameOver = true;
                break;
        }
    }
}

void moveSnake() {
    int newX = snakeHead->x;
    int newY = snakeHead->y;

    switch (currentDirection) {
        case UP:
            newY--;
            break;
        case DOWN:
            newY++;
            break;
        case LEFT:
            newX--;
            break;
        case RIGHT:
            newX++;
            break;
    }

    // 碰撞检测
    if (newX < 0 || newX >= WIDTH || newY < 0 || newY >= HEIGHT) {
        gameOver = true;
        return;
    }

    // 检查是否撞到自身
    SnakeNode* current = snakeHead;
    while (current != NULL) {
        if (current->x == newX && current->y == newY) {
            gameOver = true;
            return;
        }
        current = current->next;
    }

    // 创建新蛇头
    SnakeNode* newHead = (SnakeNode*)malloc(sizeof(SnakeNode));
    newHead->x = newX;
    newHead->y = newY;
    newHead->next = snakeHead;
    snakeHead = newHead;

    // 检查是否吃到食物
    if (newX == foodX && newY == foodY) {
        score += 10;
        foodX = rand() % WIDTH;
        foodY = rand() % HEIGHT;
    } else {
        // 删除蛇尾
        SnakeNode* tail = snakeHead;
        SnakeNode* prev = NULL;
        while (tail->next != NULL) {
            prev = tail;
            tail = tail->next;
        }
        free(tail);
        prev->next = NULL;
    }
}

6. 游戏主循环

int main() {
    initGame();

    while (!gameOver) {
        drawMap();
        handleInput();
        moveSnake();
        Sleep(100); // 控制游戏速度
    }

    printf("Game Over! Your score: %d\n", score);
    return 0;
}

实战避坑经验总结

  1. conio.h 兼容性问题: conio.h 是 Windows 平台下的头文件,在 Linux 平台下需要使用其他方式实现 getch() 函数的功能。可以使用 curses 库,或者自定义一个非阻塞读取键盘输入的函数。
  2. 内存泄漏: 在游戏结束时,需要释放蛇的链表占用的内存,避免内存泄漏。可以在 main 函数的末尾添加释放内存的代码。
  3. 游戏速度控制: Sleep() 函数的精度有限,可能会导致游戏速度不稳定。可以考虑使用更精确的计时器来控制游戏速度。
  4. 调试技巧:使用 GDB 调试 C 代码可以帮助你快速定位问题。学会设置断点,单步执行,查看变量的值,对于理解代码的执行流程和排查 Bug 非常重要。

这个 C语言实战贪吃蛇项目只是一个简单的实现,你可以根据自己的想法进行扩展,例如添加难度选择、音效、排行榜等功能。希望这个教程能够帮助你入门 C 语言游戏开发!

C语言实战:从零实现经典贪吃蛇游戏(附源码)

转载请注明出处: 代码一只喵

本文的链接地址: http://m.acea1.store/blog/421303.SHTML

本文最后 发布于2026-04-10 04:56:08,已经过了17天没有更新,若内容或图片 失效,请留言反馈

()
您可能对以下文章感兴趣
评论
  • 红豆沙 4 天前
    代码注释很详细,点赞! 避坑经验也很实用,解决了我在 Linux 下编译 `conio.h` 报错的问题。
  • e人代表 6 天前
    楼主太强了,用 C 语言也能写出这么好玩的游戏!膜拜!
  • 山西刀削面 6 天前
    感谢分享!之前一直想自己写一个贪吃蛇,但不知道从哪里下手,这篇教程给了我很大的帮助。
  • 咖啡不加糖 1 天前
    楼主太强了,用 C 语言也能写出这么好玩的游戏!膜拜!