CSDN博客

img mrh123

贪吃蛇源程序

发表于2002/7/29 9:00:00  1637人阅读

本程序为贪吃蛇游戏,想必大家都玩过这个游戏,程序源代码用TC2.0编译通过,需要图形驱动文件的支持,在TC2.0的集成环境中有.

本程序利用数据结构中的链表,来将蛇身连接,同时当蛇吃到一定数目的东西时会自动升级,及移动速度会加快,程序会时刻将一些信息显示在屏幕上,包括所得分数,要吃多少东西才能升级,并且游戏者可以自己手动选择游戏级别,级别越高,蛇的移动速度越快.
另外,此游戏可能与CPU的速度有关系.

源代码如下:
**********************************************************************************
/*******************************COMMENTS**********************************/
/* snake_game.c            

    */
/* it is a game for entermainment.         

  */
/* in the begin,there is only a snake head,and it will have to eat food  */
/* to become stronger,and it eat a piece of food each time,it will       */
/* lengthen it's body,with the number of food the snake eats going up,it */
/* will become long more and more,and the score will goes up also.    */
/* there is always useful information during the game process.    */
/* if the path by which the snake goes to eat food is the shortest,the   */
/* score will add up a double.          

  */
/*             

      */
/* enjoy yourself,and any problem,contact <blldw@etang.com>              */
/*************************************************************************/

/* all head file that will be used */
#include<stdio.h>
#include<time.h>
#include<graphics.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>

/* useful MACRO */
#define FOOD_SIZE  8
#define SCALE   8
#define UP_KEY   0x4800
#define DOWN_KEY  0x5000
#define LEFT_KEY  0x4b00
#define RIGHT_KEY  0x4d00
#define MOVE_UP   1
#define MOVE_LEFT  2
#define MOVE_DOWN  3
#define MOVE_RIGHT  4
#define INVALID_DIRECTION 0
#define QUIT_KEYC  0x1051
#define QUIT_KEY  0x1071
#define SELECT_KEYC  0x1f53
#define SELECT_KEY      0x1f73
#define PAUSE_KEYC      0x1950
#define PAUSE_KEY       0x1970
#define DEFAULT_LEVEL  1
#define HELP_COLOR  WHITE
#define WELCOME_COLOR WHITE
#define DEFAULT_COLOR GREEN
/* define the macro as follows to improve the game in future */
#define FOOD_COLOR  YELLOW
#define SNAKE_HEAD_COLOR RED
#define DEFAULT_SNAKE_COLOR YELLOW

#define EXIT_COLOR   WHITE
#define SCORE_COLOR   YELLOW

/* sturcture for snake body mainly ,and food also */
typedef struct food_infor *FOOD_INFOR_PTR;
typedef struct food_infor{
  int posx;   /* position for each piece of snake body */
  int posy;
  int next_move;      /* next move direction */
  int pre_move;       /* previous move direction,seems unuseful */
  int beEaten;        /* xidentifier for snake body or food */
  FOOD_INFOR_PTR next; /* pointer to next piece of snake body */
  FOOD_INFOR_PTR pre;  /* pointer to previous piece of snake body */
}FOOD_INFOR;

/* structure for snake head */
typedef struct _snake_head{
  int posx;
  int posy;
  int next_move;
  int pre_move;
  int eatenC;           /* number of food that have been eaten */
  int hop;              /* number of steps to eat food */
  FOOD_INFOR_PTR next;  /* pointer to the first piece of eaten food */
}SNAKE_HEAD;

/* the left-up corner and right-down corner */
typedef struct point{
  int x;
  int y;
}POINT;

/* standards for game speed           

  */
/* before level 5,the time interval is level_b[level - 1] / 10,and after */
/* level 5,the time interval is 1.00 / level_b[level - 1]                */
float level_b[9] = {10.0,8.0,6.0,3.0,1.0,20.0,40.0,160.0,640.0};

/* available varary */
SNAKE_HEAD snake_head;
FOOD_INFOR *current;    /* always point to food */
POINT  border_LT,border_RB;
int   driver,mode;        /* for graphics driver */
int   maxx,maxy;          /* max length and width of screen,in pixel */
int   eaten;    /* identifier if the food is eaten */
int   score = 0;          /* total score */
int   level = DEFAULT_LEVEL; /* level or speed */
float  interval;              /* based on speed */
int   snake_color = DEFAULT_SNAKE_COLOR; /* snake body color */
int   hopcount = 0;        /* the shortest number of steps for snake */
         /* to eat food */


