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; }