ITPub博客

首页 > 应用开发 > IT综合 > 贪吃蛇源程序 (转)

贪吃蛇源程序 (转)

原创 IT综合 作者:worldblog 时间:2007-12-12 14:04:36 0 删除 编辑
贪吃蛇源程序 (转)[@more@]

程序为贪吃蛇游戏,想必大家都玩过这个游戏,程序源代码用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 <Mailto:blldw@etang.com">blldw@etang.com>  */
/*************************************************************************/

/* all head file that will be used */
#include
#include
#include
#include
#include
#include

/* 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 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 " 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 ");
 outtextxy(border_LT.x + textwidth("quit ") * 3 / 2,border_RB.y + th * 2 + 4,
  "pause

");
 outtextxy(border_LT.x + (border_RB.x - border_LT.x) / 2,
  border_RB.y + th * 2 + 4,"select level ");

 

}

/* 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下载


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10752043/viewspace-992094/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论