贪吃蛇

#include <stdio.h>

#include <windows.h>

#include <stdlib.h>

#include <conio.h>

#include <stdbool.h>

#include <time.h>

#pragma warning(disable:4996)

#define S 200

 

//定位坐标

void gotoxy(int x, int y)

{

COORD pos;

pos.X = x - 1;

pos.Y = y - 1;

SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);

}

 

//蛇的一个节点

typedef struct SNAKE

{

int x; //使用横坐标

int y; //使用纵坐标

struct SNAKE *next;

}snake;

 

//需要的函数

void show(void); //主界面

void tail(void); //输出蛇

void game(void); //开始游戏

void esc_key(void); //按ESC键退出

void up(void); //按向上键

void down(void); //按向下键

void left(void); //按向左键

void right(void); //按向右键

void out(void); //过界

void out_tail(void); //碰到蛇身

void out_food(void); //食物

 

//需要的全局变量

snake *head; //蛇头

int score = 0; //分数

char game_key; //游戏接收用户输入指令

snake *p; //遍历蛇移动

snake *next_head; //蛇移动时分配新蛇头

int m, n; //食物坐标

char food = '@'; //食物图标

int main(void)

{

score = 0;

show();

tail(); //打印蛇身

game();

 

system("pause");

return 0;

}

 

//主界面

void show(void)

{

int i;

for (i = 1; i < 58; i += 2) //打印上下边框

{

gotoxy(i, 1);

printf("■");

gotoxy(i, 24);

printf("■");

}

for (i = 1; i < 24; i++) //打印左右边框

{

gotoxy(1, i);

printf("■");

gotoxy(57, i);

printf("■");

}

//打印辅助信息

gotoxy(65, 5);

printf("欢迎来到贪吃蛇!");

gotoxy(65, 10);

printf("得分:");

gotoxy(65, 15);

printf("游戏说明: 按任意开始,按回车键暂停,按ESC键退出游戏.");

gotoxy(75, 17);

printf("使用W,S,A,D键控制上下左右移动.");

gotoxy(75, 19);

printf("吃一食物得1分,不可过界,不可撞自己.");

gotoxy(65, 23);

printf("作者:完美教父");

}

 

//输出蛇身

void tail(void)

{

int i; //循环变量

snake *tail;

tail = (snake *)malloc(sizeof(snake)); //分配地址,定义蛇尾坐标

tail->x = 23;

tail->y = 5;

tail->next = NULL;

for (i = 1; i <= 4; i++) //遍历增加蛇头

{

head = (snake *)malloc(sizeof(snake)); //分配地址,定义一个蛇头坐标

head->next = tail; //将蛇头链接蛇尾

head->x = 23 + 2 * i; //定义蛇头X坐标

head->y = 5; //定义蛇头Y坐标

tail = head; //蛇头链接完蛇尾后,将原蛇尾赋给蛇头,以便下次循环,创建了新的蛇头坐标,它就做为蛇身使用

}

for (i = 0; i <= 4; i++) //遍历打印出蛇身

{

gotoxy(tail->x, tail->y);

printf("■");

tail = tail->next;

}

 

}

 

//开始游戏

void game(void)

{

game_key = getch();

if (game_key == 27) //当按ESC键出现退出选单

{

esc_key();

}

out_food(); //随机出现食物

while(1)

{

Sleep(S); //移动速度

gotoxy(65, 10);

printf("得分:%d", score);

if (kbhit())

{

game_key = getch();

if (game_key == 27)

{

esc_key();

}

else if (game_key == 13)

{

gotoxy(22, 22);

printf("游戏暂停,请按任意键继续!");

getch();

gotoxy(22, 22);

printf("                        ");

 

}

else if (game_key == 'w' || game_key == 'W')

{

up();

}

else if (game_key == 's' || game_key == 'S')

{

down();

}

}

out(); //判断过界

out_tail(); //碰到蛇身

next_head = (snake *)malloc(sizeof(snake)); //分配移动时临时新蛇头

next_head->next = head; //将新蛇头的尾指向现有蛇头

next_head->x = head->x + 2; //初始化新蛇头横坐标

next_head->y = head->y; //初始化新蛇头纵坐标

head = next_head; //将head赋给新蛇头

gotoxy(head->x, head->y);

printf("■");

if (head->x == m && head->y == n)  //如果吃到食物,重新输出食物,并且分数加1

{

out_food();

score++;

}

else

{

p = head;

while (p->next->next != NULL) //遍历处理向前移动时删除尾部

{

p = p->next;

}

gotoxy(p->next->x, p->next->y);

printf(" ");

free(p->next); //释放尾节点

p->next = NULL; //新尾节点next指向NULL

}

}

}

 

