使用SetTimer函数和线程函数编写一个贪吃蛇C语言程序
时间: 2024-03-02 22:52:55 浏览: 70
以下是使用SetTimer函数和线程函数编写的贪吃蛇C语言程序的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
// 定义界面大小
const int WIDTH = 30;
const int HEIGHT = 20;
// 定义蛇的长度和位置
const int INIT_LENGTH = 3;
int snakeX[100] = {0};
int snakeY[100] = {0};
int snakeLength = INIT_LENGTH;
// 定义食物的位置
int foodX = 0;
int foodY = 0;
// 定义蛇的运动方向
const int DIR_UP = 1;
const int DIR_DOWN = 2;
const int DIR_LEFT = 3;
const int DIR_RIGHT = 4;
int direction = DIR_RIGHT;
// 定义游戏是否结束
int gameOver = 0;
// 定义互斥锁
HANDLE mutex;
// 定义绘制界面函数
void draw()
{
// 清空控制台输出
system("cls");
// 输出上边界
for (int i = 0; i < WIDTH; i++)
{
printf("#");
}
printf("\n");
// 输出中间部分
for (int i = 0; i < HEIGHT; i++)
{
printf("#");
for (int j = 0; j < WIDTH - 2; j++)
{
if (i == foodY && j == foodX)
{
printf("*"); // 输出食物
}
else
{
int flag = 0;
for (int k = 0; k < snakeLength; k++)
{
if (i == snakeY[k] && j == snakeX[k])
{
printf("o"); // 输出蛇
flag = 1;
break;
}
}
if (flag == 0)
{
printf(" "); // 输出空格
}
}
}
printf("#\n");
}
// 输出下边界
for (int i = 0; i < WIDTH; i++)
{
printf("#");
}
printf("\n");
}
// 定义更新蛇的位置函数
void updateSnake()
{
// 上锁
WaitForSingleObject(mutex, INFINITE);
// 更新蛇的位置
for (int i = snakeLength - 1; i > 0; i--)
{
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
switch (direction)
{
case DIR_UP:
snakeY[0]--;
break;
case DIR_DOWN:
snakeY[0]++;
break;
case DIR_LEFT:
snakeX[0]--;
break;
case DIR_RIGHT:
snakeX[0]++;
break;
}
// 判断是否吃到食物
if (snakeX[0] == foodX && snakeY[0] == foodY)
{
snakeLength++;
foodX = rand() % (WIDTH - 2) + 1;
foodY = rand() % (HEIGHT - 2) + 1;
}
// 判断是否碰到墙壁或自身
if (snakeX[0] < 0 || snakeX[0] >= WIDTH - 2 ||
snakeY[0] < 0 || snakeY[0] >= HEIGHT ||
snakeLength > 100)
{
gameOver = 1;
}
for (int i = 1; i < snakeLength; i++)
{
if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i])
{
gameOver = 1;
break;
}
}
// 解锁
ReleaseMutex(mutex);
}
// 定义更新方向函数
void updateDirection(int dir)
{
// 上锁
WaitForSingleObject(mutex, INFINITE);
// 更新方向
switch (dir)
{
case 'w':
if (direction != DIR_DOWN)
{
direction = DIR_UP;
}
break;
case 's':
if (direction != DIR_UP)
{
direction = DIR_DOWN;
}
break;
case 'a':
if (direction != DIR_RIGHT)
{
direction = DIR_LEFT;
}
break;
case 'd':
if (direction != DIR_LEFT)
{
direction = DIR_RIGHT;
}
break;
}
// 解锁
ReleaseMutex(mutex);
}
// 定义定时器回调函数
VOID CALLBACK timerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
// 更新蛇的位置
updateSnake();
// 绘制界面
draw();
// 判断游戏是否结束
if (gameOver == 1)
{
KillTimer(NULL, idEvent);
printf("Game Over!\n");
}
}
// 定义线程函数
DWORD WINAPI threadProc(LPVOID lpParameter)
{
while (1)
{
char ch = _getch();
updateDirection(ch);
}
}
// 主函数
int main()
{
// 初始化互斥锁
mutex = CreateMutex(NULL, FALSE, NULL);
// 初始化随机数种子
srand((unsigned)time(NULL));
// 初始化蛇的位置
for (int i = 0; i < INIT_LENGTH; i++)
{
snakeX[i] = INIT_LENGTH - i - 1;
snakeY[i] = 0;
}
// 初始化食物的位置
foodX = rand() % (WIDTH - 2) + 1;
foodY = rand() % (HEIGHT - 2) + 1;
// 创建定时器
UINT_PTR timerID = SetTimer(NULL, 0, 100, timerProc);
// 创建线程
HANDLE thread = CreateThread(NULL, 0, threadProc, NULL, 0, NULL);
// 等待线程结束
WaitForSingleObject(thread, INFINITE);
// 关闭互斥锁
CloseHandle(mutex);
return 0;
}
```
该程序使用了SetTimer函数创建定时器和CreateThread函数创建线程,实现了贪吃蛇的基本功能。其中,定时器回调函数timerProc用于更新蛇的位置和绘制界面,线程函数threadProc用于监听键盘输入并更新蛇的运动方向。程序使用互斥锁对共享资源进行保护,确保线程安全。
阅读全文