贪吃蛇C语言代码,使用线程和定时器
时间: 2024-03-18 11:42:22 浏览: 70
以下是贪吃蛇的C语言代码,使用了线程和定时器实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <windows.h>
#define MAP_WIDTH 40
#define MAP_HEIGHT 20
#define SNAKE_INIT_LENGTH 3
#define SNAKE_MAX_LENGTH 100
// 定义方向
enum Direction {
UP,
DOWN,
LEFT,
RIGHT
};
// 定义蛇的结构体
struct Snake {
int x[SNAKE_MAX_LENGTH];
int y[SNAKE_MAX_LENGTH];
int length;
enum Direction direction;
};
// 定义食物的结构体
struct Food {
int x;
int y;
};
// 定义地图
char map[MAP_HEIGHT][MAP_WIDTH];
// 定义蛇和食物
struct Snake snake;
struct Food food;
// 定义线程和定时器
HANDLE hTimer;
HANDLE hThread;
// 初始化地图
void init_map() {
int i, j;
for (i = 0; i < MAP_HEIGHT; i++) {
for (j = 0; j < MAP_WIDTH; j++) {
if (i == 0 || i == MAP_HEIGHT - 1 || j == 0 || j == MAP_WIDTH - 1)
map[i][j] = '#';
else
map[i][j] = ' ';
}
}
}
// 初始化蛇
void init_snake() {
int i;
snake.length = SNAKE_INIT_LENGTH;
snake.direction = RIGHT;
for (i = 0; i < SNAKE_INIT_LENGTH; i++) {
snake.x[i] = MAP_WIDTH / 2 - i;
snake.y[i] = MAP_HEIGHT / 2;
}
}
// 初始化食物
void init_food() {
srand(time(NULL));
food.x = rand() % (MAP_WIDTH - 2) + 1;
food.y = rand() % (MAP_HEIGHT - 2) + 1;
}
// 更新地图
void update_map() {
int i, j;
for (i = 0; i < MAP_HEIGHT; i++) {
for (j = 0; j < MAP_WIDTH; j++) {
if (i == 0 || i == MAP_HEIGHT - 1 || j == 0 || j == MAP_WIDTH - 1)
map[i][j] = '#';
else
map[i][j] = ' ';
}
}
for (i = 0; i < snake.length; i++) {
map[snake.y[i]][snake.x[i]] = '*';
}
map[food.y][food.x] = '@';
}
// 控制蛇的移动
void move_snake() {
int i;
for (i = snake.length - 1; i > 0; i--) {
snake.x[i] = snake.x[i - 1];
snake.y[i] = snake.y[i - 1];
}
switch (snake.direction) {
case UP:
snake.y[0]--;
break;
case DOWN:
snake.y[0]++;
break;
case LEFT:
snake.x[0]--;
break;
case RIGHT:
snake.x[0]++;
break;
}
}
// 判断蛇是否吃到食物
void eat_food() {
if (snake.x[0] == food.x && snake.y[0] == food.y) {
snake.length++;
if (snake.length > SNAKE_MAX_LENGTH)
snake.length = SNAKE_MAX_LENGTH;
init_food();
}
}
// 判断蛇是否撞墙或者撞到自己
int is_dead() {
int i;
if (snake.x[0] == 0 || snake.x[0] == MAP_WIDTH - 1 || snake.y[0] == 0 || snake.y[0] == MAP_HEIGHT - 1)
return 1;
for (i = 1; i < snake.length; i++) {
if (snake.x[0] == snake.x[i] && snake.y[0] == snake.y[i])
return 1;
}
return 0;
}
// 游戏结束
void gameover() {
printf("Game Over!\n");
printf("Press any key to continue...\n");
_getch();
exit(0);
}
// 控制蛇的方向
void control() {
if (_kbhit()) {
switch (_getch()) {
case 'w':
if (snake.direction != DOWN)
snake.direction = UP;
break;
case 's':
if (snake.direction != UP)
snake.direction = DOWN;
break;
case 'a':
if (snake.direction != RIGHT)
snake.direction = LEFT;
break;
case 'd':
if (snake.direction != LEFT)
snake.direction = RIGHT;
break;
}
}
}
// 定时器回调函数
VOID CALLBACK timer_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired) {
move_snake();
eat_food();
update_map();
control();
if (is_dead())
gameover();
}
// 线程函数
DWORD WINAPI thread_func(LPVOID lpParam) {
while (1) {
WaitForSingleObject(hTimer, INFINITE);
}
return 0;
}
// 主函数
int main() {
init_map();
init_snake();
init_food();
update_map();
printf("Press any key to start...\n");
_getch();
hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
LARGE_INTEGER liDueTime;
liDueTime.QuadPart = 0;
SetWaitableTimer(hTimer, &liDueTime, 1000 / 10, timer_callback, NULL, FALSE);
hThread = CreateThread(NULL, 0, thread_func, NULL, 0, NULL);
while (1) {
system("cls");
int i, j;
for (i = 0; i < MAP_HEIGHT; i++) {
for (j = 0; j < MAP_WIDTH; j++) {
printf("%c", map[i][j]);
}
printf("\n");
}
Sleep(1000 / 10);
}
return 0;
}
```
上面的代码中,使用了定时器和线程来控制蛇的移动和游戏的进行。其中,定时器用来定时调用回调函数,线程用来等待定时器的信号。回调函数中包含了蛇的移动、吃食物、更新地图、控制方向等逻辑,线程函数中输出地图并等待定时器的信号。通过这种方式,可以实现一个简单的贪吃蛇游戏。
阅读全文