从零开始写贪吃蛇游戏(C语言控制台版)

一、前言

贪吃蛇是一款经典的小游戏,玩家通过键盘控制蛇的移动,吃掉随机出现的食物,同时避免撞到墙壁或自己的身体。本文将从零开始,使用C语言在Windows控制台下实现一个贪吃蛇游戏。我们将使用Windows API进行光标定位和按键检测,并利用宽字符显示图形界面,使游戏更加生动。

二、开发环境

PixPin_2026-02-18_18-40-22

  • 操作系统:Windows
  • 编译器:Visual Studio(或其他支持Windows API的C编译器)
  • 字符集:Unicode(用于显示宽字符)
  • 知识点:链表、Windows API、控制台编程

三、整体设计

1. 数据结构

蛇由多个节点组成,每个节点包含坐标和指向下一个节点的指针。我们使用单向链表存储蛇身。

c 复制代码
typedef struct SnakeNode {
    int x;                  // 控制台列坐标(x为偶数)
    int y;                  // 控制台行坐标
    struct SnakeNode* next;
} SnakeNode, *pSnakeNode;

游戏全局信息用一个结构体保存:

c 复制代码
typedef struct Snake {
    pSnakeNode phead;       // 蛇头指针
    pSnakeNode pfood;       // 食物指针
    enum State state;       // 游戏状态
    enum Direction dir;     // 当前移动方向
    int food_wight;         // 当前食物分值(吃一个得几分)
    int score;              // 总分
    int sleep_time;         // 移动速度(毫秒)
} Snake, *pSnake;
  • 状态枚举:Ok(正常)、Kill_self(撞自身)、Kill_Wall(撞墙)、End_Nor(正常退出)
  • 方向枚举:UpDownLeftRight

2. 界面绘制

控制台以字符单元格为单位,我们使用宽字符(如■、●、★、□)来绘制蛇身、食物和墙壁。由于宽字符在控制台中通常占用两个普通字符的宽度,因此蛇的x坐标必须为偶数,以保证对齐。我们通过GotoXY函数将光标移动到指定位置,然后输出相应符号。

3. 游戏逻辑

  • 蛇的移动:在蛇头前方创建一个新节点,若该位置是食物,则将食物节点插入蛇头(蛇变长);否则将新节点插入蛇头,并删除尾节点(保持长度不变)。
  • 碰撞检测:移动后检查蛇头是否越界(撞墙),或与蛇身其他节点重合(撞自身)。
  • 食物生成:随机生成一个位置(x为偶数,且在墙内),确保不与当前蛇身重合。
  • 键盘控制 :通过GetAsyncKeyState检测按键,实现方向控制、加速/减速、暂停和退出。

四、代码实现详解

1. 头文件(snake.h)

首先定义所需的常量、枚举、结构体和函数声明。

c 复制代码
#pragma once
#include <locale.h>
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>

// 宽字符符号
#define WALL L'□'
#define BODY L'●'
#define FOOD L'★'
#define HEAD L'■'

// 按键检测宏(检测按键的上升沿)
#define KeyPress(VK) ((GetAsyncKeyState(VK) & 1) ? 1 : 0)

// 游戏状态
enum State {
    Ok,          // 正常进行
    Kill_self,   // 撞到自己
    Kill_Wall,   // 撞到墙
    End_Nor      // 正常退出(按ESC)
};

// 移动方向
enum Direction {
    Up,
    Down,
    Left,
    Right
};

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

// 游戏主体
typedef struct Snake {
    pSnakeNode phead;
    pSnakeNode pfood;
    enum State state;
    enum Direction dir;
    int food_wight;   // 食物分值
    int score;        // 总分
    int sleep_time;   // 移动间隔(ms)
} Snake, *pSnake;

// 函数声明
void GotoXY(short x, short y);
void HideCursor(void);
void WelcomeUI(void);
void InitGame(pSnake ps);
void RunGame(pSnake ps);
void Check(pSnake ps);
void GreatFood(pSnake ps);
void EndGame(pSnake ps);

2. 工具函数(snake.c)