/* all sub function */
void init_graphics();
void generate_first_step();
int  judge_death();
int  willeatfood();
void generate_food();
void addonefood();
void redrawsnake();
void show_all();
void sort_all();
void change_direction();
void help();
void show_score(int);
void change_level();
void show_level();
void release(SNAKE_HEAD);
int  can_promote();
void win();
void show_infor_to_level();
void show_eaten();
void calculate_hop();

/* main function or entry */
void main()
{
 char  str[50] = "YOU LOSE!!!"; /* fail information */
 clock_t start;
 int  querykey;
 int  tempx,tempy;

/* if fail and want to resume game,go here */
retry:
 init_graphics();
 show_all();    /* show wall */
 generate_first_step();      /* generate food and snake head */
 show_score(score);          /* show score to player */
 eaten = 0;

 /* begin to play game */
 while(1)
 {
  if(judge_death() == 1) /* die */
   break;

  if(willeatfood() == 1)
  {
   eaten = 1;
   addonefood();

   snake_head.hop ++;

   if(snake_head.hop == hopcount)
    score += level * 2;
   else
    score += level;

   can_promote();

   show_score(score);

  }

  sort_all();

  redrawsnake();

  snake_head.hop ++;

  show_infor_to_level();

  show_eaten();

  show_all();

  change_direction();

  if(eaten == 1)
  {
   generate_food();

   calculate_hop();
   snake_head.hop = 0;

   eaten = 0;
  }

  if(level <= 5)
   interval = level_b[level - 1] / 10.0;
  else
   interval =  1.00 / level_b[level - 1];
  start = clock();
  while((clock() - start) / CLK_TCK < interval)
  {
   querykey = bioskey(1);
   if(querykey != 0)
   {
    switch(bioskey(0))
    {
     case UP_KEY:
      snake_head.next_move = MOVE_UP;
      break;
     case LEFT_KEY:
      snake_head.next_move = MOVE_LEFT;
      break;
     case DOWN_KEY:
      snake_head.next_move = MOVE_DOWN;
      break;
     case RIGHT_KEY:
      snake_head.next_move = MOVE_RIGHT;
      break;
     case SELECT_KEYC:
     case SELECT_KEY:
      change_level();
      score = 0;
      show_score(score);
      show_level();
      break;
     case PAUSE_KEYC:
     case PAUSE_KEY:
      while(!bioskey(1));
      break;
     case QUIT_KEYC:
     case QUIT_KEY:
      goto exit_game;

     default:
      break;
    }
   }
  }
 }

 settextstyle(DEFAULT_FONT,0,2);
 setcolor(EXIT_COLOR);

 tempx = border_LT.x + (border_RB.x - border_LT.x - textwidth(str)) / 2;
 tempy = border_LT.y + (border_RB.y - border_LT.y) / 2;
 outtextxy(tempx,tempy,str);

 strcpy(str,"press <R/r> to retry,or ENTER key to exit");

 tempy += textheight(str) * 2;
 settextstyle(DEFAULT_FONT,0,1);
 tempx = border_LT.x + (border_RB.x - border_LT.x - textwidth(str)) / 2;
 outtextxy(tempx,tempy,str);

select:

 while(!bioskey(1));

 querykey = bioskey(0);

 if((querykey == 0x1372) || (querykey == 0x1352))
 {
  level = DEFAULT_LEVEL;
  score = 0;

  release(snake_head);

  closegraph();
  goto retry;

 }

 if(querykey != 0x1c0d)
  goto select;

 closegraph();
 return;

exit_game:
 release(snake_head);
 closegraph();

}

/* sub function show_eaten()       */
/* function: to show the total number piece of food */
/*     that have been eaten by snake any time */
void show_eaten()
{
 int tempx,tempy;
 int size;
 void *buf;
 char str[15];

 settextstyle(DEFAULT_FONT,0,1);
 setcolor(DEFAULT_COLOR);

 sprintf(str,"eaten:%d",snake_head.eatenC);

 tempx = 0;
 tempy = border_LT.y + textheight(str) * 6;

 size = imagesize(tempx,tempy,tempx + textwidth(str) + textwidth("A"),
      tempy + textheight(str));
 buf = malloc(size);
 getimage(tempx,tempy,tempx + textwidth(str) + textwidth("A"),
    tempy + textheight(str),buf);
 putimage(tempx,tempy,buf,XOR_PUT);
 outtextxy(tempx,tempy,str);

 free(buf);

}

