控制台贪吃蛇游戏完整实现
一、游戏核心架构
1. 数据结构设计
typedef struct SnakeNode {
int x;
int y;
struct SnakeNode* next;
} SnakeNode;
typedef struct {
SnakeNode* head;
SnakeNode* tail;
int dx; // X方向增量
int dy; // Y方向增量
int food_x;
int food_y;
int score;
int game_over;
} GameState;
2. 游戏初始化
void init_game(GameState* game) {
// 创建初始蛇身(3节)
SnakeNode* node1 = create_node(10, 10);
SnakeNode* node2 = create_node(11, 10);
SnakeNode* node3 = create_node(12, 10);
node1->next = node2;
node2->next = node3;
game->head = node1;
game->tail = node3;
game->dx = 1; // 初始向右移动
game->dy = 0;
game->score = 0;
game->game_over = 0;
generate_food(game);
}
SnakeNode* create_node(int x, int y) {
SnakeNode* node = malloc(sizeof(SnakeNode));
node->x = x;
node->y = y;
node->next = NULL;
return node;
}
二、游戏循环实现
1. 主循环逻辑
void game_loop() {
GameState game;
init_game(&game);
while (!game.game_over) {
handle_input(&game);
update_game(&game);
render(&game);
usleep(100000); // 控制游戏速度(100ms)
}
show_game_over(&game);
free_resources(&game);
}
2. 运动更新逻辑
void update_game(GameState* game) {
// 计算新头部位置
int new_x = game->head->x + game->dx;
int new_y = game->head->y + game->dy;
// 碰撞检测
if (check_collision(game, new_x, new_y)) {
game->game_over = 1;
return;
}
// 创建新头部
SnakeNode* new_head = create_node(new_x, new_y);
new_head->next = game->head;
game->head = new_head;
// 检查是否吃到食物
if (new_x == game->food_x && new_y == game->food_y) {
game->score += 10;
generate_food(game);
} else {
// 移除尾部节点
SnakeNode* prev = game->head;
while (prev->next != game->tail) prev = prev->next;
free(game->tail);
prev->next = NULL;
game->tail = prev;
}
}
三、关键功能实现
1. 跨平台输入处理
// 通用输入处理接口
#ifdef _WIN32
#include <conio.h>
#else
#include <termios.h>
#include <unistd.h>
#endif
void handle_input(GameState* game) {
int key = getch_nonblock();
switch(key) {
case 'w': case 'W': case KEY_UP:
if (game->dy != 1) { game->dx = 0; game->dy = -1; }
break;
case 's': case 'S': case KEY_DOWN:
if (game->dy != -1) { game->dx = 0; game->dy = 1; }
break;
case 'a': case 'A': case KEY_LEFT:
if (game->dx != 1) { game->dx = -1; game->dy = 0; }
break;
case 'd': case 'D': case KEY_RIGHT:
if (game->dx != -1) { game->dx = 1; game->dy = 0; }
break;
case 'q': case 'Q':
game->game_over = 1;
break;
}
}
// 非阻塞输入实现
int getch_nonblock() {
#ifdef _WIN32
if (_kbhit()) return _getch();
#else
struct termios oldt, newt;
int ch;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return ch;
#endif
return -1;
}
2. 碰撞检测系统
int check_collision(GameState* game, int x, int y) {
// 边界检测(假设游戏区域80x24)
if (x < 0 || x >= 80 || y < 0 || y >= 24)
return 1;
// 自碰撞检测
SnakeNode* current = game->head;
while (current != NULL) {
if (current != game->head && current->x == x && current->y == y)
return 1;
current = current->next;
}
return 0;
}
void generate_food(GameState* game) {
do {
game->food_x = rand() % 80;
game->food_y = rand() % 24;
} while (check_collision(game, game->food_x, game->food_y));
}
四、图形渲染模块
1. 跨平台绘制实现
void render(GameState* game) {
#ifdef _WIN32
system("cls");
#else
printf("\033[2J\033[H"); // 清屏
#endif
// 绘制边界
for (int x = 0; x < 80; x++) printf("#");
printf("\n");
for (int y = 0; y < 24; y++) {
printf("#");
for (int x = 1; x < 79; x++) {
if (x == game->food_x && y == game->food_y)
printf("F");
else if (is_snake_body(game, x, y))
printf("O");
else
printf(" ");
}
printf("#\n");
}
for (int x = 0; x < 80; x++) printf("#");
printf("\nScore: %d\n", game->score);
}
int is_snake_body(GameState* game, int x, int y) {
SnakeNode* current = game->head;
while (current != NULL) {
if (current->x == x && current->y == y)
return 1;
current = current->next;
}
return 0;
}
五、扩展功能实现
1. 难度分级系统
typedef struct {
int speed; // 更新间隔(ms)
int food_score; // 每个食物得分
int wall_collision; // 是否开启墙碰撞
} Difficulty;
const Difficulty levels[] = {
{150, 10, 1}, // 简单模式
{100, 20, 1}, // 普通模式
{80, 30, 0} // 困难模式(可穿墙)
};
void set_difficulty(GameState* game, int level) {
game->speed = levels[level].speed;
game->food_score = levels[level].food_score;
game->wall_collision = levels[level].wall_collision;
}
2. 存档功能
void save_game(GameState* game, const char* filename) {
FILE* fp = fopen(filename, "wb");
if (!fp) return;
// 写入游戏状态
fwrite(&game->dx, sizeof(int), 1, fp);
fwrite(&game->dy, sizeof(int), 1, fp);
fwrite(&game->score, sizeof(int), 1, fp);
// 写入蛇身数据
SnakeNode* current = game->head;
while (current != NULL) {
fwrite(current, sizeof(SnakeNode), 1, fp);
current = current->next;
}
fclose(fp);
}
void load_game(GameState* game, const char* filename) {
// 实现略,需要处理链表重建
}
编译与运行指南:
-
Linux/macOS 编译命令:
gcc snake.c -o snake -lncurses ./snake
-
Windows 编译命令(使用MinGW):
gcc snake.c -o snake.exe -lconio snake.exe
核心玩法:
- WASD/方向键控制方向
- Q键退出游戏
- 吃到食物(F)增长身体
- 碰撞墙壁或自身游戏结束
性能优化点:
- 使用双向链表提升遍历效率
- 空间换时间:使用二维数组记录蛇身位置
- 分帧渲染减少闪烁
- 预分配节点内存池
扩展方向:
- 添加不同皮肤支持
- 实现网络对战模式
- 添加道具系统(加速、护盾等)
- 支持关卡地图编辑
- 添加成就系统