隐藏光标
c 复制代码
void HideCursor() {
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO tmp = { 0 };
    GetConsoleCursorInfo(handle, &tmp);
    tmp.bVisible = false;
    SetConsoleCursorInfo(handle, &tmp);
}
光标定位
c 复制代码
void GotoXY(short x, short y) {
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD rd = { x, y };
    SetConsoleCursorPosition(handle, rd);
}
欢迎界面(可选)
c 复制代码
void WelcomeUI() {
    GotoXY(50, 15);
    printf("欢迎来到贪吃蛇游戏");
    GotoXY(50, 17);
    system("pause");
    system("cls");
    GotoXY(42, 15);
    printf("按↑、↓、←、→控制方向,按空格暂停,按ESC退出");
    GotoXY(50, 17);
    system("pause");
    system("cls");
}

3. 初始化游戏(InitGame)

初始化游戏参数,绘制墙壁,创建蛇身,并生成第一个食物。

c 复制代码
void InitGame(pSnake ps) {
    // 设置初始参数
    ps->dir = Right;
    ps->food_wight = 2;      // 初始食物分值
    ps->score = 0;
    ps->sleep_time = 300;     // 初始速度
    ps->state = Ok;

    // 绘制墙壁(矩形框)
    // 上边界
    GotoXY(10, 3);
    for (int i = 0; i < 25; i++) {
        wprintf(L"%lc", WALL);
    }
    // 左边界
    for (int i = 1; i <= 20; i++) {
        GotoXY(10, 3 + i);
        wprintf(L"%lc", WALL);
    }
    // 下边界
    GotoXY(10, 24);
    for (int i = 0; i < 25; i++) {
        wprintf(L"%lc", WALL);
    }
    // 右边界
    for (int i = 1; i <= 20; i++) {
        GotoXY(58, 3 + i);
        wprintf(L"%lc", WALL);
    }

    // 创建蛇身(5个节点,初始位置水平排列)
    ps->phead = NULL;
    for (int i = 0; i < 5; i++) {
        pSnakeNode newnode = (pSnakeNode)malloc(sizeof(SnakeNode));
        newnode->next = NULL;
        newnode->x = 16 + i * 2;  // x坐标递增2,保证连续
        newnode->y = 6;
        // 头插法建立链表(蛇头在最后一个插入的节点)
        if (ps->phead == NULL) {
            ps->phead = newnode;
        } else {
            newnode->next = ps->phead;
            ps->phead = newnode;
        }
    }

    // 绘制蛇
    pSnakeNode pur = ps->phead;
    while (pur) {
        GotoXY(pur->x, pur->y);
        if (pur == ps->phead) {
            wprintf(L"%lc", HEAD);  // 蛇头
        } else {
            wprintf(L"%lc", BODY);  // 蛇身
        }
        pur = pur->next;
    }

    // 生成第一个食物
    GreatFood(ps);
}

4. 生成食物(GreatFood)

随机生成食物位置,要求:

  • x坐标在[12, 46]之间(墙壁内)
  • y坐标在[4, 22]之间(墙壁内)
  • x为偶数(与蛇身对齐)
  • 不能与蛇身重合
c 复制代码
void GreatFood(pSnake ps) {
    int x = 0;
    int y = 0;
again:
    do {
        x = rand() % 35 + 12;   // 12 ~ 46
        y = rand() % 19 + 4;    // 4  ~ 22
    } while (x % 2 != 0);       // 保证x为偶数

    // 分配食物节点
    ps->pfood = (pSnakeNode)malloc(sizeof(SnakeNode));
    if (ps->pfood == NULL) {
        perror("malloc");
        return;
    }
    ps->pfood->x = x;
    ps->pfood->y = y;
    ps->pfood->next = NULL;

    // 检查是否与蛇身重合
    pSnakeNode pur = ps->phead;
    while (pur) {
        if (x == pur->x && y == pur->y) {
            free(ps->pfood);      // 释放冲突节点
            goto again;           // 重新生成
        }
        pur = pur->next;
    }

    // 绘制食物
    GotoXY(ps->pfood->x, ps->pfood->y);
    wprintf(L"%lc", FOOD);
}

5. 游戏主循环(RunGame)

这是游戏的核心,循环执行以下步骤:

  • 显示当前分数和提示信息
  • 检测按键(Check)
  • 创建新节点(根据方向)
  • 判断是否吃到食物
  • 更新蛇的位置
  • 碰撞检测