/* sub function: show_infor_to_level      */
/* function:show information to player that how many pieces */
/*   of food have to been eaten to get to next level */
/*   ,and this is not related with score,but only    */
/*   eaten number of food        

*/
/*             

  */
/* level standard:let highlevel stand for the number of     */
/*                pieces of food that can be put int the    */
/*                vertical direction of play area,and  */
/*      before level 5,as long as the snake eat   */
/*      a quarter of highlevel,it will go to next */
/*      level,and between level 5 and 7,as long   */
/*      as the snake eat one thirds of highlevel, */
/*      it will go to next level,and between      */
/*      level 8 and 9,the snake will go to next   */
/*      level as long as it eat half of highlevel */
/* note: level is between 1 to 9.       */
void show_infor_to_level()
{
 int highlevel;
 int size;
 int tempx,tempy;
 int toeat;
 void *buf;
 char str[50];

 highlevel = (border_RB.y - border_LT.y) / SCALE;

 switch(level)
 {
  case 1:
  case 2:
  case 3:
  case 4:
   toeat = (highlevel / 4) * level - snake_head.eatenC;
   break;

  case 5:
  case 6:
  case 7:
   toeat = (highlevel + highlevel / 3 * (level - 4))  - snake_head.eatenC;
   break;

  case 8:
  case 9:
   toeat = (highlevel * 2 + highlevel / 2 * (level - 7)) -

snake_head.eatenC;
   break;

  default:
   break;
 }

 settextstyle(DEFAULT_FONT,0,1);
 setcolor(DEFAULT_COLOR);

 if(snake_head.next == NULL)
 {
  sprintf(str,"next level");

  tempx = 0;
  tempy = border_LT.y + textheight(str) * 2;

  outtextxy(tempx,tempy,str);
 }

 if(toeat < 0)
  toeat = 0;

 sprintf(str,"%d:%d",level + 1,toeat);
 tempx = 0;
 tempy = border_LT.y + textheight(str) * 4;
 size = imagesize(tempx,tempy,tempx + textwidth(str) + textwidth("A"),tempy +

textheight(str));
 buf = malloc(size);
 getimage(tempx,tempy,tempx + textwidth(str) + textwidth("A"),tempy +

textheight(str),buf);
 putimage(tempx,tempy,buf,XOR_PUT);
 outtextxy(tempx,tempy,str);
 free(buf);

}

/* sub function: win()          */
/* function:if the player pass level 9,this function     */
/*   will be called ,to show "YOU WIN information */
/*    and after a key is pressed,the game will go  */
/*   on,but all is back to begin,excepte the      */
/*   snake body length.       

*/
void win()
{
 char str[] = "YOU WIN";
 int tempx,tempy;

 settextstyle(DEFAULT_FONT,0,8);
 setcolor(WELCOME_COLOR);

 tempx = border_LT.x + (border_RB.x - border_LT.x - textwidth(str)) / 2;
 tempy = border_LT.y + (border_RB.y - border_LT.y - textheight(str)) / 2;

 outtextxy(tempx,tempy,str);

 while(!bioskey(1));

}

/* sub function: can_promote()        */
/* function:see if the snake can go to next level on basis  */
/*   of the snake length.       

*/
/*             

  */
/* note:standards of promote level is instructed above  */
int can_promote()
{
 /* compare SCORE with standard level score */

 int high_level;
 static int last_score = 0;

 high_level = (border_RB.y - border_LT.y) / SCALE;

 switch(level)
 {
  case 1:
  case 2:
  case 3:
  case 4:
   if(snake_head.eatenC == (high_level / 4 * level))
    level ++;
   last_score = score;
   break;

  case 5:
  case 6:
  case 7:
   if(snake_head.eatenC == (high_level + high_level / 3 * (level - 4)))
    level ++;
   last_score = score;
   break;

  case 8:
   if(snake_head.eatenC == (high_level * 2 + high_level / 2 ))
    level ++;
   last_score = score;
   break;

  case 9:
   if(snake_head.eatenC == (high_level * 3))
   {
    win();

    score = 0;
    last_score = 0;
    level = DEFAULT_LEVEL;

   }
   break;

  default:
   break;
 }


 show_level();
}

