C语言编程题实现一个简易的贪吃蛇游戏

C语言编程题,实现一个简易的贪吃蛇游戏。贪吃蛇是一款经典的益智小游戏,玩家控制一条蛇,通过吃食物来增加身体长度,同时避免撞到自己或边界。实现贪吃蛇游戏在C语言中可以有多种方法,每种方法的核心是使用不同的技术或库来控制蛇的移动、绘制场景和检测碰撞。

1、基于控制台字符操作的贪吃蛇游戏

使用最基础的控制台字符操作,不依赖任何外部库。游戏在控制台内运行,利用键盘输入和字符绘制游戏场景。

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>

#define WIDTH 20
#define HEIGHT 20

#define UP 1
#define DOWN 2
#define LEFT 3
#define RIGHT 4

int game_over;
int snake_x, snake_y, fruit_x, fruit_y, score;
int tail_x[100], tail_y[100]; // 蛇的身体
int tail_length;
int direction;

void setup() {
    game_over = 0;
    snake_x = WIDTH / 2;
    snake_y = HEIGHT / 2;
    fruit_x = rand() % WIDTH;
    fruit_y = rand() % HEIGHT;
    score = 0;
    direction = STOP;
    tail_length = 0;
}

void draw() {
    system("cls");
    for (int i = 0; i < WIDTH + 2; i++) printf("#");
    printf("\n");

    for (int i = 0; i < HEIGHT; i++) {
        for (int j = 0; j < WIDTH; j++) {
            if (j == 0) printf("#");
            if (i == snake_y && j == snake_x) printf("O");
            else if (i == fruit_y && j == fruit_x) printf("F");
            else {
                int printed = 0;
                for (int k = 0; k < tail_length; k++) {
                    if (tail_x[k] == j && tail_y[k] == i) {
                        printf("o");
                        printed = 1;
                    }
                }
                if (!printed) printf(" ");
            }
            if (j == WIDTH - 1) printf("#");
        }
        printf("\n");
    }

    for (int i = 0; i < WIDTH + 2; i++) printf("#");
    printf("\n");
    printf("Score: %d\n", score);
}

void input() {
    if (_kbhit()) {
        switch (_getch()) {
            case 'w': direction = UP; break;
            case 's': direction = DOWN; break;
            case 'a': direction = LEFT; break;
            case 'd': direction = RIGHT; break;
            case 'x': game_over = 1; break;
        }
    }
}

void logic() {
    int prev_x = tail_x[0];
    int prev_y = tail_y[0];
    int prev2_x, prev2_y;
    tail_x[0] = snake_x;
    tail_y[0] = snake_y;

    for (int i = 1; i < tail_length; i++) {
        prev2_x = tail_x[i];
        prev2_y = tail_y[i];
        tail_x[i] = prev_x;
        tail_y[i] = prev_y;
        prev_x = prev2_x;
        prev_y = prev2_y;
    }

    switch (direction) {
        case UP: snake_y--; break;
        case DOWN: snake_y++; break;
        case LEFT: snake_x--; break;
        case RIGHT: snake_x++; break;
    }

    if (snake_x >= WIDTH) snake_x = 0; else if (snake_x < 0) snake_x = WIDTH - 1;
    if (snake_y >= HEIGHT) snake_y = 0; else if (snake_y < 0) snake_y = HEIGHT - 1;

    for (int i = 0; i < tail_length; i++) {
        if (tail_x[i] == snake_x && tail_y[i] == snake_y) {
            game_over = 1;
        }
    }

    if (snake_x == fruit_x && snake_y == fruit_y) {
        score += 10;
        fruit_x = rand() % WIDTH;
        fruit_y = rand() % HEIGHT;
        tail_length++;
    }
}

int main() {
    setup();
    while (!game_over) {
        draw();
        input();
        logic();
        Sleep(100); // 控制速度
    }
    printf("Game Over! Score: %d\n", score);
    return 0;
}

2、使用ncurses库实现贪吃蛇游戏

ncurses 是一个用于控制终端输入输出的库,可以更好地控制光标位置,实现动画效果,如没安装ncurses库,需要安装ncurses库。

#include <ncurses.h>
#include <stdlib.h>
#include <time.h>

#define WIDTH 20
#define HEIGHT 20

int snake_x, snake_y, fruit_x, fruit_y, score;
int tail_x[100], tail_y[100], tail_length;
int game_over, direction;

void setup() {
    initscr();
    clear();
    noecho();
    cbreak();
    timeout(100);
    keypad(stdscr, TRUE);
    curs_set(0);

    snake_x = WIDTH / 2;
    snake_y = HEIGHT / 2;
    fruit_x = rand() % WIDTH;
    fruit_y = rand() % HEIGHT;
    score = 0;
    tail_length = 0;
    game_over = 0;
    direction = 'r';
}

void draw() {
    clear();
    for (int i = 0; i < WIDTH; i++) mvprintw(0, i, "#");
    for (int i = 1; i < HEIGHT; i++) {
        mvprintw(i, 0, "#");
        mvprintw(i, WIDTH - 1, "#");
    }
    for (int i = 0; i < WIDTH; i++) mvprintw(HEIGHT - 1, i, "#");

    mvprintw(snake_y, snake_x, "O");
    mvprintw(fruit_y, fruit_x, "F");

    for (int i = 0; i < tail_length; i++) {
        mvprintw(tail_y[i], tail_x[i], "o");
    }

    mvprintw(HEIGHT + 1, 0, "Score: %d", score);
    refresh();
}

