c_snake_game

第 2 课:项目结构 📁

良好的项目结构是成功编程的第一步。本课将介绍如何组织 C 语言项目。


2.1 为什么需要项目结构?

想象一下,如果你把所有的东西都扔进一个房间,找东西会有多困难!代码也是一样。良好的结构帮助我们:


2.2 我们的贪吃蛇项目结构

snake_game/
├── src/                    # 源代码目录
│   ├── main.c              # 程序入口
│   ├── game.c / game.h     # 游戏核心逻辑
│   ├── snake.c / snake.h   # 蛇的实现
│   ├── food.c / food.h     # 食物系统
│   ├── ui.c / ui.h         # 用户界面
│   ├── input.c / input.h   # 输入处理
│   ├── score.c / score.h   # 分数系统
│   └── utils.c / utils.h   # 工具函数
├── docs/                   # 文档目录
│   └── 教程文件...
├── data/                   # 游戏数据
│   └── highscore.txt       # 最高分记录
├── obj/                    # 编译中间文件(自动生成)
├── Makefile                # 构建配置文件
├── README.md               # 项目说明
└── .gitignore              # Git 忽略文件

2.3 文件命名规范

C 语言文件类型

扩展名 用途 说明
.c 源文件 包含实际的代码实现
.h 头文件 包含函数声明、类型定义、宏

命名规则

// ✅ 好的命名
main.c          // 清晰明了
snake.c         // 小写字母,有意义
game_state.h    // 多个单词用下划线连接

// ❌ 不好的命名
Main.C          // 大小写混乱
1snake.c        // 数字开头
my super file.c // 包含空格

2.4 源文件 vs 头文件

源文件 (.c)

源文件包含实际的代码实现

// snake.c
#include "snake.h"

snake_t* snake_create(int x, int y) {
    // 实际的实现代码
    snake_t* snake = malloc(sizeof(snake_t));
    // ... 更多代码
    return snake;
}

头文件 (.h)

头文件包含声明和接口

// snake.h
#ifndef SNAKE_H
#define SNAKE_H

// 类型声明
typedef struct snake snake_t;

// 函数声明
snake_t* snake_create(int x, int y);
void snake_destroy(snake_t* snake);

#endif

为什么要分开?

┌─────────────────────────────────────────────────┐
│  头文件 (.h)              源文件 (.c)            │
│  ───────────              ───────────            │
│  "我能做什么"              "我怎么做"              │
│  菜单                      厨房里的实际烹饪        │
│  接口                      实现                   │
└─────────────────────────────────────────────────┘

2.5 动手创建项目结构

让我们创建完整的项目结构:

# 进入项目目录
cd ~/c_projects/snake_game

# 创建源代码目录
mkdir -p src

# 创建数据目录
mkdir -p data

# 创建空文件
touch src/main.c
touch src/game.c src/game.h
touch src/snake.c src/snake.h
touch src/food.c src/food.h
touch src/ui.c src/ui.h
touch src/input.c src/input.h
touch src/score.c src/score.h
touch src/utils.c src/utils.h

# 创建 README.md
touch README.md

# 查看结构
tree . 2>/dev/null || find . -type f | head -20

2.6 理解相对路径和绝对路径

# 绝对路径 - 从根目录开始的完整路径
/home/user/c_projects/snake_game/src/main.c

# 相对路径 - 从当前目录开始的路径
# 假设当前在 snake_game 目录
src/main.c          # ./src/main.c 的简写
../other/file.c     # 上一级目录中的文件
./main.c            # 当前目录的文件(.表示当前目录)

路径练习

# 假设你在 snake_game 目录
cd ~/c_projects/snake_game

# 进入 src 目录
cd src

# 返回 snake_game 目录
cd ..

# 直接从任何地方进入 src 目录
cd ~/c_projects/snake_game/src

# 查看 src 目录内容但不进入
ls ~/c_projects/snake_game/src

2.7 Makefile 简介

Makefile 告诉计算机如何编译你的项目:

# 简单的 Makefile 示例
CC = gcc
CFLAGS = -Wall -g

snake_game: src/main.c src/snake.c
	$(CC) $(CFLAGS) -o snake_game src/main.c src/snake.c

clean:
	rm -f snake_game

详细讲解见 第 11 课:Makefile


✅ 本课检查清单


📝 作业

  1. 在你的项目目录中创建完整的目录结构
  2. 在每个 .h 头文件中添加基本的保护宏:
    #ifndef XXX_H
    #define XXX_H
       
    // 内容...
       
    #endif
    
  3. main.c 中写入:
    #include <stdio.h>
       
    int main() {
        printf("Hello, Snake!\n");
        return 0;
    }
    

下一课:第一个程序