纯C写的windows下贪吃蛇,BUG检查中。。。(2010.6.7更新)

/*
贪吃蛇
规则:在BOUNDRY*BOUNDRY的矩阵上有一条初始长度为2的蛇,BOUNDRY*BOUNDRY矩阵内
随机产生一个食物,当蛇与食物相遇时,长度加1,运动方向由方向键控制。初始向右。

流程如下:

开始->监听键盘->方向键1,暂停键2,其他键3

方向键1->下一秒蛇身按照方向键运动->判断->蛇身是否与便捷或自身相碰->是4,否5
是4->游戏结束
否5->判断:是否碰到食物->是6,否7

是6->蛇身长度加1,蛇头坐标变为食物所在坐标->监听键盘
否7->监听键盘

暂停键2:暂停

其他键3:无动作 
关键的一个函数:kbhit(),非阻塞函数,用于判断是否按下键盘,按下返回键值,否则返回0 
迷你了TC的gotoxy(int x,int y)函数,从而解决了屏幕闪烁问题
*/

/*Made by Shadow*/
/*---------------CODE-------------*/

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<conio.h>
#include<windows.h>
#define BOUNDRY 21

int area[BOUNDRY][BOUNDRY];
/*Map:
      0-normal
      1-snake
      2-food
      3-boundry
      4-obstacle(optional)*/

struct snake
{
       int x,y;/*each node's location*/
       struct snake *next;/*a pionter to the next node*/
}*head;

int foodon=0;/*a flag wether there's food on the map*/
char direction='d';/*use w-up,s-down,a-left,d-right*/
float speed=0.5;/*initilize speed*/
int s_length=2;/*snake's length*/
int level=1;/*game level which is related to snake's length*/

struct
{
      int x,y;
}food;/*food's location*/

void makemap()/*initialization of map*/
{
     int i,j;
     for (i=0;i<BOUNDRY;i++)
         for (j=0;j<BOUNDRY;j++) area[i][j]=0;
     for (i=0,j=0;j<BOUNDRY;j++) area[i][j]=3;
     for (i=0,j=0;i<BOUNDRY;i++) area[i][j]=3;
     for (i=BOUNDRY-1,j=0;j<BOUNDRY;j++) area[i][j]=3;
     for (i=0,j=BOUNDRY-1;i<BOUNDRY;i++) area[i][j]=3;
     //area[(int)BOUNDRY/2][(int)BOUNDRY/2]=1;
     //area[(int)BOUNDRY/2-1][(int)BOUNDRY/2-1]=1;
}

void locatesnake()/*head for finding snake's location*/
{
     struct snake *p_snake;/*current node of snake*/
     for (p_snake=head;p_snake->next!=NULL;p_snake=p_snake->next)
     area[p_snake->x][p_snake->y]=1;
     area[p_snake->x][p_snake->y]=1;
}

void locatefood()/*create food in a normal block*/
{
     do
     {
         food.x=(int)(rand()/(RAND_MAX+1.0)*BOUNDRY);
         food.y=(int)(rand()/(RAND_MAX+1.0)*BOUNDRY);
     }while(area[food.x][food.y]!=0);
     foodon=1;
     area[food.x][food.y]=2;
}

void createsnake()/*initilize the snake*/
{
       head=(struct snake *)malloc(sizeof(struct snake));
       head->x=(int)BOUNDRY/2;
       head->y=(int)BOUNDRY/2;
       head->next=(struct snake *)malloc(sizeof(struct snake));
       head->next->x=head->x-1;
       head->next->y=head->y;/*creat a snake in the center of the matrix*/
       head->next->next=NULL;
}

void freesnake()/*to free the allocated memories*/
{
     struct snake *p_snake;
     for (p_snake=head;p_snake->next!=NULL;p_snake=p_snake->next)
     {
         free(head);
         head=p_snake;
     }
     free(p_snake);/*to free the last allocated memory*/
}
     
void key_listener(float sp)/*to listen the keybord,sp for the speed*/
{
     char key;
     struct snake *p_snake;
     if(kbhit()) key=getch();
     else return;/*no key is pressed*/
     if ((key>='A')&&(key<='Z')) key+=32;
     switch (key)
     {
            case 'p':
                 if(speed!=0) speed=0;
                 else speed=sp;
                 break;
            case 'w':
                 direction='w';
                 break;
            case 'a':
                 direction='a';
                 break;
            case 's':
                 direction='s';
                 break;
            case 'd':
                 direction='d';
                 break;
            case 'e':
                 freesnake();
                 system("cls");
                 printf("/n/nYour Record:/nYour snake's length: %d/nTime you remained: %d s/n",s_length,(int)(clock()/CLOCKS_PER_SEC));
                 puts("/n/nThanks for playing!");
                 system("pause");
                 exit(0);
            case 'c': /*for changing speed*/
                 printf("Please enter a new speed interval:(one move/per second)");
                 scanf("%f",&speed);
            default:;
     }
}