/* sub function: calulate_hop()        */
/* function: calculate the shortest path from snake head to */
/*           the food it will eaten.      */
void calculate_hop()
{
 hopcount = (snake_head.posx >= current->posx) ? ((snake_head.posx - current->posx) /

SCALE) :
    ((current->posx - snake_head.posx) / SCALE);
 hopcount += (snake_head.posy >= current->posy) ? ((snake_head.posy - current->posy) /

SCALE) :
    ((current->posy - snake_head.posy) / SCALE);


}

/* sub function: release()         

*/
/* function:free memory before exit game or restart   */
void release(SNAKE_HEAD snake_head)
{
 FOOD_INFOR_PTR traceon,last;

    traceon = snake_head.next;
 snake_head.eatenC = 0;
 snake_head.next = NULL;
 snake_head.hop = 0;

 while(traceon)
  if(traceon->next != NULL)
   traceon = traceon->next;
  else
   break;
 while(traceon)
 {
  last = traceon->pre;
  free(traceon);
  traceon = last;
 }

}

/* sub function: show_level()x        */
/* function:show level information to player anytime  */
void show_level()
{
 char str[20];
 int size;
 void *buf;

 settextstyle(DEFAULT_FONT,0,1);
 setcolor(DEFAULT_COLOR);

 sprintf(str,"Level:%d",level);
 size = imagesize(0,border_LT.y,textwidth(str),border_LT.y + textheight(str));
 buf = malloc(size);
 getimage(0,border_LT.y,textwidth(str),
    border_LT.y + textheight(str),buf);
 putimage(0,border_LT.y,buf,XOR_PUT);

 free(buf);

 outtextxy(0,border_LT.y,str);
}

/* sub function: change_level()        */
/* function:if the play choose "select level <S/S>" item,   */
/*     this function will be called     */
void change_level()
{
 int c;
 int size;
 void *buf;
 int tempx,tempy;
 char str[] = "new level (1--9):";

 settextstyle(DEFAULT_FONT,0,1);
 setcolor(DEFAULT_COLOR);

 tempx = 0;
 tempy = border_LT.y - textheight("A") * 3 / 2;
 outtextxy(tempx,tempy,str);
goon:
 while(!bioskey(1));
 c = bioskey(0);
 if((c == 0x1051) || (c == 0x1071))
  goto exit;
 if(isdigit(c&0x00ff))
  level = (c&0x00ff) - 48;
 else
  goto goon;
exit:
 size = imagesize(tempx,tempy,tempx + textwidth(str),tempy + textheight(str));
 buf = malloc(size);
 getimage(tempx,tempy,tempx + textwidth(str),tempy + textheight(str),buf);
 putimage(tempx,tempy,buf,XOR_PUT);
 free(buf);

}

/* sub function: show_score()        */
/* function:show score information to player anytime  */
void show_score(int count)
{
 int th;
 int size;
 void *buf;
 char str[20];

 settextstyle(DEFAULT_FONT,0,2);
 setcolor(SCORE_COLOR);

 sprintf(str,"Score: %d",count);
 th = textheight("hello");

 if((count == 0) && (snake_head.next == NULL))
 {
  outtextxy(border_LT.x + (border_RB.x - border_LT.x) / 4,
      border_LT.y - 2 * th,str);
 }
 else
 {
  size = imagesize(border_LT.x + (border_RB.x - border_LT.x) / 4,
       border_LT.y - 2 * th,
       border_LT.x + (border_RB.x - border_LT.x) / 4 +

textwidth(str) + textwidth("100"),
       border_LT.y - 2 * th + th);
  buf = malloc(size);
  getimage(border_LT.x + (border_RB.x - border_LT.x) / 4,border_LT.y - 2 * th,
     border_LT.x + (border_RB.x - border_LT.x) / 4 + textwidth(str) +

textwidth("100"),
     border_LT.y - 2 * th + th,buf);
  putimage(border_LT.x + (border_RB.x - border_LT.x) / 4,
     border_LT.y - 2 * th,buf,XOR_PUT);
  outtextxy(border_LT.x + (border_RB.x - border_LT.x) / 4,
      border_LT.y - 2 * th,str);
  free(buf);
 }

}

