正文

字符模式下的贪吃蛇2007-03-20 11:52:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/lingdlz/24128.html

分享到:

 贪吃蛇 编译环境:      TC3           要求显示器能提供:  彩色 43/50 线文本模式 否则程序将退出。 功 能:有计时,升级功能,可以完家控制蛇,也可以让电脑控制蛇             完家边欣赏边喝咖啡,可以暂停,可以立即退出 。                  请用记事本编辑源程序   说 明 :这个程序是上学期写的,现在看来很多缺陷      但是不想改了,这是个文本模式下的小游戏      本来想在图形模式下搞,但是在TC3下就是进      不了图形模式,偶尔进了一次,但硬盘搞挂后      又不知道怎么进了,幸亏把编译好的结果存到      了磁盘上。点击:下载完整代码snake.rar          部分代码: /**************************************************\ 编译环境:     TC3 (我还没找到其它可以的)           要求显示器能提供: 彩色 43/50 线文本模式              否则程序将退出。              请用记事本编辑源程序       author:江南孤峰  data: 2006--6--11    \**************************************************/ #include <stdio.h>#include <conio.h>#include <time.h>#include <stdlib.h>#include <dos.h>#include <graphics.h> /*  功能键定义  */ #define ESC   0x011b#define DOWN  0x5000#define LEFT  0x4b00#define RIGHT 0x4d00#define UP    0x4800#define ENTER 0x1c0d /* 边缘定义,其中下边缘随模式不同而不同 */ #define EDGE_LEFT   22#define EDGE_RIGHT  80#define EDGE_TOP    5 /* 移动状态键定义 */ #define GET_FOOD  2#define LOST_GAME 1#define WIN_GAME  0#define CAN_MOVE  0#define CANT_MOVE 3 /* 时间显示中断 */ #define _CPPARGS#define SHOW_TIME 0x1c /*************** 全局变量定义 ************************/ typedef struct snake_body{ int x,y;  struct snake_body *next;}snake_body; typedef struct snake_statues    /* 蛇头信息 */{ int save_x,save_y;  snake_body *head;  snake_body *trail;}snake_statues; snake_statues *snake;snake_body    *body_temp;      /* 初始化都在Re_Set()函数中完成 */int  EDGE_DOWN,MODE,show_time;   int  level,score,speed,Food_x,Food_y;char snake_head[8],snake_food[8],erase[8]; /**************** 函数申明 ****************************/ int  Re_Set();int  Over();void Init_Mode();void Init_Face();void Init_Block();void Init_Snake();void Set_Food();char Start_Play();void Print_Menu();char User_Key(); int User_Play();int Check_Move();int Move_Failed(); int Computer_Play();int Search_Path();int Test_Left();int Test_Right();int Test_Up();int Test_Down(); void interrupt newhandler(_CPPARGS);void My_Exit();void ReSet_Time(void interrupt(* proc)(_CPPARGS)); /********************* 主函数 *************************/ /* 这里我把这个函数注解了,如果你能进入图形模式就打开它   那样编译后的可执行文件可以直接进入全屏模式。void Init_Graph(){ int gdriver=DETECT,gmode;   registerbgidriver(EGAVGA_driver);  /*建立独立图形运行程序 *  initgraph(&gdriver,&gmode," ");  closegraph();}*/ void Hide_Cursor(void){/* 设置光标尺寸,隐藏光标 */ union REGS inregs,outregs; inregs.h.ch = 100; inregs.h.cl = 100; inregs.h.ah = 1; int86(0x10,&inregs,&outregs);} void main(){ int  t;  char c;  /* Init_Graph();  如果能够在图形模式下编译就打开这个函数    另外一种进入全屏模式的方法是,可以用TC2编译该函数,    在本程序中加入 system("可执行文件名"); 语句将TC2下编译    生成的可执行文件和本程序的可执行文件放一起,就可以直接进    入全屏模式。 */  system("full.exe");  Init_Mode();      /* 进入彩色 43/50 线文本模式 */  Hide_Cursor();  Init_Block();     /* 得到蛇身,蛇头内存块 */  ReSet_Time(newhandler); /* 重设时间中断过程 */ while( 1 )  { t = Re_Set();   /* 重完或初次游戏的初始化操作 */    if( t == 1)     /* 观看游戏 */    { t = Computer_Play();      if( t )  { t = Over(WIN_GAME);                  if( !t ) break;                    }      else     { t = Over(LOST_GAME);                 if( !t ) break;                }    }   else if( t == -1 )     { t = User_Play();      if( t )  { t = Over(WIN_GAME);                  if( !t ) break;                 }      else     { t = Over(LOST_GAME);               if( !t ) break;                }    }   else  break;    }  My_Exit();          /* 恢复时间中断处理过程 */} /**************** 和时间显示有关的函数 *****************/ void interrupt (*oldhandler)(_CPPARGS);    /* 旧时间中断处理函数指针 */ void interrupt newhandler(_CPPARGS)    /* 每次时间中断都会调用此函数 */{ show_time ++;  oldhandler();}        /* 设置新的中断处理过程 */void ReSet_Time(void interrupt(* proc)(_CPPARGS)){ oldhandler = getvect(SHOW_TIME);    /* 保存旧中断处理函数指针 */  disable();       /* 关闭所有中断 */  setvect(SHOW_TIME,proc);     /* 设置新中断处理函数 */  enable();       /* 开中断 */} void My_Exit()         /* 恢复中断处理过程 */{ disable();  setvect(SHOW_TIME,oldhandler);    /* 恢复源时间中断处理函数 */  enable();  exit(0);} /*********** 初始化显示模式定义下边缘  ****************/ void Init_Mode(){ struct text_info text;   textmode(64);      gettextinfo(&text);   if(text.screenheight == 43)     { MODE = 43;          EDGE_DOWN = 40;      }  else if(text.screenheight == 50)     { MODE = 50;    EDGE_DOWN = 46;  }  else  { printf("\n\n\tThe text mode was not c4350 ,Try use TC3 compiler !\n");         system("ENTER");         exit( 0 );        }} /************** 初始化所有数据 *********************/ int Re_Set() { char c;   level = 0;    /* 全局变量初始化 */  score = 0;  speed = 300;      show_time = 0;  snake = NULL;        body_temp = NULL;   Init_Face();       Init_Snake();  c = User_Key();    if( c == 'c')   return 1;         /* 观看电脑游戏 */  else  if( c == 'e')   return 0;         /* 退出游戏 */  else   return -1;        /* 开始游戏 */} /********************* 打印菜单 **********************/ void Print_Menu(){ if(MODE == 50)  window(1,6,22,45);  else            window(1,6,22,39);        textbackground(BLUE);     textcolor(WHITE);      clrscr();      printf("\n\n");      printf("     Level:0-9\n");      printf("\n  Current Score:0\n");      printf("\n  Current Level:0\n");      printf("\n  **  RUN OPTION  ** \n\n");      printf("**********************\n");      printf("*                    *\n");      printf("* start/ENTER:[Enter]*\n");      printf("*                    *\n");      printf("*   exit game:[Esc]  *\n");      printf("*                    *\n");       cprintf("*  move  left: [%c]   *",27); /* 打印方向键字符 */       cprintf("*  move right: [%c]   *",26);       cprintf("*  move  down: [%c]   *",25);       cprintf("*  move    up: [%c]   *",24);      printf("*                    *\n");      printf("*  Set  speed: [s]   *\n");      printf("*  Set  level: [d]   *\n");      printf("*  Computer_p: [c]   *\n");      printf("*                    *\n");      printf("**********************");      printf("\n\n\n");      printf("Run in:text mode c4350\n");      printf("should at fullscreen  \n\n");      printf("Run time: 00 : 00   \n\n");      printf("if you find some error\n");      printf("please send mail to me");} /****************** 获取用户输入 *********************/ char User_Key(){ int key;   error:  window(30,20,68,23);  textcolor(WHITE);  textbackground(BLUE);  highvideo();  clrscr();  gotoxy(1,2);  printf(" Enter your Select from left menu:");   for(key = 0; key < 8; key ++) { sound(key * 500);   delay( 100 ); }  nosound();   /* 铃声 */  while( !bioskey( 1 ) ) ;        /* 等待用户按键 */  key = bioskey( 0 );        /* 获取按键码 */  gotoxy(1,3);  switch( key )    { case 0x1f53:     /* s键设置游戏速度 */      case 0x1f73: printf(" Enter your speed:");     scanf("%d",&speed);     level = (300 - speed)/10;     if(level >= 10)         level = 9;  /* 将光标置于分数栏 */       if(MODE == 50)  window(1,6,22,45);        else            window(1,6,22,39);        gotoxy(17,5);   break;                                case 0x2044:     /* d键设置运行级别 */      case 0x2064: printf(" Enter your level:");     scanf("%d",&level);        if(MODE == 50)  window(1,6,22,45);        else            window(1,6,22,39);        gotoxy(17,7);   printf("%d\b",level);     speed = 300 - level * 10;   break;       case 0x2e43:     /* c键观看电脑游戏 */      case 0x2e63: key = -1;   break;       case ENTER:  key = 0;       break;           case ESC:    return 'e';    /* 退出游戏 */        default:    printf(" Input error !");      putch(7);   /* 输入不正确 */     sleep(1);            goto error;    }   if(MODE == 50)        window(24,6,79,45);      else                  window(24,6,79,39);   textbackground(BLACK);   clrscr();  gettext(30,18,31,19,erase);        puttext(snake->head->x,snake->head->y,     /* 初次绘蛇 */       snake->head->x+1,snake->head->y+1,snake_head);   puttext(snake->trail->x,snake->trail->y,       snake->trail->x+1,snake->trail->y+1,snake_food);  Set_Food();     if(MODE == 50)  window(1,6,22,45);   else            window(1,6,22,39);   gotoxy(17,5);                           /* 将光标置于分数栏 */   if(key == -1 )      return 'c';            else                return 'm';} /************ 获取组成蛇的两个字符块 ****************/ void Init_Block(){ textbackground(BLACK);  textcolor(GREEN);  clrscr();       /* 蛇身和食物块 */  gotoxy(36,18);     putch('@');     /*    @@        */  gotoxy(37,18);     putch('@');     /*    @@        */  gotoxy(36,19);     putch('@');  gotoxy(37,19);     putch('@');  gettext(36,18,37,19,snake_food);   textcolor(RED);    clrscr();       /* 蛇头块       */  gotoxy(36,18);     putch('*');     /*    **        */  gotoxy(37,18);     putch('*');     /*    **        */  gotoxy(36,19);     putch('*');  gotoxy(37,19);     putch('*');  gettext(36,18,37,19,snake_head);}      /************** 初始化用户界面 *********************/ void Init_Face(){ clrscr();  window(1,1,80,4);        { textbackground(GREEN); textcolor(WHITE);     highvideo(); clrscr(); gotoxy(22,3);     printf("WELCOME TO PLAY THE GAME OF SNAKE !");   }   if(MODE == 50)     window(1,47,80,50);      else               window(1,41,80,43);   { textbackground(GREEN);         textcolor(WHITE);     clrscr();              printf("\n\t  Author information: QQ:403324669 ,  Email:lingdlz@163.com ");   }   Print_Menu();     window(1,5,80,5);       { textbackground(RED);  clrscr(); }   if(MODE == 50)  window(1,46,80,46);       /* 下边缘 */  else            window(1,40,80,40);     { textbackground(RED); clrscr(); }   if(MODE == 50)  window(23,5,23,46);       /* 左边缘 */  else            window(23,5,23,40);     { textbackground(RED); clrscr(); }   if(MODE == 50)  window(80,5,80,46);       /* 右边缘 */  else            window(80,5,80,40);           { textbackground(RED); clrscr(); }               if(MODE == 50)  window(24,6,79,45);    else            window(24,6,79,39);     { textbackground(BLACK); clrscr(); }}  /******************** 初始化构成蛇的链表 *********************/ void Init_Snake(){ snake = (snake_statues *)malloc(sizeof(snake_statues));  snake->head->x = 36;             snake->head->y = 18;  body_temp = (snake_body *)malloc(sizeof(snake_body));  body_temp->x = 34;               body_temp->y = 18;  body_temp->next = NULL;  snake->head->next = body_temp;  snake->trail = body_temp;} /******************** 设置随机食物 *************************/ void Set_Food()   { int i = 0,down = 20;   /* 这个函数不完善,因为它要求很高 */  char test[8];           /* 既要随机出现,又要保证产生速度 */     if(MODE == 43)     down = 17; a:  randomize();      i = rand();   do{ i /= 13;      }while( i > down - 1 );   Food_y = i * 2 + 6;     randomize();      i = rand();   do{ i /= 11;      }while( i > 19 );   Food_x = i * 4 + 24;    gettext(Food_x,Food_y,Food_x+1,Food_y+1,test);        if( memcmp(test,erase,8) )     {           Food_x += 2; Food_y +=2;  gettext(Food_x,Food_y,Food_x+1,Food_y+1,test);    if( memcmp(test,erase,8) ) {        Food_x -= 2; Food_y +=2;  gettext(Food_x,Food_y,Food_x+1,Food_y+1,test);    if( memcmp(test,erase,8) )   {       Food_x -= 2; Food_y -=2;  gettext(Food_x,Food_y,Food_x+1,Food_y+1,test);    if( memcmp(test,erase,8) )     {     Food_x += 2; Food_y -=2;  gettext(Food_x,Food_y,Food_x+1,Food_y+1,test);    if( memcmp(test,erase,8) )        {  Food_x = 24; Food_y = 6;  gettext(Food_x,Food_y,Food_x+1,Food_y+1,test);    if( memcmp(test,erase,8) )  { Food_x = 48; Food_y = 40;  gettext(Food_x,Food_y,Food_x+1,Food_y+1,test);    if( memcmp(test,erase,8) )    goto a;  }       }     } /* 这里很晕吧,这样其实还不行,主要是那个随机数 */   }   /* 产生器不怎么随机食物老是在一个范围里出现自己 */ }     /* 又不会编写随机数函数,哎!空一声长叹         */     }  puttext(Food_x,Food_y,Food_x+1,Food_y+1,snake_food);} /******************** 移动蛇 ***************************/ int Move_Snake(int add)     { int save_x1,save_x2,save_y1,save_y2;  char strtime[10];   if(show_time > 17)   /* 显示时间 */  { if(MODE == 50)  window(1,6,22,45);           else            window(1,6,22,39);   show_time = 0;  /* 恢复计时器 */   gotoxy(1,32);   _strtime(strtime);   printf("Run Time: %10s",strtime);   }   puttext(snake->head->x,snake->head->y,snake->head->x+1,       snake->head->y+1,snake_head);   puttext(snake->save_x,snake->save_y,snake->save_x + 1,       snake->save_y + 1,snake_food);   if( !add )       /* 没有得到食物的移动擦除蛇尾  */  puttext(snake->trail->x,snake->trail->y,snake->trail->x + 1,       snake->trail->y + 1,erase);  delay(speed);   body_temp = snake->head->next;  /* 改变蛇身坐标,坐标依次前移   */  save_x1 = body_temp->x;             save_y1 = body_temp->y;  body_temp->x = snake->save_x;      body_temp->y = snake->save_y; while(body_temp->next)   /* 依次将坐标值往后移动        */    { body_temp = body_temp->next;      save_x2 = body_temp->x;          save_y2 = body_temp->y;      body_temp->x = save_x1;          body_temp->y = save_y1;      save_x1 = save_x2;               save_y1 = save_y2;    }  if( add )     /* 得到食物改变蛇尾指针,增加移动速度 */     { body_temp = (snake_body *)malloc(sizeof(snake_body));       body_temp->x = save_x1;            body_temp->y = save_y1;       body_temp->next = NULL;            snake->trail->next = body_temp;        speed -= 6;   /* 更新速度得分和级别 */         score += 100;        if(MODE == 50)  window(1,6,22,45);        else            window(1,6,22,39);        gotoxy(17,5);   printf("%d\b",score);        if(score % 500 == 0)          { level++;       gotoxy(17,7);       printf("%d\b",level);   }         putch(7);   /* 响铃 */     }  snake->trail = body_temp;   /* 新尾指针 */  if(level == 9 && score >= 4500)        return 1; else                                   return 0;} /******************* 释放用户分配内存 **********************/ void Free(){ snake_body *temp;                     temp = snake->head;           free(snake);  while(temp->next)    { body_temp = temp->next;       free(temp);      temp = body_temp;    }                          free(temp);} /******************** 游戏结束提示是否继续 ********************/ int Over(int t){ int  i;   if( t == WIN_GAME)       for(i = 0; i < 8; i ++)        /* 响铃示警 */ { sound(300 * i);    delay(100);  }  else for(i = 0; i < 8; i ++) { sound( 500 );      delay(100);  } nosound();        /* 关闭扬声器 */  window(35,16,60,24);                /* 定义游戏结束窗口 */ textattr(BLINK+WHITE+(RED<<4));        clrscr();                              gotoxy(1,2); if( t == LOST_GAME )       cprintf("       GAME OVER  ! "); else  cprintf("   HAPPY YOU WIN  ! ");  gotoxy(1,4); cprintf(" Enter:[ESC]    exit ");      gotoxy(1,6); cprintf(" Enter:[other]  continue ");   while( !bioskey( 1 ) )   ;  i = bioskey( 0 );       delay(500);   if(i == ESC)   return 0;  else           return 1;} /************************ 用户游戏函数 **************************/ int User_Play(){ int d = DOWN,t = 0;  int key; while( 1 )  { while(!kbhit())                   /* 自动移动 */     {  key = Check_Move( d );      switch( key )       { case CAN_MOVE:  t = Move_Snake(0);  break;    case LOST_GAME: return 0;                  case CANT_MOVE: d = Move_Failed(d); break;      /* 用户按下无效移动键 */  case GET_FOOD:  t = Move_Snake( 1 );            if( t )   return 1;         /* 胜利,回主函数 */     else        Set_Food();        break;       }    }          key = bioskey( 0 );       /* 接收按键 */     switch( key )      {  case DOWN:   d = DOWN;  break;         case LEFT:   d = LEFT;  break;         case RIGHT:  d = RIGHT; break;         case UP:     d = UP;    break;         case ENTER: do{ while(!kbhit())     ;     key = bioskey( 0 );         } while(key != ENTER);      break;         case ESC: window(30,20,68,23);      printf(" Do you really want to exit(y/n) ?");            key = getche();            if( key == 'y' || key == 'Y' )              { Free();    My_Exit(); }  /* 按下退出键释放内存退出游戏 */     else clrscr(); break; default:     window(30,20,68,23);  /* 无效按键处理 */       printf("\t  Use direction key please !");       sleep( 1 );       clrscr();        if(MODE == 50)  window(1,6,22,45); /* 光标移动到得分栏 */               else            window(1,6,22,39);               gotoxy(17,5);          }      key = Check_Move( d );     switch( key )      { case CAN_MOVE:  t = Move_Snake(0);  break;  /* 没有食物的移动 */ case LOST_GAME: return 0;                /* 失败返回主函数 */ case CANT_MOVE: d = Move_Failed(d);  break;   case GET_FOOD:  t = Move_Snake( 1 );               if( t )  return 1;       /* 胜利,回主函数 */       else     Set_Food();      }  }} /**************** 检查移动状态 ********************/ int Check_Move(int dest)    { int x,y;  char test[8];  x = snake->head->next->x;  y = snake->head->next->y;  snake->save_x = snake->head->x;  snake->save_y = snake->head->y;  switch(dest)    { case DOWN:  snake->head->y += 2;  break;      case LEFT:  snake->head->x -= 2;  break;      case RIGHT: snake->head->x += 2;  break;      case UP:    snake->head->y -= 2;  break;      default:    break;    }  if(snake->head->x == Food_x && snake->head->y == Food_y)       return GET_FOOD;  if(snake->head->x >= EDGE_RIGHT || snake->head->x <= EDGE_LEFT ||     snake->head->y >= EDGE_DOWN  || snake->head->y <= EDGE_TOP)       return LOST_GAME;  if(x == snake->head->x && y == snake->head->y)       return CANT_MOVE;  gettext(snake->head->x,snake->head->y,       snake->head->x + 1,snake->head->y + 1,test);   if( memcmp(snake_food,test,8) ) return CAN_MOVE;  else       return LOST_GAME;} /****************** 处理用户的无效按键 *******************/ int Move_Failed(int dest){  snake->head->x = snake->save_x;     snake->head->y = snake->save_y;   switch(dest)                   { case UP:    dest = DOWN;        break;        case LEFT:  dest = RIGHT;       break;        case RIGHT: dest = LEFT;        break;        case DOWN:  dest = UP;          break;      }   return dest;}

阅读(4257) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册