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