c 复制代码
void RunGame(pSnake ps) {
    while (1) {
        // 显示游戏信息
        GotoXY(78, 8);
        wprintf(L"贪吃蛇小游戏");
        GotoXY(72, 10);
        wprintf(L"当前食物分数为%2d, 总分为%2d", ps->food_wight, ps->score);
        GotoXY(72, 12);
        wprintf(L"按↑、↓、←、→控制方向");
        GotoXY(72, 14);
        wprintf(L"按空格暂停, 按ESC退出");

        // 检测按键
        Check(ps);

        // 创建新节点(即将成为新蛇头)
        pSnakeNode Newnode = (pSnakeNode)malloc(sizeof(SnakeNode));
        if (Newnode == NULL) {
            perror("malloc");
            return;
        }
        Newnode->next = NULL;

        // 根据方向计算新节点坐标
        switch (ps->dir) {
        case Down:
            Newnode->x = ps->phead->x;
            Newnode->y = ps->phead->y + 1;
            break;
        case Up:
            Newnode->x = ps->phead->x;
            Newnode->y = ps->phead->y - 1;
            break;
        case Left:
            Newnode->x = ps->phead->x - 2;
            Newnode->y = ps->phead->y;
            break;
        case Right:
            Newnode->x = ps->phead->x + 2;
            Newnode->y = ps->phead->y;
            break;
        }

        // 判断是否吃到食物
        if (Newnode->x == ps->pfood->x && Newnode->y == ps->pfood->y) {
            // 吃到食物:将食物节点插入蛇头,蛇变长
            ps->pfood->next = ps->phead;
            ps->phead = ps->pfood;

            // 重新绘制整个蛇(注意:原代码此处有bug,全部画成了BODY)
            // 修正:根据节点身份分别画HEAD和BODY
            pSnakeNode pur = ps->phead;
            while (pur) {
                GotoXY(pur->x, pur->y);
                if (pur == ps->phead) {
                    wprintf(L"%lc", HEAD);
                } else {
                    wprintf(L"%lc", BODY);
                }
                pur = pur->next;
            }

            // 生成新食物
            GreatFood(ps);
            // 增加分数
            ps->score += ps->food_wight;
        } else {
            // 没吃到食物:移动(插入新头,删除尾)
            Newnode->next = ps->phead;
            ps->phead = Newnode;

            // 重新绘制蛇(清除尾节点)
            pSnakeNode pur = ps->phead;
            while (pur) {
                GotoXY(pur->x, pur->y);
                if (pur->next == NULL) {
                    // 尾节点:清除原位置(打印两个空格)
                    printf("  ");
                } else {
                    if (pur == ps->phead) {
                        wprintf(L"%lc", HEAD);
                    } else {
                        wprintf(L"%lc", BODY);
                    }
                }
                pur = pur->next;
            }

            // 找到倒数第二个节点,删除尾节点
            pur = ps->phead;
            while (pur->next->next) {
                pur = pur->next;
            }
            free(pur->next);
            pur->next = NULL;
        }

        // 控制速度
        Sleep(ps->sleep_time);

        // 碰撞检测
        // 撞墙
        if (ps->phead->x <= 10 || ps->phead->x >= 58 || ps->phead->y <= 3 || ps->phead->y >= 23) {
            ps->state = Kill_Wall;
        }
        // 撞自身(排除蛇头)
        pSnakeNode tmp1 = ps->phead->next;
        while (tmp1) {
            if (tmp1->x == ps->phead->x && tmp1->y == ps->phead->y) {
                ps->state = Kill_self;
                break;
            }
            tmp1 = tmp1->next;
        }

        if (ps->state != Ok) {
            break;  // 游戏结束,退出循环
        }
    }
}

注意:原代码在吃到食物后的绘制部分将所有节点都画成了BODY,导致蛇头也变为身体符号。这里已修正为根据是否为头节点分别绘制HEAD和BODY。

6. 按键检测(Check)

检测按键并做出相应处理。使用GetAsyncKeyState的返回值的第0位(上升沿)来判断按键是否被按下一次。

