#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#define WIDTH 20
#define HEIGHT 15
// 地图
char map[HEIGHT][WIDTH];
// 蛇结构体
typedef struct {
int x;
int y;
} Segment;
// 蛇
Segment snake[(WIDTH * HEIGHT) / 2]; // 最大长度为地图面积的一半
// 蛇的长度
int snakeLength = 1;
// 方向
enum Direction { UP, DOWN, LEFT, RIGHT };
enum Direction direction = RIGHT;
// 食物
Segment food;
// 分数
int score = 0;
// 函数声明
void draw();
void generateFood();
int checkCollision(int x, int y);
// 捕获键盘输入
char getch() {
char buf = 0;
struct termios old = {0};
if (tcgetattr(0, &old) < 0)
perror("tcsetattr()");
old.c_lflag &= ~ICANON;
old.c_lflag &= ~ECHO;
old.c_cc[VMIN] = 1;
old.c_cc[VTIME] = 0;
if (tcsetattr(0, TCSANOW, &old) < 0)
perror("tcsetattr ICANON");
if (read(0, &buf, 1) < 0)
perror ("read()");
old.c_lflag |= ICANON;
old.c_lflag |= ECHO;
if (tcsetattr(0, TCSADRAIN, &old) < 0)
perror ("tcsetattr ~ICANON");
return buf;
}
int main() {
// 初始化地图
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < WIDTH; j++) {
map[i][j] = ' ';
}
}
// 初始化蛇的位置
snake[0].x = WIDTH / 2;
snake[0].y = HEIGHT / 2;
// 生成食物
generateFood();
// 游戏主循环
int running = 1;
printf("按下键盘中的以移动(w上 s下 a左 d右 q退出 r重新开始): ");
while (running) {
system("clear");
draw();
char input = getch();// 获取用户输入
// 更新蛇的方向
enum Direction newDirection = direction;
if (input == 'w') {
newDirection = UP;
} else if (input == 's') {
newDirection = DOWN;
} else if (input == 'a') {
newDirection = LEFT;
} else if (input == 'd') {
newDirection = RIGHT;
} else if (input == 'q') {
running = 0;
} else if (input == 'r') {
// 重新初始化游戏状态
snake[0].x = WIDTH / 2;
snake[0].y = HEIGHT / 2;
snakeLength = 1;
direction = RIGHT;
score = 0;
generateFood();
running = 1;
continue;
}
direction = newDirection;
printf("Direction:%c", input); //打印出方向
// 计算新的蛇头位置
int newHeadX = snake[0].x;
int newHeadY = snake[0].y;
if (direction == UP) {
newHeadY--;
} else if (direction == DOWN) {
newHeadY++;
} else if (direction == LEFT) {
newHeadX--;
} else if (direction == RIGHT) {
newHeadX++;
}
// 检查是否撞到蛇身或出界
if (checkCollision(newHeadX, newHeadY)) {
running = 0;
printf("Game Over\n");
break;
}
// 更新蛇的位置
for (int i = snakeLength - 1; i > 0; i--) {
snake[i] = snake[i - 1];
}
snake[0].x = newHeadX;
snake[0].y = newHeadY;
// 判断是否吃到食物
if (newHeadX == food.x && newHeadY == food.y) {
score++;
generateFood();
snakeLength++;
}
}
return 0;
}
// 绘制地图
void draw() {
// 清空地图
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < WIDTH; j++) {
map[i][j] = ' ';
}
}
// 绘制蛇
for (int i = 0; i < snakeLength; i++) {
int x = snake[i].x;
int y = snake[i].y;
if (i == 0) {
map[y][x] = 'O'; // 蛇头
} else {
map[y][x] = 'o'; // 蛇身
}
}
// 绘制食物
int x = food.x;
int y = food.y;
map[y][x] = '*';
// 打印地图和分数
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < WIDTH; j++) {
printf("%c", map[i][j]);
}
printf("\n");
}
printf("Score: %d\n", score);
}
// 生成食物
void generateFood() {
srand(time(NULL));
food.x = rand() % WIDTH;
food.y = rand() % HEIGHT;
}
// 检查是否撞到蛇身或出界
int checkCollision(int x, int y) {
// 是否出界
if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) {
return 1;
}
// 是否撞到蛇身
for (int i = 0; i < snakeLength; i++) {
if (snake[i].x == x && snake[i].y == y) {
return 1;
}
}
return 0;
}