//按ESC键退出

void esc_key(void)

{

char esc_k;

//int esc_z; //返回值

gotoxy(22, 22);

printf("是否退出游戏(Y/N)!");

esc_k = getch(); //接收用户输入确认指令(Y/N)

if (esc_k == 'y' || esc_k == 'Y')

{

exit(1); //当用户按y/Y esc_z返回1

}

else if (esc_k == 'n' || esc_k == 'N')

{

gotoxy(22, 22);

printf("                  ");

}

else

{

gotoxy(22, 22);

printf("输入有误,按任意键回到游戏!");

getch();

gotoxy(22, 22);

printf("                          ");

}

}

 

//按向上键

void up(void)

{

while (1)

{

Sleep(S);

gotoxy(65, 10);

printf("得分:%d", score);

if (kbhit())

{

game_key = getch();

if (game_key == 27)

{

esc_key();

}

else if (game_key == 13)

{

gotoxy(22, 22);

printf("游戏暂停,请按任意键继续!");

getch();

gotoxy(22, 22);

printf("                        ");

 

}

else if (game_key == 'a' || game_key == 'A')

{

left();

}

else if (game_key == 'd' || game_key == 'D')

{

right();

}

}

out();

out_tail(); //碰到蛇身

next_head = (snake *)malloc(sizeof(snake)); //分配移动时临时新蛇头

next_head->next = head; //将新蛇头的尾指向现有蛇头

next_head->x = head->x; //初始化新蛇头横坐标

next_head->y = head->y - 1; //初始化新蛇头纵坐标

head = next_head; //将head赋给新蛇头

gotoxy(head->x, head->y);

printf("■");

if (head->x == m && head->y == n)

{

out_food();

score++;

}

else

{

p = head;

while (p->next->next != NULL) //遍历处理向前移动时删除尾部

{

p = p->next;

}

gotoxy(p->next->x, p->next->y);

printf(" ");

free(p->next); //释放尾节点

p->next = NULL; //新尾节点next指向NULL

}

}

}

 

//按向下键

void down(void)

{

while (1)

{

Sleep(S);

gotoxy(65, 10);

printf("得分:%d", score);

if (kbhit())

{

if (kbhit())

{

game_key = getch();

if (game_key == 27)

{

esc_key();

}

else if (game_key == 13)

{

gotoxy(22, 22);

printf("游戏暂停,请按任意键继续!");

getch();

gotoxy(22, 22);

printf("                        ");

 

}

else if (game_key == 'a' || game_key == 'A')

{

left();

}

else if (game_key == 'd' || game_key == 'D')

{

right();

}

}

}

out();

out_tail(); //碰到蛇身

next_head = (snake *)malloc(sizeof(snake)); //分配移动时临时新蛇头

next_head->next = head; //将新蛇头的尾指向现有蛇头

next_head->x = head->x; //初始化新蛇头横坐标

next_head->y = head->y + 1; //初始化新蛇头纵坐标

head = next_head; //将head赋给新蛇头

gotoxy(head->x, head->y);

printf("■");

if (head->x == m && head->y == n)

{

out_food();

score++;

}

else

{

p = head;

while (p->next->next != NULL) //遍历处理向前移动时删除尾部

{

p = p->next;

}

gotoxy(p->next->x, p->next->y);

printf(" ");

free(p->next); //释放尾节点

p->next = NULL; //新尾节点next指向NULL

}

}

}

 