void input() {
    int key = getch();
    switch (key) {
        case KEY_UP: if (direction != 'd') direction = 'u'; break;
        case KEY_DOWN: if (direction != 'u') direction = 'd'; break;
        case KEY_LEFT: if (direction != 'r') direction = 'l'; break;
        case KEY_RIGHT: if (direction != 'l') direction = 'r'; break;
        case 'x': game_over = 1; break;
    }
}

void logic() {
    int prev_x = tail_x[0], prev_y = tail_y[0];
    int prev2_x, prev2_y;
    tail_x[0] = snake_x;
    tail_y[0] = snake_y;

    for (int i = 1; i < tail_length; i++) {
        prev2_x = tail_x[i];
        prev2_y = tail_y[i];
        tail_x[i] = prev_x;
        tail_y[i] = prev_y;
        prev_x = prev2_x;
        prev_y = prev2_y;
    }

    switch (direction) {
        case 'u': snake_y--; break;
        case 'd': snake_y++; break;
        case 'l': snake_x--; break;
        case 'r': snake_x++; break;
    }

    if (snake_x < 1 || snake_x >= WIDTH - 1 || snake_y < 1 || snake_y >= HEIGHT - 1) game_over = 1;

    for (int i = 0; i < tail_length; i++) {
        if (tail_x[i] == snake_x && tail_y[i] == snake_y) game_over = 1;
    }

    if (snake_x == fruit_x && snake_y == fruit_y) {
        score += 10;
        fruit_x = rand() % (WIDTH - 2) + 1;
        fruit_y = rand() % (HEIGHT - 2) + 1;
        tail_length++;
    }
}

int main() {
    srand(time(NULL));
    setup();
    while (!game_over) {
        draw();
        input();
        logic();
    }
    endwin();
    printf("Game Over! Score: %d\n", score);
    return 0;
}

3、基于SDL库实现的贪吃蛇游戏

SDL 是一个多媒体库,可以用于开发简单的2D游戏。使用SDL可以创建图形界面,让游戏更有趣。如没安装SDL库,需要安装SDL库。

#include <SDL2/SDL.h>
#include <stdio.h>
#include <time.h>

#define WIDTH 640
#define HEIGHT 480
#define CELL_SIZE 20

typedef struct {
    int x, y;
} Point;

Point snake[100];
int snake_length = 1;
Point fruit;
int dx = 1, dy = 0;
int game_over = 0;

void init_game() {
    snake[0].x = WIDTH / (2 * CELL_SIZE);
    snake[0].y = HEIGHT / (2 * CELL_SIZE);
    fruit.x = rand() % (WIDTH / CELL_SIZE);
    fruit.y = rand() % (HEIGHT / CELL_SIZE);
}

void draw(SDL_Renderer *renderer) {
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);

    SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
    SDL_Rect fruit_rect = {fruit.x * CELL_SIZE, fruit.y * CELL_SIZE, CELL_SIZE, CELL_SIZE};
    SDL_RenderFillRect(renderer, &fruit_rect);

    SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
    for (int i = 0; i < snake_length; i++) {
        SDL_Rect rect = {snake[i].x * CELL_SIZE, snake[i].y * CELL_SIZE, CELL_SIZE, CELL_SIZE};
        SDL_RenderFillRect(renderer, &rect);
    }

    SDL_RenderPresent(renderer);
}

void update() {
    for (int i = snake_length - 1; i > 0; i--) {
        snake[i] = snake[i - 1];
    }

    snake[0].x += dx;
    snake[0].y += dy;

    if (snake[0].x == fruit.x && snake[0].y == fruit.y) {
        snake_length++;
        fruit.x = rand() % (WIDTH / CELL_SIZE);
        fruit.y = rand() % (HEIGHT / CELL_SIZE);
    }

    if (snake[0].x < 0 || snake[0].x >= WIDTH / CELL_SIZE || snake[0].y < 0 || snake[0].y >= HEIGHT / CELL_SIZE) {
        game_over = 1;
    }

    for (int i = 1; i < snake_length; i++) {
        if (snake[0].x == snake[i].x && snake[0].y == snake[i].y) {
            game_over = 1;
        }
    }
}

int main() {
    srand(time(NULL));

    SDL_Init(SDL_INIT_VIDEO);

    SDL_Window *window = SDL_CreateWindow("Snake", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

    init_game();

    while (!game_over) {
        SDL_Event event;
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) game_over = 1;
            if (event.type == SDL_KEYDOWN) {
                switch (event.key.keysym.sym) {
                    case SDLK_UP: if (dy == 0) { dx = 0; dy = -1; } break;
                    case SDLK_DOWN: if (dy == 0) { dx = 0; dy = 1; } break;
                    case SDLK_LEFT: if (dx == 0) { dx = -1; dy = 0; } break;
                    case SDLK_RIGHT: if (dx == 0) { dx = 1; dy = 0; } break;
                }
            }
        }

        update();
        draw(renderer);
        SDL_Delay(100);
    }

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    printf("Game Over! Score: %d\n", snake_length - 1);
    return 0;
}

推荐阅读
cjavapy编程之路首页