/* sub function: help()          

*/
/* function: show help information at the beginning of game */
/*    and let player know how to play the game  */
void help()
{
 char str[100];
 int  th;

 settextstyle(DEFAULT_FONT,0,1);

 setcolor(HELP_COLOR);

 th = textheight("hello");

 sprintf(str,"move left : %c",27);
 outtextxy(border_LT.x,border_RB.y,str);

 sprintf(str,"move up   : %c",24);
 outtextxy(border_LT.x + (border_RB.x - border_LT.x) / 2,
     border_RB.y,str);

 sprintf(str,"move down : %c",25);
 outtextxy(border_LT.x,border_RB.y + th + 2,str);

 sprintf(str,"move right: %c",26);
 outtextxy(border_LT.x + (border_RB.x - border_LT.x) / 2,
     border_RB.y + th + 2,str);

 outtextxy(border_LT.x,border_RB.y + th * 2 + 4,"quit <Q/q>");
 outtextxy(border_LT.x + textwidth("quit <Q/q>") * 3 / 2,border_RB.y + th * 2 + 4,
     "pause <P/p>");
 outtextxy(border_LT.x + (border_RB.x - border_LT.x) / 2,
     border_RB.y + th * 2 + 4,"select level <S/s>");

 

}

/* sub function: show_all()         

*/
/* function:redraw the play area,means show wall   */
void show_all()
{

 int i,j;

 setcolor(DEFAULT_COLOR);
 /*
 for(i = border_LT.x; i <= border_RB.x; i += SCALE)
  for(j = border_LT.y; j <= border_RB.y; j += SCALE)
   rectangle(i,j,i + SCALE, j + SCALE);
 */

 rectangle(border_LT.x,border_LT.y,border_RB.x,border_RB.y);
}

/* sub function: generate_food()        

*/
/* function:after the food is eaten by snake,the function will  */
/*    be called to generate another food,and it will      */
/*   ensure that the generated food shouldn't appeare    */
/*    in the snake body.        

 */
void generate_food()
{
 FOOD_INFOR_PTR traceon;
 int tempx,tempy;

generate:
    current->posx = random(border_RB.x - SCALE / 2);
 while((current->posx <= border_LT.x) || ((current->posx - border_LT.x) % SCALE == 0) ||
   ((current->posx - border_LT.x) % SCALE % (SCALE / 2) != 0))
   current->posx ++;

 current->posy = random(border_RB.y - SCALE / 2);
 while((current->posy <= border_LT.y) || ((current->posy - border_LT.y) % SCALE == 0) ||
   ((current->posy - border_LT.y) % SCALE % (SCALE / 2) != 0))
   current->posy ++;

 traceon = snake_head.next;
 while(traceon)
 {
  if((traceon->posx == current->posx) && (traceon->posy == current->posy))
   goto generate;
  traceon = traceon->next;
 }


 if(current->posx - border_LT.x == SCALE / 2)
  current->posx += SCALE;
 if(border_RB.x - current->posx == SCALE / 2)
  current->posx -= SCALE;
 if(current->posy - border_LT.y == SCALE / 2)
  current->posy += SCALE;
 if(border_RB.y - current->posy == SCALE / 2)
  current->posy -= SCALE;

 setcolor(DEFAULT_COLOR);

 rectangle(current->posx - SCALE / 2,current->posy - SCALE / 2,
     current->posx + SCALE / 2,current->posy + SCALE / 2);
 setfillstyle(SOLID_FILL,YELLOW);
 floodfill(current->posx,current->posy,DEFAULT_COLOR);

}

/* sub function: init_graphics()        

*/
/* function:initialize the game interface      */
void init_graphics()
{
 driver = DETECT;
 mode = 0;

 initgraph(&driver,&mode,"*.bgi");
 maxx = getmaxx();
 maxy = getmaxy();

 border_LT.x = maxx / SCALE;
 border_LT.y = maxy / SCALE;

 border_RB.x = maxx * (SCALE - 1) / SCALE;
 border_RB.y = maxy * (SCALE - 1) / SCALE;

 while((border_RB.x - border_LT.x) % FOOD_SIZE)
  (border_RB.x) ++;
 while((border_RB.y - border_LT.y) % FOOD_SIZE)
  (border_RB.y) ++;

 while((border_RB.y - border_LT.y) % ( 12 * SCALE))
  border_RB.y += SCALE;

 setcolor(DEFAULT_COLOR);

 rectangle(border_LT.x,border_LT.y,border_RB.x,border_RB.y);

 help();

 show_level();

}

