首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

貪吃蛇C語言實戰(下):從畫圖原型到完整遊戲——穿牆、食物、增長、碰撞全實現

     編輯:關於C語言

貪吃蛇C語言實戰(下):從畫圖原型到完整遊戲——穿牆、食物、增長、碰撞全實現

上集實現了單方塊移動繪圖原型,本集將其進化為完整貪吃蛇:多節蛇身跟隨、軌跡清除、穿牆邏輯、食物隨機生成與防重疊、吃食增長機制、自我碰撞判定、遊戲主循環整合。

一、數據結構升級

typedef struct Position { int x, y; } Pos;
Pos array;              // 方向向量
Pos snake[300000];      // 蛇身結點數組(足夠大)
long len = 1;           // 蛇長
Pos egg;                // 食物座標

二、防反向輸入的鍵盤控制

void command() {
    if (_kbhit()) {
        switch (_getch()) {
            case 'a': if (array.x != 1 || array.y != 0) { array.x = -1; array.y = 0; } break;
            case 'd': if (array.x != -1 || array.y != 0) { array.x = 1; array.y = 0; } break;
            case 'w': if (array.x != 0 || array.y != 1) { array.x = 0; array.y = -1; } break;
            case 's': if (array.x != 0 || array.y != -1) { array.x = 0; array.y = 1; } break;
        }
    }
}

關鍵:檢查 array 當前方向,僅在非反向時更新,防止蛇直接掉頭撞自己。

三、多節移動與軌跡清除

void move() {
    setcolor(BLACK);
    rectangle(snake[len-1].x-5, snake[len-1].y-5, snake[len-1].x+5, snake[len-1].y+5);  // 擦除尾部
    for (int i = len-1; i > 0; i--) {  // 身體跟隨:後節移到前節位置
        snake[i].x = snake[i-1].x;
        snake[i].y = snake[i-1].y;
    }
    snake[0].x += array.x * 10;  // 頭部按向量移動
    snake[0].y += array.y * 10;
    break_wall();  // 穿牆處理
}

核心邏輯:從尾部向前依次賦值,最後移動頭部。先擦除舊尾部,再更新座標,避免殘影。

四、穿牆邏輯 break_wall()

void break_wall() {
    if (snake[0].x >= 640) snake[0].x = 0;
    else if (snake[0].x <= 0) snake[0].x = 640;
    else if (snake[0].y >= 480) snake[0].y = 0;
    else if (snake[0].y <= 0) snake[0].y = 480;
}

超出邊界即從對面出現,增加遊戲趣味性,也簡化了邊界死亡判定。

五、食物系統:生成與防重疊

void creat_egg() {
    while (true) {
        int ok = 0;
        egg.x = rand() % 80 * 5 + 100;  // 對齊網格(5像素)並留邊距
        egg.y = rand() % 50 * 5 + 100;
        for (int i = 0; i < len; i++) {
            if (snake[i].x == 0 && snake[i].y == 0) continue;
            if (abs(snake[i].x - egg.x) <= 10 && abs(snake[i].y - egg.y) <= 10) { ok = -1; break; }
        }
        if (ok == 0) return;  // 位置合法
    }
}

食物座標按5像素網格對齊(與蛇移動步長一致),檢查與所有蛇身結點距離>10像素,確保不重疊、不貼身。

六、吃食增長機制 eat_egg()

void eat_egg() {
    if (abs(snake[0].x - egg.x) <= 5 && abs(snake[0].y - egg.y) <= 5) {
        setcolor(BLACK); circle(egg.x, egg.y, 5);  // 擦除舊食物
        creat_egg();  // 生成新食物
        // 增長:在頭部插入新結點
        len++;
        for (int i = len-1; i > 0; i--) {
            snake[i].x = snake[i-1].x;
            snake[i].y = snake[i-1].y;
        }
        snake[0].x += array.x * 10;  // 新頭部向前一步
        snake[0].y += array.y * 10;
    }
}

增長策略:數組整體後移一位騰出 snake[0],新頭部按當前方向前進一步,視覺上蛇變長了且方向不變。

七、自我碰撞判定 eat_self()

void eat_self() {
    if (len == 1) return;
    for (int i = 1; i < len; i++) {
        if (abs(snake[i].x - snake[0].x) <= 5 && abs(snake[i].y - snake[0].y) <= 5) {
            outtextxy(250, 200, "GAME OVER!");
            Sleep(3000);
            closegraph();
            exit(0);
        }
    }
}

檢查頭部與除自身外所有結點距離,<5像素即碰撞。使用範圍判定容忍座標微小誤差。

八、繪圖與主循環

void draw() {
    setcolor(BLUE);
    for (int i = 0; i < len; i++)
        rectangle(snake[i].x-5, snake[i].y-5, snake[i].x+5, snake[i].y+5);
    setcolor(RED); circle(egg.x, egg.y, 5);
    Sleep(100);  // 幀率控制
}

void init() {
    initgraph(640, 480);
    srand((unsigned)time(NULL));
    snake[0].x = rand()%80*5+100;
    snake[0].y = rand()%50*5+100;
    array.x = (rand()%2)?1:-1; array.y = 0;  // 隨機左右
    creat_egg();
}

int main() {
    init();
    while (true) {
        command();
        move();
        eat_egg();
        draw();
        eat_self();
    }
    return 0;
}

九、完整代碼與已知問題

全文附帶完整可編譯代碼(含 graphics.h, conio.h, time.h, math.h)。已知潛在Bug:creat_egg 中 srand 重複調用可能導致隨機性下降;eat_egg 增長後未重新檢查穿牆;極長蛇身數組可能棧溢出(建議動態分鏈表)。歡迎指正優化。

總結

從單方塊畫圖到完整貪吃蛇,核心遞進:

  1. 數組模擬蛇身 + 尾部清除實現平滑移動
  2. 方向向量 + 反向檢查保證操作邏輯
  3. 穿牆邏輯簡化邊界處理
  4. 食物隨機生成 + 空間檢查保證公平性
  5. 頭部插入法實現增長,自我碰撞判定完成遊戲閉環

這是一個極佳的C語言綜合練習:指釖/數組、結構體、隨機數、圖形庫、遊戲循環、狀態機。下一步可嘗試:分數記錄、等級加速、雙人對戰、AI自動尋路……

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved