G0001学习记录 G0001写贪吃蛇
分享作者:F888
作者昵称:我爱小易
评测品牌:灵动微电子
评测型号:MM32G0001A1TC
发布时间:2025-10-20 11:04:28
1
前言
这是最后一期G0001的系教程了,我个人觉得锻炼编程技巧的方法就是写一个游戏了
开源口碑分享内容

一、硬件平台与功能概览

  • 主控:MM32G000
  • 显示:I2C/SPI OLED(128×64)
  • 输入:4 个独立按键(上/下/左/右)

二、核心数据结构设计

1. 定义“蛇段”结构体

typedef struct {
    uint8_t x;
    uint8_t y;
    uint8_t length; // 实际仅蛇头用到 length,食物可复用此结构
} Snake;

2. 全局变量管理状态

Snake snake;                // 蛇头
Snake food;                 // 食物
Snake snake_body[50];       // 蛇身(最大长度 50,占用 100 字节)
uint8_t direction = 4;      // 当前方向(1=上, 2=下, 3=左, 4=右)
uint8_t previous_direction = 4; // 上一次方向(防 180° 调头)


三、关键函数解析

1. 初始化:蛇与食物

void Snake_Init() {
    snake.x = 32; snake.y = 20;
    snake.length = INIT_SNAKE_LENGTH; // 如 3

    // 初始化蛇身:水平向左排列
    for (uint8_t i = 0; i < snake.length; i++) {
        snake_body[i].x = snake.x - i;
        snake_body[i].y = snake.y;
    }

    // 食物初始位置
    food.x = 32; food.y = 26; food.length = 1;
}
蛇身初始化必须与初始方向一致,否则移动时会“断裂”。

2. 方向控制:防 180° 调头

uint8_t Snake_GetKey() {
    if (KEY_NUM == 0) return previous_direction;

    switch(KEY_NUM) {
        case 1: // 上
            if (previous_direction != KEY_DOWN) {
                previous_direction = KEY_UP;
                return KEY_UP;
            }
            break;
        // ... 其他方向类似
    }
    return previous_direction; // 无效操作返回原方向
}
⚠️不能从“上”直接按“下”,否则蛇会“咬自己脖子”!

3. 蛇的移动:数组平移法

void Snake_Update() {
    // 蛇身整体前移:从尾到头拷贝
    for (uint8_t i = snake.length - 1; i > 0; i--) {
        snake_body[i] = snake_body[i - 1];
    }
    // 蛇头更新为当前位置
    snake_body[0].x = snake.x;
    snake_body[0].y = snake.y;

    // 绘制整条蛇
    for (uint8_t i = 0; i < snake.length; i++) {
        OLED_DrawPoint(snake_body[i].x, snake_body[i].y);
    }
}
头进尾出,无需动态内存

4. 吃食物 & 随机生成

oid Snake_Eatfood() {
    if (snake.x == food.x && snake.y == food.y) {
        snake.length++; // 蛇变长

        // 利用全局时间种子生成随机位置
        srand(times); // times 由 1ms 定时器累加
        food.x = rand() % 126 + 1; // 避开边框(1~126)
        food.y = rand() % 62 + 1;  // (1~62)
    }
}

5. 游戏结束判断

uint8_t Snake_GameOver() {
    if (snake.x >= GAME_WIDTH - 1 || snake.x < 1 ||
        snake.y >= GAME_HEIGHT - 1 || snake.y < 1) {
        return 0; // 碰墙
    }
    return 1; // 游戏继续
}
边界定义:OLED 有效区域为 (1,1) 到 (126,62),边框 (0,0)-(127,63) 为游戏墙。

四、主循环:帧刷新策略


void snake_game_main() {
    OLED_Clear();
    Draw_GameBorder();
    Snake_Init();
    OLED_Update();

    while (1) {
        Snake_direction();   // 更新蛇头坐标
        Snake_Update();      // 移动并绘制蛇身
        Snake_Eatfood();     // 检测吃食物
        Snake_Draw(food.x, food.y, 1); // 重绘食物
        OLED_Update();       // 刷新屏幕

        OLED_ClearArea(1, 1, 126, 62); // 清除游戏区(下帧重绘)

        if (!Snake_GameOver()) break; // 游戏结束
    }
}

五、结语

通过这个项目,你不仅锻炼了编程能力,更培养了:

  • 问题分解能力(把游戏拆成初始化、移动、碰撞等模块)
  • 调试思维
  • 资源约束意识



全部评论
暂无评论
0/144