/* sub function: generateX_first_step()       */
/* function:generate snake head and first food to prepare for   */
/*   game to start,and this function will also initialize*/
/*      the move direction of snake head,and show welcome */
/*   information to player.        

*/
void generate_first_step()
{
 char str[] = "welcome to snake game,press ENTER key to start";
 int size;
 int tempx,tempy;
 void *buf;
 randomize();

 /* generate snake head */
 snake_head.posx = random(border_RB.x - SCALE / 2);
 while((snake_head.posx <= border_LT.x) || ((snake_head.posx - border_LT.x) % SCALE == 0)

||
   ((snake_head.posx - border_LT.x) % SCALE % (SCALE / 2) != 0))
   snake_head.posx ++;

 snake_head.posy = random(border_RB.y - SCALE / 2);
 while((snake_head.posy <= border_LT.y) || ((snake_head.posy - border_LT.y) % SCALE == 0)

||
   ((snake_head.posy - border_LT.y) % SCALE % (SCALE / 2) != 0))
   snake_head.posy ++;

 setcolor(DEFAULT_COLOR);

 rectangle(snake_head.posx - SCALE / 2,snake_head.posy - SCALE / 2,
     snake_head.posx + SCALE / 2,snake_head.posy + SCALE / 2);
 setfillstyle(SOLID_FILL,SNAKE_HEAD_COLOR);
 floodfill(snake_head.posx,snake_head.posy,DEFAULT_COLOR);

 /* generate first food */

 current = (FOOD_INFOR_PTR)malloc(sizeof(FOOD_INFOR));

goon_generate:

 current->posx = random(border_RB.x - SCALE / 2);
 while((current->posx <= border_LT.x) || ((current->posx - border_LT.x) % SCALE == 0) ||
   ((current->posx - border_LT.x) % SCALE % (SCALE / 2) != 0))
   current->posx ++;

 current->posy = random(border_RB.y - SCALE / 2);
 while((current->posy <= border_LT.y) || ((current->posy - border_LT.y) % SCALE == 0) ||
   ((current->posy - border_LT.y) % SCALE % (SCALE / 2) != 0))
   current->posy ++;

 if((current->posx == snake_head.posx) && (current->posy == snake_head.posy))
  goto goon_generate;

 rectangle(current->posx - SCALE / 2,current->posy - SCALE / 2,
     current->posx + SCALE / 2,current->posy + SCALE / 2);
 setfillstyle(SOLID_FILL,FOOD_COLOR);
 floodfill(current->posx,current->posy,DEFAULT_COLOR);

 calculate_hop();

 snake_head.next = NULL;
 snake_head.eatenC = 0;
 snake_head.hop = 0;

 current->next = NULL;
 current->pre = NULL;
 current->beEaten = 0;
 current->next_move = INVALID_DIRECTION;
 current->pre_move = INVALID_DIRECTION;

 if(snake_head.posx == current->posx)
 {
  if(snake_head.posy > current->posy)
   snake_head.next_move = MOVE_UP;
  else
   snake_head.next_move = MOVE_DOWN;
 }
 else
 {
  if(snake_head.posx < current->posx)
   snake_head.next_move = MOVE_RIGHT;
  else
   snake_head.next_move = MOVE_LEFT;
 }

 snake_head.pre_move = snake_head.next_move;

 settextstyle(DEFAULT_FONT,0,1);
 setcolor(WELCOME_COLOR);

 tempx = border_LT.x + (border_RB.x - border_LT.x - textwidth(str)) / 2;
 tempy = border_LT.y - textheight("A") * 6 / 2;

 outtextxy(tempx,tempy,str);

 size = imagesize(tempx,tempy,tempx + textwidth(str),
      tempy + textheight(str));
 buf = malloc(size);
 getimage(tempx,tempy,tempx + textwidth(str),
    tempy + textheight(str),buf);
 while(bioskey(0) != 0x1c0d);

 putimage(tempx,tempy,buf,XOR_PUT);
 free(buf);

}