c 复制代码
void Check(pSnake ps) {
    if (KeyPress(VK_F3)) {
        // 加速:减小sleep_time,增加食物分值
        if (ps->sleep_time > 120) {
            ps->sleep_time -= 20;
            ps->food_wight += 2;
        }
    } else if (KeyPress(VK_F4)) {
        // 减速:增大sleep_time,减少食物分值
        if (ps->food_wight >= 2) {
            ps->sleep_time += 20;
            ps->food_wight -= 2;
        }
    } else if (KeyPress(VK_ESCAPE)) {
        // 退出游戏
        ps->state = End_Nor;
    } else if (KeyPress(VK_UP) && ps->dir != Down) {
        ps->dir = Up;
    } else if (KeyPress(VK_DOWN) && ps->dir != Up) {
        ps->dir = Down;
    } else if (KeyPress(VK_LEFT) && ps->dir != Right) {
        ps->dir = Left;
    } else if (KeyPress(VK_RIGHT) && ps->dir != Left) {
        ps->dir = Right;
    } else if (KeyPress(VK_SPACE)) {
        // 空格暂停,再次按空格继续
        while (1) {
            Sleep(300);
            if (KeyPress(VK_SPACE)) {
                break;
            }
        }
    }
}

7. 游戏结束释放内存(EndGame)

释放蛇的所有节点以及可能未被吃掉的食物节点。

c 复制代码
void EndGame(pSnake ps) {
    // 释放蛇身节点
    pSnakeNode pur = ps->phead;
    while (pur) {
        pSnakeNode tmp = pur->next;
        free(pur);
        pur = tmp;
    }
    // 如果食物节点还在(未被吃),也要释放
    if (ps->pfood != NULL) {
        free(ps->pfood);
        ps->pfood = NULL;
    }
}

五、主函数(test.c)

主函数负责设置控制台环境、循环开始游戏以及询问是否继续。

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include "snake.h"

int main() {
    char ch = 0;
    do {
        ch = 0;
        system("cls");                         // 清屏
        srand((unsigned int)time(NULL));        // 初始化随机种子
        setlocale(LC_ALL, "");                  // 启用本地化(支持宽字符)
        system("mode con cols=120 lines=33");    // 设置控制台窗口大小
        system("title 贪吃蛇");                  // 设置标题
        HideCursor();                            // 隐藏光标

        Snake snake;
        // WelcomeUI();   // 可选的欢迎界面
        InitGame(&snake);
        RunGame(&snake);
        EndGame(&snake);

        GotoXY(24, 10);
        printf("还要再来一局吗?请输入(Y/N):");
        ch = getchar();
        while (getchar() != '\n');   // 清空输入缓冲区
    } while (ch == 'Y' || ch == 'y');

    GotoXY(0, 28);
    return 0;
}

六、完整代码

以下为三个文件的完整代码(已修正上述bug):

snake.h

c 复制代码
#pragma once
#include <locale.h>
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>

#define WALL L'□'
#define BODY L'●'
#define FOOD L'★'
#define HEAD L'■'
#define KeyPress(VK) ((GetAsyncKeyState(VK) & 1) ? 1 : 0)

enum State {
    Ok,
    Kill_self,
    Kill_Wall,
    End_Nor
};

enum Direction {
    Up,
    Down,
    Left,
    Right
};

typedef struct SnakeNode {
    int x;
    int y;
    struct SnakeNode* next;
} SnakeNode, *pSnakeNode;

typedef struct Snake {
    pSnakeNode phead;
    pSnakeNode pfood;
    enum State state;
    enum Direction dir;
    int food_wight;
    int score;
    int sleep_time;
} Snake, *pSnake;

void GotoXY(short x, short y);
void HideCursor();
void WelcomeUI();
void InitGame(pSnake ps);
void RunGame(pSnake ps);
void Check(pSnake ps);
void GreatFood(pSnake ps);
void EndGame(pSnake ps);

snake.c

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include "snake.h"

void HideCursor() {
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO tmp = { 0 };
    GetConsoleCursorInfo(handle, &tmp);
    tmp.bVisible = false;
    SetConsoleCursorInfo(handle, &tmp);
}

void GotoXY(short x, short y) {
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD rd = { x, y };
    SetConsoleCursorPosition(handle, rd);
}

void WelcomeUI() {
    GotoXY(50, 15);
    printf("欢迎来到贪吃蛇游戏");
    GotoXY(50, 17);
    system("pause");
    system("cls");
    GotoXY(42, 15);
    printf("按↑、↓、←、→控制方向,按空格暂停,按ESC退出");
    GotoXY(50, 17);
    system("pause");
    system("cls");
}