//按向左键

void left(void)

{

while (1)

{

Sleep(S);

gotoxy(65, 10);

printf("得分:%d", score);

if (kbhit())

{

game_key = getch();

if (game_key == 27)

{

esc_key();

}

else if (game_key == 13)

{

gotoxy(22, 22);

printf("游戏暂停,请按任意键继续!");

getch();

gotoxy(22, 22);

printf("                        ");

 

}

else if (game_key == 'w' || game_key == 'W')

{

up();

}

else if (game_key == 's' || game_key == 'S')

{

down();

}

}

out(); //过界

out_tail(); //碰到蛇身

next_head = (snake *)malloc(sizeof(snake)); //分配移动时临时新蛇头

next_head->next = head; //将新蛇头的尾指向现有蛇头

next_head->x = head->x - 2; //初始化新蛇头横坐标

next_head->y = head->y; //初始化新蛇头纵坐标

head = next_head; //将head赋给新蛇头

gotoxy(head->x, head->y);

printf("■");

if (head->x == m && head->y == n)

{

out_food();

score++;

}

else

{

p = head;

while (p->next->next != NULL) //遍历处理向前移动时删除尾部

{

p = p->next;

}

gotoxy(p->next->x, p->next->y);

printf(" ");

free(p->next); //释放尾节点

p->next = NULL; //新尾节点next指向NULL

}

}

}

 

//按向右键

void right(void)

{

while (1)

{

Sleep(S);

gotoxy(65, 10);

printf("得分:%d", score);

if (kbhit())

{

game_key = getch();

if (game_key == 27)

{

esc_key();

}

else if (game_key == 13)

{

gotoxy(22, 22);

printf("游戏暂停,请按任意键继续!");

getch();

gotoxy(22, 22);

printf("                        ");

 

}

else if (game_key == 'w' || game_key == 'W')

{

up();

}

else if (game_key == 's' || game_key == 'S')

{

down();

}

}

out(); //过界

out_tail(); //碰到蛇身

next_head = (snake *)malloc(sizeof(snake)); //分配移动时临时新蛇头

next_head->next = head; //将新蛇头的尾指向现有蛇头

next_head->x = head->x + 2; //初始化新蛇头横坐标

next_head->y = head->y; //初始化新蛇头纵坐标

head = next_head; //将head赋给新蛇头

gotoxy(head->x, head->y);

printf("■");

if (head->x == m && head->y == n)

{

out_food();

score++;

}

else

{

p = head;

while (p->next->next != NULL) //遍历处理向前移动时删除尾部

{

p = p->next;

}

gotoxy(p->next->x, p->next->y);

printf(" ");

free(p->next); //释放尾节点

p->next = NULL; //新尾节点next指向NULL

}

}

}

 

//过界

void out(void)

{

if (head->x == 57 || head->x == 1 || head->y ==1 || head->y == 24)

{

gotoxy(22, 22);

printf("过界了!!!按任意键重新游戏!");

getch();

system("cls");

main();

}

}

 

//碰到蛇身

void out_tail(void)

{

snake *p;

p = head;

while (p->next != NULL)

{

if (head->x == p->next->x && head->y == p->next->y)

{

gotoxy(22, 22);

printf("碰到蛇身!!!按任意键重新游戏");

getch();

system("cls");

main();

}

p = p->next;

}

}

 

//食物

void out_food(void)

{

snake *p;

p = head;

m = rand() % 52 + 4;

n = rand() % 20 + 4;

if (m % 2 == 0)

{

m += 1;

}

while (p->next != NULL)

{

if (p->x == m && p->y == n)

{

out_food();

}

p = p->next;

}

gotoxy(m, n);

printf("%c", food);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

完美教父

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值