The source code of a greedy snake game I wrote in Turbo C 2.0 lately

本文介绍了一个基于C语言实现的贪吃蛇游戏源代码。该程序利用了多种C语言标准库,如stdio.h和conio.h等,并定义了用于游戏逻辑的数据结构,包括方向枚举和蛇段结构体。此外,还提供了初始化蛇、获取速度等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<bios.h>
#include<graphics.h>
#include<malloc.h>
#include<stdlib.h>
#define VK_UP 0x4800
#define VK_DOWN 0x5000
#define VK_LEFT 0x4b00
#define VK_RIGHT 0x4d00
#define VK_ESC 0x011b
#define VK_ENTER 0x1c0d
#define TIME_UNIT 100 /*this match's time unit(millisecond)*/
#define GAME_TIME 8000 /*every game's time(in TIME_UNIT)*/

enum Direction{UP,DOWN,LEFT,RIGHT};
struct SnakeSegment{
     int head_x,head_y;  /*the position of the left-up point */
     int block_num;      /*the number of blocks in this segment*/
     enum Direction dir; /*direction*/
     struct SnakeSegment* prev;
     struct SnakeSegment* next;
};
struct GreedySnake{
     int seg_num;   /*the number of snake's segments*/
     struct SnakeSegment* first;
     struct SnakeSegment* last;
     int width;     /*the snake's width*/
     int block_length;   /*a block's length*/
};
int get_velocity(int grade)
{
     int v;
    
     switch(grade){
     case 1:
          v=12;
          break;
     case 2:
          v=8;
          break;
     case 3:
          v=4;
          break;
     case 4:
          v=2;
          break;
     case 5:
          v=1;
          break;
     }
     return v;
}
void initialize_snake(struct GreedySnake* s)
{
     s->width=2;
     s->block_length=3;

     s->seg_num=1;
    
     s->first=s->last=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
     s->first->head_x=20;
     s->first->head_y=0;
     s->first->block_num=13;
     s->first->dir=DOWN;
     s->first->prev=s->first->next=NULL;
}
void show_current_status(struct GreedySnake* s)
{
     int hx,hy,tx,ty;
     struct SnakeSegment* f=s->first;/*begin from the fist segment*/
    
     cleardevice();
     /*show a segment everytime*/
     while(f != NULL){
          hx=f->head_x;
          hy=f->head_y;
          switch(f->dir){
          case UP:
          case DOWN:
               tx=hx+s->width;
               ty=hy+f->block_num * s->block_length;
               break;
          case LEFT:
          case RIGHT:
               tx=hx+f->block_num * s->block_length;
               ty=hy+s->width;
               break;
          }
          bar(hx,hy,tx,ty);
          f=f->next;/*show the next segment*/
     }
}
void update_status(struct GreedySnake* s,enum Direction d,int grow_block_num)
{
     struct SnakeSegment* f=s->first;
     struct SnakeSegment* l=s->last;
     struct SnakeSegment* add;
     int seg_num=s->seg_num;
     int first_segment_changed=1;/*when the quantity of a snake's segments is over or equal with 2,this variable is useful*/
     if(seg_num==1){
          /*only one segment*/
          switch(f->dir){
          case UP:
               switch(d){
               case UP:
                    f->head_y -= s->block_length;
                    break;
               case LEFT:
                    f->block_num--;
                   
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=LEFT;
                   
                    if(f->block_num<=0){
                         add->head_x=f->head_x + s->width - s->block_length;
                         add->head_y=f->head_y + s->block_length - s->width;
                         add->prev=add->next=NULL;
                        
                         free(f);
                         f=l=add;
                    }
                    else{
                         f->head_y += s->block_length;
                         add->head_x = f->head_x - s->block_length;       
                         add->head_y = f->head_y;
                        
                         f->prev=add;
                         add->next=f;
                         add->prev=NULL;
                         f=add;
                         seg_num++;
                    }
                    s->first=f;
                    s->last=l;
                    s->seg_num=seg_num;
                    break;
               case RIGHT:
                    f->block_num--;
                   
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=RIGHT;
                   
                    if(f->block_num<=0){
                         add->head_x=f->head_x;
                         add->head_y=f->head_y + s->block_length - s->width;
                         add->prev=add->next=NULL;

                         free(f);
                         f=l=add;
                    }
                    else{
                         f->head_y += s->block_length;
                         add->head_x=f->head_x + s->width;      
                         add->head_y=f->head_y;
                        
                         f->prev=add;
                         add->next=f;
                         add->prev=NULL;
                         f=add;
                         seg_num++;
                    }
                    s->first=f;
                    s->last=l;
                    s->seg_num=seg_num;
                    break;
               }
               break;
          case DOWN:
               switch(d){
               case DOWN:
                    f->head_y += s->block_length;
                    break;
               case LEFT:
                    f->block_num--;
                   
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=LEFT;

                    if(f->block_num<=0){
                         add->head_x=f->head_x + s->width - s->block_length;
                         add->head_y=f->head_y;
                        
                         add->prev=add->next=NULL;
                         free(f);
                         f=l=add;
                    }
                    else{
                         add->head_x=f->head_x - s->block_length;
                         add->head_y=f->head_y + (f->block_num * s->block_length) - s->width;

                         f->prev=add;
                         add->next=f;
                         add->prev=NULL;
                         f=add;
                         seg_num++;
                    }
                    s->first=f;
                    s->last=l;
                    s->seg_num=seg_num;
                    break;
               case RIGHT:
                    f->block_num--;
                   
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=RIGHT;
                   
                    if(f->block_num<=0){
                         add->head_x=f->head_x;
                         add->head_y=f->head_y;

                         add->prev=add->next=NULL;
                         free(f);
                         f=l=add;
                    }
                    else{
                         add->head_x=f->head_x + s->width;
                         add->head_y=f->head_y + (f->block_num * s->block_length) - s->width;;
              
                         f->prev=add;
                         add->next=f;
                         add->prev=NULL;
                         f=add;
                         seg_num++;
                    }
                    s->first=f;
                    s->last=l;
                    s->seg_num=seg_num;
                    break;
               }
               break;
          case LEFT:
               switch(d){
               case LEFT:
                    f->head_x -= s->block_length;
                    break;
               case UP:
                    f->block_num--;
                   
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=UP;
                   
                    if(f->block_num<=0){
                         add->head_x=f->head_x + s->block_length - s->width;
                         add->head_y=f->head_y + s->width - s->block_length;

                         add->prev=add->next=NULL;
                         free(f);
                         f=l=add;
                    }
                    else{
                         f->head_x += s->block_length;
                         add->head_x=f->head_x;
                         add->head_y=f->head_y - s->block_length;
              
                         f->prev=add;
                         add->next=f;
                         add->prev=NULL;
                         f=add;
                         seg_num++;
                    }
                    s->first=f;
                    s->last=l;
                    s->seg_num=seg_num;
                    break;
               case DOWN:
                    f->block_num--;
                   
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=DOWN;
                   
                    if(f->block_num<=0){
                         add->head_x=f->head_x + s->block_length - s->width;
                         add->head_y=f->head_y;

                         add->prev=add->next=NULL;
                         free(f);
                         f=l=add;
                    }
                    else{
                         f->head_x += s->block_length;
                         add->head_x=f->head_x;
                         add->head_y=f->head_y + s->width;
              
                         f->prev=add;
                         add->next=f;
                         add->prev=NULL;
                         f=add;
                         seg_num++;
                    }
                    s->first=f;
                    s->last=l;
                    s->seg_num=seg_num;
                    break;
               }
               break;
          case RIGHT:
               switch(d){
               case RIGHT:
                    f->head_x += s->block_length;
                    break;
               case UP:
                    f->block_num--;
                   
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=UP;
                   
                    if(f->block_num<=0){
                         add->head_x=f->head_x;
                         add->head_y=f->head_y + s->width - s->block_length;

                         add->prev=add->next=NULL;
                         free(f);
                         f=l=add;
                    }
                    else{
                         add->head_x=f->head_x + (f->block_num * s->block_length) - s->width;
                         add->head_y=f->head_y - s->block_length;
              
                         f->prev=add;
                         add->next=f;
                         add->prev=NULL;
                         f=add;
                         seg_num++;
                    }
                    s->first=f;
                    s->last=l;
                    s->seg_num=seg_num;
                    break;
               case DOWN:
                    f->block_num--;
                   
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=DOWN;
                   
                    if(f->block_num<=0){
                         add->head_x=f->head_x;
                         add->head_y=f->head_y;

                         add->prev=add->next=NULL;
                         free(f);
                         f=l=add;
                    }
                    else{
                         add->head_x=f->head_x + (f->block_num * s->block_length) - s->width;
                         add->head_y=f->head_y + s->width;
              
                         f->prev=add;
                         add->next=f;
                         add->prev=NULL;
                         f=add;
                         seg_num++;
                    }
                    s->first=f;
                    s->last=l;
                    s->seg_num=seg_num;
                    break;
               }
               break;
          }
     }
     else{
          /*deal with the first segment*/
          switch(f->dir){
          case UP:
               switch(d){
               case UP:
                    f->block_num++;
                    f->head_y -= s->block_length;
                    break;
               case DOWN:
                    first_segment_changed=0;
                    break;
               case LEFT:         
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=LEFT;
                    add->head_x = f->head_x - s->block_length;
                    add->head_y = f->head_y;

                    f->prev=add;
                    add->next=f;
                    add->prev=NULL;

                    s->first=add;
                    s->seg_num++;
                    break;
               case RIGHT:
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=RIGHT;
                    add->head_x = f->head_x + s->width;
                    add->head_y = f->head_y;

                    f->prev=add;
                    add->next=f;
                    add->prev=NULL;

                    s->first=add;
                    s->seg_num++;
                    break;
               }
               break;
          case DOWN:
               switch(d){
               case UP:
                    first_segment_changed=0;
                    break;
               case DOWN:
                    f->block_num++;
                    break;
               case LEFT:
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=LEFT;
                    add->head_x = f->head_x - s->block_length;
                    add->head_y = f->head_y + (f->block_num * s->block_length) - s->width;

                    f->prev=add;
                    add->next=f;
                    add->prev=NULL;

                    s->first=add;
                    s->seg_num++;
                    break;
               case RIGHT:
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=RIGHT;
                    add->head_x = f->head_x + s->width;
                    add->head_y = f->head_y + (f->block_num * s->block_length) - s->width;

                    f->prev=add;
                    add->next=f;
                    add->prev=NULL;

                    s->first=add;
                    s->seg_num++;
                    break;
               }
               break;
          case LEFT:
               switch(d){
               case LEFT:
                    f->block_num++;
                    f->head_x -= s->block_length;
                    break;
               case RIGHT:
                    first_segment_changed=0;
                    break;
               case UP:
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=UP;
                    add->head_x = f->head_x;
                    add->head_y = f->head_y - s->block_length;

                    f->prev=add;
                    add->next=f;
                    add->prev=NULL;

                    s->first=add;
                    s->seg_num++;
                    break;
               case DOWN:
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=DOWN;
                    add->head_x = f->head_x;
                    add->head_y = f->head_y + s->width;

                    f->prev=add;
                    add->next=f;
                    add->prev=NULL;

                    s->first=add;
                    s->seg_num++;
                    break;
               }
               break;
          case RIGHT:
               switch(d){
               case LEFT:
                    first_segment_changed=0;
                    break;
               case RIGHT:
                    f->block_num++;
                    break;
               case UP:
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=UP;
                    add->head_x = f->head_x + (f->block_num * s->block_length) - s->width;
                    add->head_y = f->head_y - s->block_length;

                    f->prev=add;
                    add->next=f;
                    add->prev=NULL;

                    s->first=add;
                    s->seg_num++;
                    break;
               case DOWN:
                    add=(struct SnakeSegment*)malloc(sizeof(struct SnakeSegment));
                    add->block_num=1;
                    add->dir=DOWN;
                    add->head_x = f->head_x + (f->block_num * s->block_length) - s->width;
                    add->head_y = f->head_y + s->width;

                    f->prev=add;
                    add->next=f;
                    add->prev=NULL;

                    s->first=add;
                    s->seg_num++;
                    break;
               }
               break;
          }
          /*deal with the last segment if the first segment has changed*/
          if(first_segment_changed==1){
               l->block_num--;
               if(l->block_num <= 0){
                    l->prev->next=NULL;
                    s->last=l->prev;
                    free(l);
                    s->seg_num--;
               }
               else{
                    if(l->dir==DOWN)
                         l->head_y += s->block_length;
                    else if(l->dir==RIGHT)
                         l->head_x += s->block_length;
               }
          }
     }
     /*execute the grow blocks*/
     if(grow_block_num>0){
          l=s->last;
          l->block_num += grow_block_num;
          if(l->dir==DOWN)
               l->head_y -= grow_block_num * s->block_length;
          else if(l->dir==RIGHT)
               l->head_x -= grow_block_num * s->block_length;
     }
}
int  out_range(struct GreedySnake*s)
{
     struct SnakeSegment* f=s->first;
     struct SnakeSegment* l=s->last;
     int seg_num=s->seg_num;
     int f_minx,f_miny,f_maxx,f_maxy;
     int l_minx,l_miny,l_maxx,l_maxy;
     /*judge if the first segment comes up against bordlines*/
     switch(f->dir){
     case UP:
          if(f->head_y < 0)
               return 1;
          break;
     case DOWN:
          if( ( f->head_y + (f->block_num * s->block_length) ) > 480)
               return 1;
          break;
     case LEFT:
          if(f->head_x < 0)
               return 1;
          break;
     case RIGHT:
          if( ( f->head_x + (f->block_num * s->block_length) ) > 640)
               return 1;
          break;
     }
     /*judge if the first segment comes up against other segments*/
     f_minx=f->head_x;
     f_miny=f->head_y;
     switch(f->dir){
     case UP:
     case DOWN:
          f_maxx=f->head_x + s->width;
          f_maxy=f->head_y + (f->block_num * s->block_length);
          break;
     case LEFT:
     case RIGHT:
          f_maxx=f->head_x + (f->block_num * s->block_length);
          f_maxy=f->head_y + s->width;
          break;
     }
     while(seg_num>=4){
          l_minx=l->head_x;
          l_miny=l->head_y;
          switch(l->dir){
          case UP:
          case DOWN:
               l_maxx=l->head_x + s->width;
               l_maxy=l->head_y + (l->block_num * s->block_length);
               break;
          case LEFT:
          case RIGHT:
               l_maxx=l->head_x + (l->block_num * s->block_length);
               l_maxy=l->head_y + s->width;
               break;
          }
          if( ( (f_minx>=l_minx && f_minx<=l_maxx) && (f_miny>=l_miny && f_miny<=l_maxy) ) || ( (f_maxx>=l_minx && f_maxx<=l_maxx) && (f_maxy>=l_miny && f_maxy<=l_maxy) ) )
               return 1;
          l=l->prev;
          seg_num--;
     }
     /*the first segment come up against nothing*/
     return 0;
}
void initialize_game()
{
     int gdriver,gmode;
    
     /*configure the monitor*/
     gdriver=VGA;
     gmode=VGAHI;
     registerbgidriver(EGAVGA_driver);

     /*change to the graph mode*/
     initgraph(&gdriver,&gmode,"");
    
     /*initialize the screen*/
     setbkcolor(WHITE);
     cleardevice();
     setfillstyle(1,RED);
}
int play_game(struct GreedySnake* s,int grade)
{

     int key;
     int velocity;/*the snake's moving velocity(in TIME_UNIT) in the current game*/
     int time_count;/*the time(in TIME_UNIT) which the current game has used*/
    
     int grow_interval;
     int grow_block_num;
     int no_grow_time;
     int need_grow;
    
     enum Direction update_dir;

     /*configure this game*/
     time_count=0;
     velocity=get_velocity(grade);
    
     grow_interval=100;
     grow_block_num=8;
     no_grow_time=0;
     need_grow=0;

     /*initialize the snake and show it*/
     initialize_snake(s);
     show_current_status(s);
    
     for(;;)
     {
          if(bioskey(1) != 0){/*user pressed a key*/
               key=bioskey(0);
               switch(key){
               case VK_UP:
                    update_dir=UP;
                    break;
               case VK_DOWN:
                    update_dir=DOWN;
                    break;
               case VK_LEFT:
                    update_dir=LEFT;
                    break;
               case VK_RIGHT:
                    update_dir=RIGHT;
                    break;
               case VK_ESC:
                    return 0;
               }
          }
          else
               /*follow the current direction to move*/
               update_dir=s->first->dir;
         
          /*update the snake's status*/
          if(need_grow==0)
               update_status(s,update_dir,0);
          else
               update_status(s,update_dir,grow_block_num);
         

          /*show the snake's current status*/
          show_current_status(s);

          /*judge if the snake is out of range*/
          if(out_range(s))
               return 1;
         
          delay(velocity * TIME_UNIT);
          time_count += velocity;

          /*judge if this game is time-expired*/
          if(time_count>=GAME_TIME)
               return 2;
         
         
          if(need_grow==1){
               need_grow=0;
               no_grow_time += velocity;
          }
          else{
               no_grow_time += velocity;
               if(no_grow_time >= grow_interval){
                    need_grow=1;
                    no_grow_time=0;
               }
          }

     }
}
void end_game(struct GreedySnake* s)
{
     struct SnakeSegment* temp;
     struct SnakeSegment* f=s->first;

     /*close the graph mode*/
     closegraph();

     /*set allocated memory free*/
     while(f != NULL){
          temp=f;
          f=f->next;
          free(temp);
     }
}
int main(){
     char ch;
     struct GreedySnake snake;
     int end_match;/*control the match's end*/
     int key;
     int grade;/*game difficulty*/
     int game_result;
         
     /*let the user select a game*/
     do{
          clrscr();
          gotoxy(30,12);
          cprintf("Start the game?(Y/N):");
          ch=getchar();
          ch=tolower(ch);
     }while(ch != 'y' && ch != 'n');
     if(ch =='n'){
          clrscr();
          return 0;
     }
     else{
          /*let the user decide the game's difficulty*/
          do{
               clrscr();
               gotoxy(30,12);
               cprintf("Select the grade(1-5):");
               ch=getchar();
          }while(ch!='1' && ch!='2' && ch!='3' && ch!='4' && ch !='5');
          switch(ch){
          case '1':
               grade=1;
               break;
          case '2':
               grade=2;
               break;
          case '3':
               grade=3;
               break;
          case '4':
               grade=4;
               break;
          case '5':
               grade=5;
               break;
          }
     }
    
     /*start the match*/
     end_match=0;

     do{
          initialize_game();
          game_result=play_game(&snake,grade);
          end_game(&snake);
          if(game_result==0){
               /*abort the match*/
               end_match=1;
          }
          else if(game_result==1){
               /*lose the game*/
               clrscr();
               gotoxy(27,12);
               cprintf("You have lose the game!");
               do{
                    while(bioskey(1)==0);
                    key=bioskey(0);
               }while(key != VK_ENTER);
               /*end the match*/
               end_match=1;
          }
          else{
               if(grade>=5){
                    /*win the match*/
                    clrscr();
                    gotoxy(15,12);
                    cprintf("Congratulations!You have pass all the grades!");
                    do{
                         while(bioskey(1)==0);
                         key=bioskey(0);
                    }while(key != VK_ENTER);
                    /*end the match*/
                    end_match=1;
               }
               else{
                    /*pass a game,continue or quit*/
                    do{
                         clrscr();
                         gotoxy(20,12);
                         cprintf("You win!Come to the next grade?(Y/N):");
                         ch=getchar();
                         ch=tolower(ch);
                    }while(ch != 'y' && ch != 'n');
                    if(ch=='n')
                         /*quit the match*/
                         end_match=1;
                    else
                         /*play the next grade*/
                         grade++;
               }
          }
     }while(end_match==0);
    
     /*clear the screen*/
     clrscr();

     return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值