void InitGame(pSnake ps) {
    ps->dir = Right;
    ps->food_wight = 2;
    ps->score = 0;
    ps->sleep_time = 300;
    ps->state = Ok;

    // 画墙
    GotoXY(10, 3);
    for (int i = 0; i < 25; i++) {
        wprintf(L"%lc", WALL);
    }
    for (int i = 1; i <= 20; i++) {
        GotoXY(10, 3 + i);
        wprintf(L"%lc", WALL);
    }
    GotoXY(10, 24);
    for (int i = 0; i < 25; i++) {
        wprintf(L"%lc", WALL);
    }
    for (int i = 1; i <= 20; i++) {
        GotoXY(58, 3 + i);
        wprintf(L"%lc", WALL);
    }

    // 创建蛇
    ps->phead = NULL;
    for (int i = 0; i < 5; i++) {
        pSnakeNode newnode = (pSnakeNode)malloc(sizeof(SnakeNode));
        newnode->next = NULL;
        newnode->x = 16 + i * 2;
        newnode->y = 6;
        if (ps->phead == NULL) {
            ps->phead = newnode;
        } else {
            newnode->next = ps->phead;
            ps->phead = newnode;
        }
    }

    // 画蛇
    pSnakeNode pur = ps->phead;
    while (pur) {
        GotoXY(pur->x, pur->y);
        if (pur == ps->phead) {
            wprintf(L"%lc", HEAD);
        } else {
            wprintf(L"%lc", BODY);
        }
        pur = pur->next;
    }

    // 生成食物
    GreatFood(ps);
}

void GreatFood(pSnake ps) {
    int x = 0, y = 0;
again:
    do {
        x = rand() % 35 + 12;
        y = rand() % 19 + 4;
    } while (x % 2 != 0);

    ps->pfood = (pSnakeNode)malloc(sizeof(SnakeNode));
    if (ps->pfood == NULL) {
        perror("malloc");
        return;
    }
    ps->pfood->x = x;
    ps->pfood->y = y;
    ps->pfood->next = NULL;

    pSnakeNode pur = ps->phead;
    while (pur) {
        if (x == pur->x && y == pur->y) {
            free(ps->pfood);
            goto again;
        }
        pur = pur->next;
    }

    GotoXY(ps->pfood->x, ps->pfood->y);
    wprintf(L"%lc", FOOD);
}

void Check(pSnake ps) {
    if (KeyPress(VK_F3)) {
        if (ps->sleep_time > 120) {
            ps->sleep_time -= 20;
            ps->food_wight += 2;
        }
    } else if (KeyPress(VK_F4)) {
        if (ps->food_wight >= 2) {
            ps->sleep_time += 20;
            ps->food_wight -= 2;
        }
    } else if (KeyPress(VK_ESCAPE)) {
        ps->state = End_Nor;
    } else if (KeyPress(VK_UP) && ps->dir != Down) {
        ps->dir = Up;
    } else if (KeyPress(VK_DOWN) && ps->dir != Up) {
        ps->dir = Down;
    } else if (KeyPress(VK_LEFT) && ps->dir != Right) {
        ps->dir = Left;
    } else if (KeyPress(VK_RIGHT) && ps->dir != Left) {
        ps->dir = Right;
    } else if (KeyPress(VK_SPACE)) {
        while (1) {
            Sleep(300);
            if (KeyPress(VK_SPACE)) {
                break;
            }
        }
    }
}

