傻瓜式贪吃蛇源码,稍微有点基础就能看懂
前言:
本人C语言并不好(大一新生),只是刚好学到链表时发现它很符合贪吃蛇的设定,所以突发奇想写了这个贪吃蛇。代码有点呆,发这篇文章仅仅是因为第一次写了一个算是有点可玩性的游戏很高兴想分享给大家而已。(虽然说这是个被玩烂了的、写烂了的游戏。)
再次声明:代码很拙劣,大佬勿喷。不过应该属于容易看懂的类型吧。。。。
基本原理:
因为蛇的身体所带数据结构都是相同的,又有顺序(从头到尾),所以可以使用链表来表示蛇。所以我写了个body结构包含{蛇的位置x,y坐标,这一部分的方向,下一个部分的地址,上一个部分的地址(在更新蛇的下一个状态时使用)},然后再不停的画蛇头蛇尾、清除蛇头蛇尾、画下一个状态的蛇头蛇尾。实现动态的效果。
源码:
#include "stdio.h"
#include "windows.h"
#include "conio.h"
#include "time.h"//Only use it to srand
#define CHANDLE (GetStdHandle(STD_OUTPUT_HANDLE))
#define WEITH 40
#define HIGHT 25
#define SIDE "■"
#define HEAD "●"
#define TAIL "○"
enum Derction{up,down,left,right};
struct Body
{
int x;
int y;
Derction D;
struct Body *next;
struct Body *last;
};
typedef struct Body NODE;
//the body of snake
NODE *CreatSnake();
NODE *AddLenth(NODE *head);
//updata the position of snake
void Updataxy(NODE *p,int type);
void UpdataSnake(NODE *tail);
//other
void game();
void xyprint(int x,int y,char *s) ;
void HideCursor();
void PrintMap();
int main()
{
system("title 贪吃蛇小游戏——by Wander303");
HideCursor();
PrintMap();
game() ;
xyprint(0,HIGHT,"Game Over!!!!");
return 0;
}
void xyprint(int x,int y,char *s)
{
SetConsoleCursorPosition(CHANDLE,(COORD){x,y});
printf("%s",s);
}
void HideCursor()
{
CONSOLE_CURSOR_INFO Cur;
Cur.bVisible =0;
Cur.dwSize =1;
SetConsoleCursorInfo(CHANDLE,&Cur);
}
void PrintMap()
{
int i,j;
srand(time(NULL));
for(i=0;i<HIGHT;i++)
if(i==0||i==HIGHT-1)
for(j=0;j<WEITH;j++)
xyprint(j*2,i,SIDE);
else
{
xyprint(0,i,SIDE);
xyprint((WEITH-1)*2,i,SIDE);
}
}
COORD NewFood()
{
COORD food;
food.X=((rand()%(WEITH-2))/2)*2+2;
food.Y=((rand()%(HIGHT-2))/2)*2+1;
xyprint(food.X,food.Y,"★");
return food;
}
NODE *CreatSnake()
{
NODE *head;
head=(NODE *)malloc(sizeof(NODE));
head->next =NULL;
head->last=NULL;
head->x = WEITH;//set the initial position
head->y =HIGHT/2;
head->D =right;
xyprint(head->x,head->y,HEAD);
return head;
}
NODE *AddLenth(NODE *head)
{
NODE *pnow=head;
for(;pnow->next!=NULL;)
pnow=pnow->next;
pnow->next=(NODE *)malloc(sizeof(NODE));
*(pnow->next)=*pnow;
pnow->next->last=pnow;
pnow=pnow->next;
Updataxy(pnow,0);
xyprint(pnow->x,pnow->y,TAIL);
pnow->next =NULL;
return pnow;
}
void UpdataSnake(NODE *tail)//updata the snake state
{
NODE *pnow=tail;
for(;pnow->last!=NULL;)
{
pnow->x=pnow->last->x;
pnow->y=pnow->last->y;
pnow->D=pnow->last->D ;
pnow=pnow->last;
}
}
void Updataxy(NODE *p,int type)//addlenth use type==0,other user type!=0;
{
switch(p->D)
{
case up:p->y-=(type)?1:-1;break;
case down:p->y+=(type)?1:-1;break;
case left:p->x-=(type)?2:-2;break;
case right:p->x+=(type)?2:-2;break;
}
}
void DrawSnake(NODE *head,NODE *tail)
{
xyprint(head->x,head->y,TAIL);
xyprint(tail->x,tail->y," ");
UpdataSnake(tail);
Updataxy(head,1);
xyprint(head->x,head->y,HEAD);
xyprint(tail->x,tail->y,TAIL);
}
int gameover(NODE *head)
{
NODE *pnow=head->next;
if(head->x==0||head->x==(WEITH-1)*2||head->y==0||head->y==HIGHT-1)
return 1;
for(;pnow!=NULL;)
if(head->x==pnow->x && head->y==pnow->y)
return 1;
else
pnow=pnow->next ;
return 0;
}
void game()
{
NODE *head,*tail;
COORD food=NewFood();
char c;
int i;
head=CreatSnake();
tail=AddLenth(head);
while(1)
{
if(kbhit())
{
switch(getch())
{
case 'w': if(head->D!=down)head->D = up;break;
case 's': if(head->D!=up)head->D = down;break;
case 'd': if(head->D!=left)head->D = right;break;
case 'a': if(head->D!=right)head->D = left;break;
}
}
DrawSnake(head,tail);
if(food.X==head->x &&food.Y ==head->y )
{
tail=AddLenth(head);
PrintMap();//if del it,sometime the map side will be destroy
food=NewFood();
}
Sleep(300);//the move speed of snake
if(gameover(head))
return;
}
}
/*
ps:支持一下新人吧!!,动动你的手指写个评论呗!什么?你懒得打字,那……点个赞也行。。
欢迎转载,但记得备注本文链接……
*/