/* sub function: judge_death()         

*/
/* function:judge if the snake will die because of incorrect    */
/*      move,there are two things that will result    */
/*      the snake to death:first,it run into the wall */
/*      ,and second,it run into its body.    

*/
int judge_death()
{
 /* return 1 means will die,and return 0 means will survive */

 int tempx,tempy;

 switch(snake_head.next_move)
 {
  case MOVE_UP:
   tempx = snake_head.posx;
   tempy = snake_head.posy - SCALE;
   break;
  case MOVE_LEFT:
   tempx = snake_head.posx - SCALE;
   tempy = snake_head.posy;
   break;
  case MOVE_DOWN:
   tempx = snake_head.posx;
   tempy = snake_head.posy + SCALE;
   break;
  case MOVE_RIGHT:
   tempx = snake_head.posx + SCALE;
   tempy = snake_head.posy;
   break;
  default:
   break;
 }

 if((tempx < border_LT.x) || (tempx > border_RB.x) ||
    (tempy < border_LT.y) || (tempy > border_RB.y))
    return 1;

 if(getpixel(tempx,tempy) == snake_color)
 {
  FOOD_INFOR_PTR traceon;
  traceon = snake_head.next;
  while(traceon != NULL)
  {
   if((traceon->posx == tempx) && (traceon->posy == tempy))
    return 1;

   traceon = traceon->next;
  }
 }

 return 0; /* survive */

}

/* sub function: willeatfood()        */
/* function:judge if the sanke can eat food.the method like */
/*    this:provided that the snake move a step based  */
/*   on its next move direction,and if this place    */
/*   have food,then the snake can eat food.   */
int willeatfood()
{
 /* 1 means will eat food ,and 0 means won't eat food */

 int tempx,tempy;

 switch(snake_head.next_move)
 {
  case MOVE_UP:
   tempx = snake_head.posx;
   tempy = snake_head.posy - SCALE;
   break;
  case MOVE_LEFT:
   tempx = snake_head.posx - SCALE;
   tempy = snake_head.posy;
   break;
  case MOVE_DOWN:
   tempx = snake_head.posx;
   tempy = snake_head.posy + SCALE;
   break;
  case MOVE_RIGHT:
   tempx = snake_head.posx + SCALE;
   tempy = snake_head.posy;
   break;
  default:
   break;
 }

 if(getpixel(tempx,tempy) == FOOD_COLOR)
  return 1;

 return 0;

}

/* sub function: addonefood()       */
/* function: this function will lengthen the snake body */
/*    this function is important because it will */
/*    not only locate memory for new snake body, */
/*    but also handle the relationship of pointer*/
/*    between the new snake body and its previous*/
/*    snake body.        

*/
void addonefood()
{
 FOOD_INFOR_PTR traceon;

 snake_head.eatenC ++ ;
 traceon = snake_head.next;

 if(snake_head.next == NULL)  /* haven't eaten any food */
 {
  traceon = (FOOD_INFOR_PTR)malloc(sizeof(FOOD_INFOR));

  switch(snake_head.next_move)
  {
   case MOVE_UP:
    traceon->posx = snake_head.posx;
    traceon->posy = snake_head.posy + SCALE;
    break;
   case MOVE_LEFT:
    traceon->posx = snake_head.posx + SCALE;
    traceon->posy = snake_head.posy;
    break;
   case MOVE_DOWN:
    traceon->posx = snake_head.posx;
    traceon->posy = snake_head.posy - SCALE;
    break;
   case MOVE_RIGHT:
    traceon->posx = snake_head.posx - SCALE;
    traceon->posy = snake_head.posy;
    break;
   default:
    break;
  }

  traceon->next_move = snake_head.next_move;
  traceon->pre_move = snake_head.next_move;
  traceon->next = NULL;
  traceon->pre = NULL;
  traceon->beEaten = 1;

  snake_head.next = traceon;
 }
 else
 {
  while(traceon)
  {
   if(traceon->next != NULL)
    traceon = traceon->next;
   else
    break;
  }

  traceon->next = (FOOD_INFOR_PTR)malloc(sizeof(FOOD_INFOR));

  traceon->next->next = NULL;
  traceon->next->pre = traceon;
  traceon = traceon->next;

  switch(traceon->pre->next_move)
  {
   case MOVE_UP:
    traceon->posx = traceon->pre->posx;
    traceon->posy = traceon->pre->posy + SCALE;
    break;
   case MOVE_LEFT:
    traceon->posx = traceon->pre->posx + SCALE;
    traceon->posy = traceon->pre->posy;
    break;
   case MOVE_DOWN:
    traceon->posx = traceon->pre->posx;
    traceon->posy = traceon->pre->posy - SCALE;
    break;
   case MOVE_RIGHT:
    traceon->posx = traceon->pre->posx - SCALE;
    traceon->posy = traceon->pre->posy;
    break;
   default:
    break;
  }

  traceon->next_move = traceon->pre->next_move;
  traceon->pre_move = traceon->pre->next_move;
  traceon->beEaten = 1;
 }

}