void RunGame(pSnake ps) {
    while (1) {
        GotoXY(78, 8);
        wprintf(L"贪吃蛇小游戏");
        GotoXY(72, 10);
        wprintf(L"当前食物分数为%2d, 总分为%2d", ps->food_wight, ps->score);
        GotoXY(72, 12);
        wprintf(L"按↑、↓、←、→控制方向");
        GotoXY(72, 14);
        wprintf(L"按空格暂停, 按ESC退出");

        Check(ps);

        pSnakeNode Newnode = (pSnakeNode)malloc(sizeof(SnakeNode));
        if (Newnode == NULL) {
            perror("malloc");
            return;
        }
        Newnode->next = NULL;

        switch (ps->dir) {
        case Down:
            Newnode->x = ps->phead->x;
            Newnode->y = ps->phead->y + 1;
            break;
        case Up:
            Newnode->x = ps->phead->x;
            Newnode->y = ps->phead->y - 1;
            break;
        case Left:
            Newnode->x = ps->phead->x - 2;
            Newnode->y = ps->phead->y;
            break;
        case Right:
            Newnode->x = ps->phead->x + 2;
            Newnode->y = ps->phead->y;
            break;
        }

        if (Newnode->x == ps->pfood->x && Newnode->y == ps->pfood->y) {
            // 吃到食物
            ps->pfood->next = ps->phead;
            ps->phead = ps->pfood;

            pSnakeNode pur = ps->phead;
            while (pur) {
                GotoXY(pur->x, pur->y);
                if (pur == ps->phead) {
                    wprintf(L"%lc", HEAD);
                } else {
                    wprintf(L"%lc", BODY);
                }
                pur = pur->next;
            }

            GreatFood(ps);
            ps->score += ps->food_wight;
        } else {
            // 没吃到食物,移动
            Newnode->next = ps->phead;
            ps->phead = Newnode;

            pSnakeNode pur = ps->phead;
            while (pur) {
                GotoXY(pur->x, pur->y);
                if (pur->next == NULL) {
                    printf("  ");
                } else {
                    if (pur == ps->phead) {
                        wprintf(L"%lc", HEAD);
                    } else {
                        wprintf(L"%lc", BODY);
                    }
                }
                pur = pur->next;
            }

            pur = ps->phead;
            while (pur->next->next) {
                pur = pur->next;
            }
            free(pur->next);
            pur->next = NULL;
        }

        Sleep(ps->sleep_time);

        // 撞墙检测
        if (ps->phead->x <= 10 || ps->phead->x >= 58 || ps->phead->y <= 3 || ps->phead->y >= 23) {
            ps->state = Kill_Wall;
        }

        // 撞自身检测
        pSnakeNode tmp1 = ps->phead->next;
        while (tmp1) {
            if (tmp1->x == ps->phead->x && tmp1->y == ps->phead->y) {
                ps->state = Kill_self;
                break;
            }
            tmp1 = tmp1->next;
        }

        if (ps->state != Ok) {
            break;
        }
    }
}

void EndGame(pSnake ps) {
    pSnakeNode pur = ps->phead;
    while (pur) {
        pSnakeNode tmp = pur->next;
        free(pur);
        pur = tmp;
    }
    if (ps->pfood != NULL) {
        free(ps->pfood);
        ps->pfood = NULL;
    }
}

test.c

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include "snake.h"

int main() {
    char ch = 0;
    do {
        ch = 0;
        system("cls");
        srand((unsigned int)time(NULL));
        setlocale(LC_ALL, "");
        system("mode con cols=120 lines=33");
        system("title 贪吃蛇");
        HideCursor();

        Snake snake;
        // WelcomeUI();  // 若需要欢迎界面,取消注释
        InitGame(&snake);
        RunGame(&snake);
        EndGame(&snake);

        GotoXY(24, 10);
        printf("还要再来一局吗?请输入(Y/N):");
        ch = getchar();
        while (getchar() != '\n');
    } while (ch == 'Y' || ch == 'y');

    GotoXY(0, 28);
    return 0;
}

七、总结

本文从零开始,详细讲解了如何使用C语言在Windows控制台下实现贪吃蛇游戏。我们学习了:

  • 使用Windows API进行光标定位和按键检测
  • 利用链表动态管理蛇身
  • 控制台宽字符输出实现图形界面
  • 游戏循环和碰撞检测的设计

代码中还存在一些可以优化的地方,例如:

  • 增加难度选择
  • 优化绘制效率(避免全屏重绘)
  • 增加分数排行榜等

读者可以在此基础上继续扩展,打造更丰富的游戏体验。希望本文对初学者理解C语言和Windows编程有所帮助。

相关推荐
Eternity∞1 小时前
Linux系统下,C语言基础
linux·c语言·开发语言
追随者永远是胜利者5 小时前
(LeetCode-Hot100)55. 跳跃游戏
java·算法·leetcode·游戏·go
爱编码的小八嘎8 小时前
第3章 Windows运行机理-3.1 内核分析(1)
c语言
A666666666678909 小时前
程序人生-Hello’s P2P
c语言·程序人生·microsoft
只想恰口饭9 小时前
程序人生-Hello’s P2P
linux·c语言·ubuntu
Simp_lify9 小时前
程序人生-Hello’s P2P
c语言
hit_waves9 小时前
程序人生-Hello’s P2P 哈尔滨工业大学计算机系统大作业
c语言·程序人生·课程设计·p2p·大作业
hoperest9 小时前
程序人生-Hello‘s P2P
linux·c语言·程序人生·ubuntu
2501_941841689 小时前
HIT-CSAPP2025大作业:程序人生-Hello’s P2P(2024111666-牛启正)
c语言·c·csapp