结构体允许你将不同类型的数据组合在一起。这是创建复杂数据结构的基础。
问题:如何表示一条蛇?
// ❌ 使用多个独立变量
int snake_x1 = 10, snake_y1 = 10;
int snake_x2 = 9, snake_y2 = 10;
int snake_x3 = 8, snake_y3 = 10;
int snake_length = 3;
// ... 很难管理!
// ✅ 使用结构体
typedef struct {
int x;
int y;
int length;
} Snake;
Snake snake = {10, 10, 3};
// 定义结构体类型
struct Point {
int x;
int y;
};
// 创建结构体变量
struct Point p1;
p1.x = 10;
p1.y = 20;
// 或者初始化
struct Point p2 = {30, 40};
// 使用 typedef 创建别名
typedef struct {
int x;
int y;
} Point;
// 现在可以直接使用 Point,不需要 struct 关键字
Point p = {10, 20};
typedef struct {
int x;
int y;
int length;
char direction;
} Snake;
Snake snake = {10, 10, 3, 'R'};
// 使用点运算符访问成员
printf("蛇的位置:(%d, %d)\n", snake.x, snake.y);
printf "蛇的长度:%d\n", snake.length);
printf "蛇的方向:%c\n", snake.direction);
// 修改成员
snake.x += 1;
snake.direction = 'D';
typedef struct {
int x;
int y;
} Point;
typedef struct Snake {
Point position; // 位置
int length; // 长度
int direction; // 方向
bool alive; // 是否存活
} Snake;
typedef struct {
Point position; // 位置
int value; // 分数值
bool active; // 是否激活
} Food;
typedef struct {
Snake snake; // 蛇
Food food; // 食物
int score; // 分数
int level; // 等级
bool running; // 游戏是否运行
} Game;
// 定义蛇身段
typedef struct {
int x;
int y;
} Segment;
// 创建蛇身数组
Segment body[100]; // 最多 100 段
// 初始化
body[0] = (Segment){10, 10}; // 头部
body[1] = (Segment){9, 10}; // 身体
body[2] = (Segment){8, 10}; // 尾部
// 访问
printf("头部位置:(%d, %d)\n", body[0].x, body[0].y);
当结构体很大时,传递指针更高效:
typedef struct {
int x, y, length;
// ... 很多成员
} Snake;
// 传递结构体(复制整个结构体)
void move_snake(Snake snake) {
snake.x += 1; // 只修改了副本
}
// 传递指针(修改原结构体)
void move_snake_ptr(Snake* snake) {
snake->x += 1; // 修改原结构体
}
// 使用
Snake s = {10, 10, 3};
move_snake_ptr(&s); // 传递地址
-> 运算符Snake* snake_ptr = &snake;
// 两种方式访问成员
snake_ptr->x = 10; // 推荐,简洁
(*snake_ptr).x = 10; // 等价,但繁琐
结构体可以包含其他结构体:
typedef struct {
int x;
int y;
} Point;
typedef struct {
Point position; // 嵌套结构体
Point velocity;
} GameObject;
// 使用
GameObject player;
player.position.x = 100;
player.position.y = 200;
player.velocity.x = 5;
player.velocity.y = 0;
#include <stdio.h>
#include <stdbool.h>
// 方向枚举
typedef enum {
DIR_UP,
DIR_DOWN,
DIR_LEFT,
DIR_RIGHT
} Direction;
// 点结构体
typedef struct {
int x;
int y;
} Point;
// 蛇身段
typedef struct Segment {
Point position;
struct Segment* next; // 指向下一段(链表)
} Segment;
// 蛇
typedef struct {
Segment* head; // 头部
Segment* tail; // 尾部
int length; // 长度
Direction dir; // 方向
} Snake;
// 食物
typedef struct {
Point position;
int value;
bool active;
} Food;
// 游戏
typedef struct {
Snake snake;
Food food;
int score;
int high_score;
int level;
bool running;
bool paused;
} Game;
// 创建新蛇
Snake* snake_create(int start_x, int start_y) {
Snake* snake = malloc(sizeof(Snake));
snake->head = malloc(sizeof(Segment));
snake->head->position = (Point){start_x, start_y};
snake->head->next = NULL;
snake->tail = snake->head;
snake->length = 1;
snake->dir = DIR_RIGHT;
return snake;
}
// 移动蛇
void snake_move(Snake* snake) {
// 根据方向计算新位置
Point new_head = snake->head->position;
switch (snake->dir) {
case DIR_UP: new_head.y -= 1; break;
case DIR_DOWN: new_head.y += 1; break;
case DIR_LEFT: new_head.x -= 1; break;
case DIR_RIGHT: new_head.x += 1; break;
}
// 创建新头部
Segment* new_segment = malloc(sizeof(Segment));
new_segment->position = new_head;
new_segment->next = snake->head;
snake->head = new_segment;
snake->length++;
// 移除尾部(除非在生长)
// ...
}
int main(void) {
// 创建游戏
Game game = {0};
game.snake = *snake_create(10, 10);
game.score = 0;
game.level = 1;
game.running = true;
printf("游戏初始化完成!\n");
printf("蛇的初始位置:(%d, %d)\n",
game.snake.head.position.x,
game.snake.head.position.y);
return 0;
}
-> 和 . 的区别Player 结构体,包含:
定义一个 Rectangle 结构体,包含两个 Point(左上角和右下角)
下一课:指针基础