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

来源:互联网 发布:加密软件破译 编辑:程序博客网 时间:2024/06/06 09:35

/*
贪吃蛇
规则:在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 21int 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;}