struct snake *snakemove()
{
       /*return the snake's head pointer if the snake is alive,or return NULL
       首先判断移动之后的格子是否是边界或者蛇自身,都不是在判断是否食物,
       也不是再移动*/
       struct snake *p_snake;
       int last_x,last_y,cur_x,cur_y;
       switch (direction)
       {
              case 'w':/*for moving upward*/
              if ((area[head->x][head->y-1]==3)||(area[head->x][head->y-1]==1)) return NULL;
              else if (area[head->x][head->y-1]==2)
                   {
                       p_snake=head;
                       head=(struct snake *)malloc(sizeof(struct snake));
                       head->x=p_snake->x;
                       head->y=p_snake->y-1;
                       head->next=p_snake;/*p_snake在之前head的位置*/
                       foodon=0;
                       s_length++;
                       return head;
                   }
                   else /*area[head->x][head->y-1]==0,just move to the next block*/
                   {
                        cur_x=head->x;
                        cur_y=head->y;
                        head->y-=1;
                        for (p_snake=head->next;p_snake->next!=NULL;p_snake=p_snake->next)
                        {
                              last_x=p_snake->x;
                              last_y=p_snake->y;
                              p_snake->x=cur_x;
                              p_snake->y=cur_y;
                              cur_x=last_x;
                              cur_y=last_y;                              
                        }/*only change the location of each node,not the chain*/
                        p_snake->x=cur_x;
                        p_snake->y=cur_y;
                        /*the last node's x/y*/
                        return head;
                   }
                   break;
              case 'a':/*for moving left*/
              if ((area[head->x-1][head->y]==3)||(area[head->x-1][head->y]==1)) return NULL;
              else if (area[head->x-1][head->y]==2)
                   {
                       p_snake=head;
                       head=(struct snake *)malloc(sizeof(struct snake));
                       head->x=p_snake->x-1;
                       head->y=p_snake->y;
                       head->next=p_snake;/*p_snake在之前head的位置*/
                       foodon=0;
                       s_length++;
                       return head;
                   }
                   else /*area[head->x-1][head->y]==0,just move to the next block*/
                   {
                        cur_x=head->x;
                        cur_y=head->y;
                        head->x-=1;
                        for (p_snake=head->next;p_snake->next!=NULL;p_snake=p_snake->next)
                        {
                              last_x=p_snake->x;
                              last_y=p_snake->y;
                              p_snake->x=cur_x;
                              p_snake->y=cur_y;
                              cur_x=last_x;
                              cur_y=last_y;                              
                        }/*only change the location of each node,not the chain*/
                        p_snake->x=cur_x;
                        p_snake->y=cur_y;
                        /*the last node's x/y*/
                        return head;
                   }
                   break;
              case 'd':/*for moving right*/
              if ((area[head->x+1][head->y]==3)||(area[head->x+1][head->y]==1)) return NULL;
              else if (area[head->x+1][head->y]==2)
                   {
                       p_snake=head;
                       head=(struct snake *)malloc(sizeof(struct snake));
                       head->x=p_snake->x+1;
                       head->y=p_snake->y;
                       head->next=p_snake;/*p_snake在之前head的位置*/
                       foodon=0;
                       s_length++;
                       return head;
                   }
                   else /*area[head->x+1][head->y]==0,just move to the next block*/
                   {
                        cur_x=head->x;
                        cur_y=head->y;
                        head->x+=1;
                        for (p_snake=head->next;p_snake->next!=NULL;p_snake=p_snake->next)
                        {
                              last_x=p_snake->x;
                              last_y=p_snake->y;
                              p_snake->x=cur_x;
                              p_snake->y=cur_y;
                              cur_x=last_x;
                              cur_y=last_y;                              
                        }/*only change the location of each node,not the chain*/
                        p_snake->x=cur_x;
                        p_snake->y=cur_y;
                        /*the last node's x/y*/
                        return head;
                   }
                   break;
              case 's':/*for moving downward*/
              if ((area[head->x][head->y+1]==3)||(area[head->x][head->y+1]==1)) return NULL;
              else if (area[head->x][head->y+1]==2)
                   {
                       p_snake=head;
                       head=(struct snake *)malloc(sizeof(struct snake));
                       head->x=p_snake->x;
                       head->y=p_snake->y+1;
                       head->next=p_snake;/*p_snake在之前head的位置*/
                       foodon=0;
                       s_length++;
                       return head;
                   }
                   else /*area[head->x][head->y+1]==0,just move to the next block*/
                   {
                        cur_x=head->x;
                        cur_y=head->y;
                        head->y+=1;
                        for (p_snake=head->next;p_snake->next!=NULL;p_snake=p_snake->next)
                        {
                              last_x=p_snake->x;
                              last_y=p_snake->y;
                              p_snake->x=cur_x;
                              p_snake->y=cur_y;
                              cur_x=last_x;
                              cur_y=last_y;                              
                        }/*only change the location of each node,not the chain*/
                        p_snake->x=cur_x;
                        p_snake->y=cur_y;
                        /*the last node's x/y*/
                        return head;
                   }
                   break;
       }/*switch strcuture ended*/
}