/* sub function: sort_all()          

 */
/* function:this function will calculate the next position of snake */
/*      and it is assume the snake has move to next position,but*/
/*   haven't appeared yet.        

 */
void sort_all()
{
 /* sort all food,include snake head,and virtual place */

 FOOD_INFOR_PTR traceon;
 void *buf;
 int  size;

 size = imagesize(snake_head.posx - SCALE / 2,snake_head.posy - SCALE / 2,
      snake_head.posx + SCALE / 2,snake_head.posy + SCALE /

2);
 buf = malloc(size);
 getimage(snake_head.posx - SCALE / 2,snake_head.posy - SCALE / 2,
    snake_head.posx + SCALE / 2,snake_head.posy + SCALE / 2,buf);
 putimage(snake_head.posx - SCALE / 2,snake_head.posy - SCALE / 2,
    buf,XOR_PUT);

 switch(snake_head.next_move)
 {
  case MOVE_UP:
   snake_head.posy -= SCALE;
   break;
  case MOVE_LEFT:
   snake_head.posx -= SCALE;
   break;
  case MOVE_DOWN:
   snake_head.posy += SCALE;
   break;
  case MOVE_RIGHT:
   snake_head.posx += SCALE;
   break;
  default:
   break;
 }

 traceon = snake_head.next;
 while(traceon)
 {
  getimage(traceon->posx - SCALE / 2,traceon->posy - SCALE / 2,
     traceon->posx + SCALE / 2,traceon->posy + SCALE / 2,buf);
  putimage(traceon->posx - SCALE / 2,traceon->posy - SCALE / 2,
     buf,XOR_PUT);

  switch(traceon->next_move)
  {
   case MOVE_UP:
    traceon->posy -= SCALE;
    break;
   case MOVE_LEFT:
    traceon->posx -= SCALE;
    break;
   case MOVE_DOWN:
    traceon->posy += SCALE;
    break;
   case MOVE_RIGHT:
    traceon->posx += SCALE;
    break;
   default:
    break;
  }
  traceon = traceon->next;
 }

 free(buf);

}

/* sub function: redrawsnake()         

*/
/* function:the function will redraw the snake based on function*/
/*    sort_all().        

  */
void redrawsnake()
{
 FOOD_INFOR_PTR traceon;

 setcolor(DEFAULT_COLOR);
 /* redraw snake head */
 setfillstyle(SOLID_FILL,SNAKE_HEAD_COLOR);
 rectangle(snake_head.posx - SCALE / 2,snake_head.posy - SCALE / 2,
     snake_head.posx + SCALE / 2,snake_head.posy + SCALE / 2);
 floodfill(snake_head.posx,snake_head.posy,DEFAULT_COLOR);

 /* redraw all eaten foodd */
 setfillstyle(SOLID_FILL,snake_color);
 traceon = snake_head.next;

 while(traceon)
 {
  rectangle(traceon->posx - SCALE / 2,traceon->posy - SCALE / 2,
      traceon->posx + SCALE / 2,traceon->posy + SCALE / 2);
  floodfill(traceon->posx,traceon->posy,DEFAULT_COLOR);
  traceon = traceon->next;
 }

}

/* sub function: change_direction()       */
/* function:this function will assign the next move direction*/
/*   of snake,it calculate on basis of the information*/
/*    of snake body structure.      

*/
void change_direction()
{
 FOOD_INFOR_PTR traceon,temp1,temp2;

 traceon = snake_head.next;

 /*if(traceon == NULL)*/ /* only have snake head */
 snake_head.pre_move = snake_head.next_move;

 if(traceon != NULL)
 {
  while(traceon)
  {
   if(traceon->next != NULL)
    traceon = traceon->next;
   else
    break;
  }
  while(traceon->pre != NULL)
  {
   traceon->pre_move = traceon->next_move;
   traceon->next_move = traceon->pre->next_move; /***/
   traceon = traceon->pre;
  }
  traceon->pre_move = traceon->next_move;
  traceon->next_move = snake_head.pre_move;

 }


}

/* SOCRE CODE ENDED */
/* DATE: JUL 2th,01 */
*********************************************************************************************
完整的程序与源代码及相关文件可以在地址http://blldw.myetang.com/c/snake.zip下载

阅读全文
0 0

相关文章推荐

img
取 消
img