六,C语言编写贪吃蛇游戏
贪吃蛇游戏是一个经典小游戏,一条蛇在封闭围墙里,围墙里随机出现一个食物,通过按键盘四个光标键控制蛇向上下左右四个方向移动,蛇头撞倒食物,则食物被吃掉,蛇身体长一节,同时记10分,接着又出现食物,等待蛇来吃,如果蛇在移动中撞到墙或身体交叉蛇头撞倒自己身体游戏结束。
下面就先说说游戏的规则:
开始:按左键开始游戏,按按钮或菜单重新开始。
下键:按下时,是蛇向下行, 当碰到墙壁时,游戏结束。
左键:按左时,是蛇向左行, 当碰到墙壁时,游戏结束。
右键:按右时,是蛇向右行, 当碰到墙壁时,游戏结束。
上键:按上时,是蛇向上行, 当碰到墙壁时,游戏结束。
当碰到目标时 计分器 加10分
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
#define DOWN_WALL 20
#define RIGHT_WALL 58
typedef struct s_snack //每一段蛇身的坐标位置
{
int x;
int y;
struct s_snack *next; //下一段蛇身
}Snake;
void Mcursor(int x, int y);
int IsHitWall();
int IsBiteYouself();
void DrawFrame();
void InitSnake();
void CreateFood();
void PlayGame();
int Move();
void Welcome();
void free_snack(Snake *head);
Snake *head, *end;
Snake *p;
int speed = 310;
int level = 0, score = 0;
int foodx, foody;
char key;
int main()
{
Loop:system("cls");
system("color 4f");
system("cls");
Welcome();
DrawFrame();
InitSnake();
CreateFood();
int i;
Mcursor(60, 7);
printf("得分:%d\n", score);
Mcursor(60, 8);
printf("当前速度:%d毫秒\n", speed);
Mcursor(60, 9);
printf("每+30分速度变快\n");
Mcursor(60, 10);
printf("不能撞墙/咬到自己\n");
Mcursor(60, 11);
printf("按空格暂停/继续\n");
PlayGame();
free_snack(head);
Mcursor(25, 8);
printf("请选择:\n1.继续游戏\n2.结束游戏\n");
scanf("%d", &i);
if (i >= 0 && i <= 1)
{
if (i == 0)
return 0;
if (i == 1)
goto Loop;
}
else
{
printf("error!!\n");
}
return 0;
}
void Mcursor(int x, int y)
{
COORD pos = { x,y };
HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(output, pos);
}
int IsHitWall()
{
if (head->x == 0 || head->x == RIGHT_WALL || head->y == 0 || head->y == DOWN_WALL)
{
Mcursor(DOWN_WALL, 14);
printf("游戏结束!撞到墙了,贪吃蛇死亡!!\n");
Mcursor(DOWN_WALL, 15);//令 ‘按任意键继续...’居中显示
return 1;
}
return 0;
}
int IsBiteYouself()
{
while (p->next != NULL)
{
p = p->next;
if (head->x == p->x&&head->y == p->y)
{
Mcursor(DOWN_WALL, 14);
printf("游戏结束!你咬到自己了,贪吃蛇死亡!!\n");
Mcursor(DOWN_WALL, 15);
return 1;
}
}
return 0;
}
void DrawFrame()
{
int i = 0;
for (i = 0; i < 60; i += 2)
{
Mcursor(i, 0);
printf("□");
Mcursor(i, DOWN_WALL);
printf("□");
}
for (i = 1; i < DOWN_WALL; i++)
{
Mcursor(0, i);
printf("□");
Mcursor(RIGHT_WALL, i);
printf("□");
}
}
void InitSnake()//初始化蛇身 头插法
{
int i = 0;
end = (Snake*)malloc(sizeof(Snake));
end->x = 20;
end->y = 15;
end->next = NULL;
for (i = 1; i <= 3; i++)
{
head = (Snake*)malloc(sizeof(Snake));
head->x = 20 + 2 * i;
head->y = 15;
head->next = end;
end = head;
}
while (end->next != NULL)
{
Mcursor(end->x, end->y);
printf("■");
end = end->next;
}
}
void CreateFood()
{
srand(time(0));
flag:
while (1)//food的x坐标必须为偶数
{
foody = rand() % (DOWN_WALL - 1 + 1 - 1) + 1;//foody的有效范围在 [1,DOWN_WALL-1 ]。rand()%num产生 0~num-1,rand产生范围数公式rand()%(m+1-n)+n;有效范围在 [n,m]
foodx = rand() % (RIGHT_WALL - 2 + 1 - 3) + 3;//foodx的有效范围在[3,RIGHT_WALL-2] 注意x是以2为单位的
if (foodx % 2 == 0)
break;
}
p = head;
while (1)
{
if (p->x == foodx && p->y == foody)//若生成坐标和蛇重叠了,回到生成坐标循环
goto flag;
if (p->next == NULL)
break;
p = p->next;
}
Mcursor(foodx, foody);
printf("☆");
}
void PlayGame()
{
int mv_ret = 0;
key = 'd';
while (1)
{
if ((GetAsyncKeyState(VK_UP) && 0x8000) && key != 's')
/*与key!='s',因为不能后退,GetAsyncKeyState(VK_UP) 判断VK_UP按键的状态
若是被按下,则位15设为1;如抬起,则为0,要与上0x8000 取出第15位进行判断*/
key = 'w';
else
{
if ((GetAsyncKeyState(VK_DOWN) && 0x8000) && key != 'w')
key = 's';
else
{
if ((GetAsyncKeyState(VK_RIGHT) && 0x8000) && key != 'a')
key = 'd';
else
{
if ((GetAsyncKeyState(VK_LEFT) && 0x8000) && key != 'd')
key = 'a';
else
{
if (GetAsyncKeyState(VK_SPACE) && 0x8000)
{
while (p->next != NULL) p = p->next;
Mcursor(p->x, p->y);
printf("■");
while (1)
{
Sleep(100);
if (GetAsyncKeyState(VK_SPACE) && 0x8000)
{
break;
}
}
Mcursor(p->x, p->y);
printf(" ");
}
else
{
if (GetAsyncKeyState(VK_ESCAPE) && 0x8000)//按下ESC退出游戏,VK_ESCAPE == 27
return;
}
}
}
}
}
if (score == level && speed > 10)
{
speed -= 10;
level += 30;
Mcursor(60, 8);
printf("当前速度:%d毫秒", speed);
}
mv_ret = Move();
if (mv_ret == 1)
{
break;
}
}
}
int Move()
{
int ret;
if ((key != 'a') && (key != 's') && (key != 'd') && (key != 'w'))
{
return 0;
}
ret = IsHitWall();
ret += IsBiteYouself();
if (ret == 1)
{
return 1;
}
p = (Snake*)malloc(sizeof(Snake));
p->next = head;
switch (key)
{
case 'd':
p->x = head->x + 2;
p->y = head->y;
break;
case 'w':
p->x = head->x;
p->y = head->y - 1;
break;
case 's':
p->x = head->x;
p->y = head->y + 1;
break;
case 'a':
p->x = head->x - 2;
p->y = head->y;
break;
}
Mcursor(p->x, p->y);
printf("■");
head = p;
Sleep(speed);
if (p->x == foodx && p->y == foody)
{
CreateFood();
score += 10;
Mcursor(60, 7);
printf("得分:%d", score);
}
else
{
while (p->next->next != NULL) p = p->next;
Mcursor(p->x, p->y);
printf(" ");
free(p->next);
p->next = NULL;
p = head;
}
return 0;
}
void Welcome()
{
Mcursor(25, 8);
printf("【贪吃蛇游戏】");
Mcursor(25, 11);
printf("【游戏规则】");
Mcursor(25, 12);
printf("1、不能撞墙、咬到自己");
Mcursor(25, 13);
printf("2、按空格暂停/继续游戏");
printf("\n");
Mcursor(30, 15);
system("pause");
system("cls");
}
void free_snack(Snake *head)
{
if (head == NULL || head->next == NULL)
{
return;
}
while ((p = head) != NULL)
{
head = head->next;
}
free(p);
}
不足之处,请多指教!