C语言基于链表实现贪吃蛇

来源:互联网 发布:Linux复杂源码 看懂 编辑:程序博客网 时间:2024/05/09 15:25

一 引言

数组实现的贪吃蛇代码比较复杂,换成链表逻辑更加清晰。每一个节点对应蛇的一节。

二 基本原理

对于贪吃蛇怎么在屏幕上移动,一种方法是移动蛇头,坐标依次传递,还有一种添头去尾。本文采用链表实现,移动采用添头去尾。

三 代码

/**************************************************************************
 **文件:snake.c
 **功能:贪吃蛇
 **编写者:Nightmare
 **编写日期:2017-01-28
 **简要说明:链表实现;可加速
 **修改者:
 **修改日期:
 **注:在VC 6.0下编写完成
 **************************************************************************/
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <time.h>


#define FrameX 4 //游戏地图位置
#define FrameY 4
#define FrameHeight 20
#define FrameWidth 40


int i;
char ch=72; //初始移动方向
int len=3; //初始蛇长
int speed=200; //初始速度
COORD cor; //临时坐标变量
int grow=0; //蛇是否变长


typedef struct Snake{ //蛇的结构体
COORD cor;
struct Snake* next;
}snake, *psnake;


psnake head; //蛇头
psnake p; //临时结点


struct Food{ //食物的结构体
COORD cor;
}food;


void initial(void); //初始化地图
void make_food(void); //产生食物
void get_speed(void); //获取速度
void move_snake(void); //蛇的移动
int is_alive(void); //蛇的死活
void free_snake(void); //释放内存
void gotoxy(COORD cor); //光标定位
int cor_com(COORD cor1, COORD cor2); //坐标比较


int main()
{
initial();
while(1)
{
make_food();
get_speed();
move_snake();
if(!is_alive())
break;
}
printf("Game Over!\n");
free_snake();
getch();


return 0;
}
/***********************光标移动***********************************************/
void gotoxy(COORD cor)
{
HANDLE hout;
hout=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hout,cor);
}
/************************ 坐标是否相等 ********************************************/
int cor_com(COORD cor1, COORD cor2)
{
return cor1.X==cor2.X && cor1.Y==cor2.Y;
}
/*************************** 初始化 ***********************************************/
void initial(void)
{
psnake p1,p2;
head=(psnake)malloc(sizeof(snake));//初始化蛇头位置
head->cor.X=FrameX+4;
head->cor.Y=FrameY+FrameHeight-6;
head->next=NULL;//定义一个新指针的同时指向空
gotoxy(head->cor);
printf("@");
p1=head;
for(i=1;i<len;i++)//初始化蛇身
{
p2=(psnake)malloc(sizeof(snake));
p2->cor.X=p1->cor.X;
p2->cor.Y=p1->cor.Y+1;
p2->next=NULL;
gotoxy(p2->cor);
printf("@");
p1->next=p2;
p1=p2;
}


srand((unsigned int)time(NULL));//初始化食物
food.cor.X=rand()%(FrameWidth-2)+1+FrameX;
food.cor.Y=rand()%(FrameHeight-2)+1+FrameY;
gotoxy(food.cor);
printf("!");



for(i=FrameY;i<FrameY+FrameHeight;i++)//初始化围墙
{
cor.X=FrameX; cor.Y=i;
gotoxy(cor);
printf("#");
cor.X=FrameX+FrameWidth-1;cor.Y=i;
gotoxy(cor);
printf("#");
}
for(i=FrameX+1;i<FrameX+FrameWidth-1;i++)
{
cor.X=i; cor.Y=FrameY;
gotoxy(cor);
printf("#");
cor.X=i; cor.Y=FrameY+FrameHeight-1;
gotoxy(cor);
printf("#");
}
}
/*************************************** 产生食物 ********************************/
void make_food(void)
{
if(cor_com(head->cor,food.cor))//是否吃到食物
{
srand((unsigned int)time(NULL));
food.cor.X=rand()%(FrameWidth-2)+1+FrameX;
food.cor.Y=rand()%(FrameHeight-2)+1+FrameY;
gotoxy(food.cor);
printf("!");


grow=1;
}
}
/*************************************** 得到速度 ***********************************/
void get_speed(void)
{
if(len%5==0)
speed-=50; //变速
}
/*************************************** 蛇的移动 *************************************/
void move_snake(void)
{
if(kbhit())
{
getch();
ch=getch();
}
if(!grow) //若蛇没有变长,去尾; 变长则不去尾
{
for(p=head;p->next->next!=NULL;p=p->next);
gotoxy(p->next->cor);
printf(" ");
free(p->next);
p->next=NULL;
}
p=(psnake)malloc(sizeof(snake));//添头(新的蛇头)
p->cor=head->cor;
p->next=head;
head=p;
switch(ch)
{
case 72: p->cor.Y--;break;
case 80: p->cor.Y++;break;
case 75: p->cor.X--;break;
case 77: p->cor.X++;break;
default: break;
}
gotoxy(p->cor);
printf("@");
grow=0;
Sleep(speed); //控制蛇的移动速度
}
/*************************************** 蛇的死活 *************************************/
int is_alive(void)
{
cor.X=FrameX;
cor.Y=FrameY+FrameHeight;
gotoxy(cor);
for(p=head->next;p!=NULL;p=p->next)//是否自食
{
if(cor_com(p->cor,head->cor))
break;
}
if(p!=NULL)
return 0;
else //是否撞墙
{
for(i=FrameY;i<FrameY+FrameHeight;i++)
{
cor.X=FrameX; cor.Y=i;
if(cor_com(cor,head->cor))
return 0;
cor.X=FrameX+FrameWidth-1;cor.Y=i;
if(cor_com(cor,head->cor))
return 0;
}
for(i=FrameX+1;i<FrameX+FrameWidth-1;i++)
{
cor.X=i; cor.Y=FrameY;
if(cor_com(cor,head->cor))
return 0;
cor.X=i; cor.Y=FrameY+FrameHeight-1;
if(cor_com(cor,head->cor))
return 0;
}
}
return 1;
}
/******************************** 释放内存 ****************************************/
void free_snake()
{
p=head;
while(head!=NULL)
{
head=head->next;
free(p);
p=head;
}
}
补充:由于一些原因,没有写食物不能出现在蛇身上的判定,可自行补充。
0 0
原创粉丝点击