void gotoxy(int x,int y) /*gotoxy的替代函数*/
{ 
     COORD c; 
     c.X=x-1; 
     c.Y=y-1; 
     SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c); 
}

void refreshscreen()
{
     gotoxy(1,1);
     int i,j;
     printf("/t/tYour level: %d/n/n",level);
     for (j=0;j<BOUNDRY;j++)
     {
         printf("/t/t");
         for (i=0;i<BOUNDRY;i++)
         {
             switch (area[i][j])
             {
                    case 0: /*normal block*/
                         printf("  ");
                         break;
                    case 1: /*snake body*/
                         printf("◎");
                         break;
                    case 2: /*food*/
                         printf("◆");
                         break;
                    case 3: /*Boundry*/
                         printf("☆");
                         break;
                    default:
                            ;
             }/*switch ended*/
         }
         putchar('/n');
     }
}

int main()
{
      struct snake *p; 
      srand((unsigned)time(NULL));/*initilize rand() seed*/
      float speedhold=0.0;/*initilize speedholder*/
      createsnake();
      makemap();
      locatesnake();
      locatefood();
      clock_t t1,t2;
      t1=t2=clock();/*set 2 time spots*/
      /*-------Game Helper-------*/
      printf("/n/n/t/tGame SNAKE/n/nWelcome to my first game:SNAKE!/n");
      printf("/nHow to play:/n    Your little snake has only 2-length long body, there will be a food in the boundry.Try to move your snake reach it.");
      printf("When your snake eats a block of food,he will grow longer.Try your best to make him the longest!/n");
      printf("/nGame Tips:/n1.To change the direction of your snake, use:/n/tw-upward/n/ta-left/n/td-right/n/ts-downward/n");
      printf("/n2.Press p for PAUSE at any time you want to pause the game./n");
      printf("/n3.Press e for EXIT at any time you want to exit the game./nYou'll get your grade before you exit./n");
      printf("/n4.Every more 10-length long body will level up./nThe speed will be faster at the same time./n");
      printf("/nAttention:If your direction towards snake's body.YOU DEAD./n/tThe same thing happened when the snake knocks against the wall./n");
      printf("/n/t/tThat's all. Just Have Fun!/n");
      printf("/t/t/tThis game is written by Shadow./n");
      system("pause");
      system("cls");
      /*-------Start The Game-----*/
      refreshscreen();
      while (1)
      {
            if ((float)(t2-t1)/CLOCKS_PER_SEC>=speed)
            {
                speedhold=speed;
                key_listener(speed);
                if (speed==0) /*to pause the game*/
                {
                    puts("The game is paused.");
                    while (speed!=speedhold)
                    {
                          key_listener(speedhold);
                    }
                }
                else
                {
                    p=snakemove();
                    if (p==NULL)
                    {
                        freesnake();
                        system("cls");
                        printf("/n/nYour Record:/nYour snake's length: %d/nTime you remained: %d s/n",s_length,(int)(clock()/CLOCKS_PER_SEC));
                        puts("/n/nThanks for playing!");
                        system("pause");
                        exit(0);
                    }
                    else
                    {
                        level=(int)(s_length/10+1);
                        if (speed>=0.1)speed=0.5-(float)s_length/100;
                        makemap();
                        if (foodon==0) locatefood();
                        locatesnake();
                        area[food.x][food.y]=2;
                    }
                }
                refreshscreen();
                printf("Your snake's length: %d/tTime you remained: %d s/n",s_length,(int)(clock()/CLOCKS_PER_SEC));
                t1=clock();
            }
            else t2=clock();
      }
      return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值