回 帖 发 新 帖 刷新版面

主题:[原创]我的贪吃蛇

我的贪吃蛇  



发表日期:2004年6月2日  出处:原创  作者:钟振龙  已经有9位读者读过此文



      看了许多有关游戏方面的编程,心痒痒的,但由于是个初学者,要想完成一个自己编的游戏,实在有点困难。这个游戏谈不上是原创,因为有很多人编过类似的游戏,应该说是模仿的吧!但对于我来说,这是一个挑战,花了我3天的时间才编写好。现在拿出来和大家分享一下,希望大家提提建议,仅供初学者交流而已!

   源程序如下:

#define N 200/*定义全局常量*/
#define m 25
#include <graphics.h>
#include <math.h>
#include <stdlib.h>
#include <dos.h>
#define LEFT 0x4b00
#define RIGHT 0x4d00
#define DOWN 0x5000
#define UP 0x4800
#define Esc 0x011b
int i,j,key,k;
struct Food/*构造食物结构体*/
{
   int x;
   int y;
   int yes;
}food;
struct Goods/*构造宝贝结构体*/
{
   int x;
   int y;
   int yes;
}goods;
struct Block/*构造障碍物结构体*/
{
   int x[m];
   int y[m];
   int yes;
}block;
struct Snake{/*构造蛇结构体*/
   int x[N];
   int y[N];
   int node;
   int direction;
   int life;
}snake;
struct Game/*构建游戏级别参数体*/
{
   int score;
   int level;
   int speed;
}game;
/*定义函数*/
void init(void);/*定义图形驱动*/
void close(void);/*定义关闭函数*/
void drawk(void);/*定义界面函数*/
void gameover(void);/*定义游戏结束函数*/
void gameplay(void);/*定义游戏主函数*/
void prscore(void);/*定义得分函数*/

void main(void){/*主函数体,调用以下四个函数*/
   init();
   setbkcolor(7);
   drawk();
   gameplay();
   close();
}

void init(void){/*构建图形驱动函数*/
   int gd=DETECT,gm;
   initgraph(&gd,&gm,"");
   cleardevice();
}

void drawk(void){/*构建游戏界面函数*/
   /*setbkcolor(LIGHTGREEN);*/
   char str3[50];
   setfillstyle(SOLID_FILL,BLUE);/*条型边框,显示版本信息*/
   bar3d(48,9,610,38,1,45);
   setcolor(YELLOW);/*版本信息*/
   sprintf(str3,"Version:5.01,Powerwing Studio");
   outtextxy(330,20,str3);
   setfillstyle(LTSLASH_FILL,YELLOW);/*设定墙边的填充形式*/
   bar3d(48,48,58,462,0,0);/*设定墙边*/
   bar3d(48,39,611,48,0,0);
   bar3d(48,452,611,462,0,0);
   bar3d(602,39,611,462,0,0);

}

void gameplay(void){/*构建游戏主函数*/
   /*初始化游戏角色*/
   randomize();/*随机数发生器*/
   goods.yes=1;
   block.yes=1;
   food.yes=1;/*场景中需建立新的食物*/
   snake.life=1;/*初始化蛇生命值*/
   snake.direction=1;/*蛇起始的移动方向定义为向右*/
   snake.x[0]=100;snake.y[0]=100;/*蛇头的位置坐标初始化*/
   snake.x[1]=110;snake.y[1]=100;
   snake.node=2;/*蛇初始化节数,共两节只有蛇头*/
   /*初始化障碍物的数组*/
          block.x[0]=170;block.y[0]=270;/*level 1*/
          block.x[1]=410;block.y[1]=310;
          block.x[2]=300;block.y[2]=200;
          block.x[3]=320;block.y[3]=420;
          block.x[4]=250;block.y[4]=350;  
          block.x[5]=220;block.y[5]=320;/*level 2*/
          block.x[6]=310;block.y[6]=410;
          block.x[7]=400;block.y[7]=500;
          block.x[8]=230;block.y[8]=230;
          block.x[9]=280;block.y[9]=280;
          block.x[10]=170;block.y[10]=280;/*level 3*/
          block.x[11]=420;block.y[11]=310;
          block.x[12]=310;block.y[12]=200;
          block.x[13]=320;block.y[13]=400;
          block.x[14]=250;block.y[14]=260;/*level 4*/  
          block.x[15]=220;block.y[15]=330;
          block.x[16]=130;block.y[16]=410;
          block.x[17]=310;block.y[17]=510;
          block.x[18]=230;block.y[18]=340;
          block.x[19]=280;block.y[19]=380;
          block.x[20]=270;block.y[20]=170;/*level 5*/
          block.x[21]=410;block.y[21]=450;
          block.x[22]=190;block.y[22]=200;
          block.x[23]=150;block.y[23]=320;
          block.x[24]=270;block.y[24]=350;  
          block.x[25]=340;block.y[25]=320;
         
   game.score=0;
   game.speed=50000;
   game.level=1;
   prscore();/*得分初始化*/
   while(1){/*判断为真可以按Esc退出循环结束游戏*/
      while(!kbhit()){/*无按键按下时,蛇自己移动身体*/

         if(game.level==1){/*画出障碍物*/        
          for(j=0;j<5;j++){
          setcolor(5);/**/
          rectangle(block.x[j],block.y[j],block.x[j]+10,block.y[j]-10);
          block.yes=0;
          }
         }
         if(game.level==2){/*画出障碍物*/        
          for(j=0;j<9;j++){
          setcolor(5);/**/
          rectangle(block.x[j],block.y[j],block.x[j]+10,block.y[j]-10);
          block.yes=0;
          }
         }
         if(game.level==3){/*画出障碍物*/        
          for(j=0;j<14;j++){
          setcolor(5);/**/
          rectangle(block.x[j],block.y[j],block.x[j]+10,block.y[j]-10);
          block.yes=0;
          }
         }
         if(game.level==4){/*画出障碍物*/        
          for(j=0;j<19;j++){
          setcolor(5);/**/
          rectangle(block.x[j],block.y[j],block.x[j]+10,block.y[j]-10);
          block.yes=0;
          }
         }
         if(game.level==5){/*画出障碍物*/        
          for(j=0;j<25;j++){
          setcolor(5);/**/
          rectangle(block.x[j],block.y[j],block.x[j]+10,block.y[j]-10);
          block.yes=0;
          }
         }
         if(food.yes==1){/*需要画出新的食物*/
           food.x=rand()%400+60;/*获得间隔60的随机数食物坐标值*/
           food.y=rand()%350+60;
           while(food.x%10!=0)/*判断坐标值是否满足被10整除,否,自动增加*/
               food.x++;
           while(food.y%10!=0)
               food.y++;
           food.yes=0;/*新的食物已经产生*/     
         }

         if(goods.yes==1){/*需要画出新的宝物*/
           goods.x=rand()%380+60;/*获得间隔60的随机数宝贝坐标值*/
           goods.y=rand()%320+80;
           while(goods.x%10!=0)/*判断坐标值是否满足被10整除,否,自动增加*/
               goods.x++;
           while(goods.y%10!=0)
               goods.y++;
           goods.yes=0;/*新的宝贝已经产生*/     
         }
         if(goods.yes==0){/*新宝贝产生,应显示出来*/

           setcolor(0);/*擦除*/
           rectangle(goods.x,goods.y,goods.x+10,goods.y-10);
           delay(50);/*延时*/
           setcolor(YELLOW);
           goods.x=goods.x+random(10)-random(20);/*随机数增量*/
           goods.y=goods.y+random(10)-random(20);
           while(goods.x%10!=0)/*判断变化后的坐标值是否满足被10整除,否,自动增加*/
               goods.x++;
           while(goods.y%10!=0)
               goods.y++;          
           rectangle(goods.x,goods.y,goods.x+10,goods.y-10);/*重画出宝贝*/
           if(goods.x<65||goods.x>585||goods.y<65|goods.y>445){/*判定宝贝是否越界*/
               setcolor(0);/*擦除越界的宝贝*/
               rectangle(goods.x,goods.y,goods.x+10,goods.y-10);
               goods.yes=1;/*越界后重新生成宝贝*/
           }
                      
         }

         if(food.yes==0){/*新食物产生,应显示出来*/
           setcolor(GREEN);
           setlinestyle(SOLID_LINE,0,THICK_WIDTH);/*设定当前线型*/
           rectangle(food.x,food.y,food.x+10,food.y-10);
         }
      for(i=snake.node-1;i>0;i--){/*取得需重画的蛇的节数*/
         snake.x[i]=snake.x[i-1];/*最后一节的坐标值等于倒数第二节的坐标值*/
         snake.y[i]=snake.y[i-1];    
      }   
      switch(snake.direction){/*判断蛇头的移动方向*/
         case 1:snake.x[0]+=10;break;/*向右*/
         case 2:snake.x[0]-=10;break;/*向左*/
         case 3:snake.y[0]-=10;break;/*向上*/
         case 4:snake.y[0]+=10;break;/*向下*/
      }
      for(i=3;i<snake.node;i++){/*超过4节后,判断蛇自身碰撞*/
         if(snake.x[i]==snake.x[0]&&snake.y[i]==snake.y[0]){/*即自身的任一节坐标值与蛇头坐标相等*/  
         for(i=1;i<snake.node-1;i++){/*擦除自己碰撞后位置蛇的身子*/
         setcolor(0);
         rectangle(snake.x[i],snake.y[i],snake.x[i]+10,snake.y[i]-10);
         rectangle(snake.x[snake.node-1],snake.y[snake.node-1],         
         snake.x[snake.node-1]+10,snake.y[snake.node-1]-10);
         }
         snake.life-=1;/*生命值减少一*/
         snake.node-=5;
         prscore();/*输出结果*/
         if(snake.life==0){/*判断生命值是否为0*/  
         gameover();/*游戏结束*/
         break;/*退出内循环*/
         }
        }
      }
      if(snake.x[0]<55||snake.x[0]>595||snake.y[0]<55||snake.y[0]>455){/*判断蛇是否与墙体碰撞*/
         for(i=1;i<snake.node-1;i++){/*擦除撞墙后位置蛇的身子*/
         setcolor(0);
         rectangle(snake.x[i],snake.y[i],snake.x[i]+10,snake.y[i]-10);
         rectangle(snake.x[snake.node-1],snake.y[snake.node-1],         
         snake.x[snake.node-1]+10,snake.y[snake.node-1]-10);
         }
         snake.x[0]=100;snake.y[0]=100;/*蛇头的位置坐标重新初始化*/
         snake.x[1]=110;snake.y[1]=100;
         snake.direction=1;/*蛇起始的移动方向定义为向右*/        
         snake.life-=1;/*生命值减少一*/
         snake.node-=5;/*相应节数减少5节*/
         prscore();        
         if(snake.life==0){
         gameover();
         break;
         }
      }
       /*判断蛇与障碍物碰撞,食物是否与障碍物重叠*/
       if(game.level==1){/*判断级别,并设定相应的障碍物数量,即数组个数*/
         k=5;
       }
       else if(game.level==2){
         k=9;
       }
       else if(game.level==3){
         k=14;
       }
       else if(game.level==4){
         k=19;
       }
       else if(game.level==5){
         k=25;
       }
         for(j=0;j<k;j++){
         if(snake.x[0]==block.x[j]&&snake.y[0]==block.y[j]){
           for(i=1;i<snake.node-1;i++){/*擦除撞墙后位置蛇的身子*/
           setcolor(0);
           rectangle(snake.x[i],snake.y[i],snake.x[i]+10,snake.y[i]-10);
           rectangle(snake.x[snake.node-1],snake.y[snake.node-1],         
           snake.x[snake.node-1]+10,snake.y[snake.node-1]-10);
           }
         if(food.x==block.x[j]&&block.y[j]==food.y){/*防止障碍物与食物重叠*/
           setcolor(0);/*设定食物的颜色为背景色,即擦除*/
           rectangle(food.x,food.y,food.x+10,food.y-10);
           food.yes=1;/*食物重新生成*/
         }
           snake.x[0]=100;snake.y[0]=100;/*蛇头的位置坐标重新初始化*/
           snake.x[1]=110;snake.y[1]=100;
           snake.direction=1;/*蛇起始的移动方向定义为向右*/        
           snake.life-=1;
           snake.node-=5;
           prscore();
           if(snake.life==0){
           gameover();
           break;
           }
          }
          }

      if(snake.x[0]==food.x&&snake.y[0]==food.y){/*判断蛇是否吃到食物*/
    
         setcolor(0);/*设定食物的颜色为背景色,即擦除*/
         rectangle(food.x,food.y,food.x+10,food.y-10);
         snake.x[snake.node]=-20;/*新的一节放在不可见的位置*/
         snake.y[snake.node]=-20;
            snake.node++;/*蛇身增加一节*/
            if(snake.node>2){/*当节数每增加5节生命值增加一*/               
               snake.life=1+fabs((snake.node-2)/5);
            }
            food.yes=1;/*场景需要增加食物*/   
            game.score+=20;/*加分*/
            prscore();/*输出得分*/  
      }     
      if(snake.x[0]==goods.x&&snake.y[0]==goods.y){/*判定蛇是否得到宝贝*/
         setcolor(0);/*设定宝贝的颜色为背景色,即擦除*/
         rectangle(goods.x,goods.y,goods.x+10,goods.y-10);
            goods.yes=1;/*场景需要增加新的宝贝*/   
            game.score+=100;/*得到宝贝后加100分*/
            prscore();/*输出得分*/  
      }    

            if(game.score<500){/*设定游戏速度和难度级别*/
              game.speed=50000;
              game.level=1;}
            else if(game.score>=500&&game.score<1000){
              game.level=2;
              game.speed=40000;}
            else if(game.score>=1000&&game.score<1500){
              game.level=3;
              game.speed=30000;}
            else if(game.score>=1500&&game.score<2000){
              game.level=4;
              game.speed=20000; }
            else if(game.score>=5000){
              game.level=5;
              game.speed=10000;}

      setcolor(4);/*画出移动的蛇*/
      setlinestyle(SOLID_LINE,0,THICK_WIDTH);/*设定当前线型*/
      for(i=0;i<snake.node;i++)
        rectangle(snake.x[i],snake.y[i],snake.x[i]+10,snake.y[i]-10);
      delay(game.speed);
      setcolor(0);/*用背景色擦去最后一节*/
      rectangle(snake.x[snake.node-1],snake.y[snake.node-1],
      snake.x[snake.node-1]+10,snake.y[snake.node-1]-10);

      
} /*endwhile(! kbhit) */

if(snake.life==0)/*判断循环结束条件:蛇死或者检测到Esc按键*/
  break;

key=bioskey(0);/*判断按键*/
if(key==Esc)
  break;
/*判断蛇头接收到的用户按键响应的移动方向*/
else if(key==UP&&snake.direction!=4)
    snake.direction=3;
else if(key==RIGHT&&snake.direction!=2)
    snake.direction=1;
else if(key==LEFT&&snake.direction!=1)
    snake.direction=2;
else if(key==DOWN&&snake.direction!=3)
    snake.direction=4;

}/*endwhile(1)*/
}
void gameover(void){/*游戏结束处理*/
   cleardevice();/*清屏*/
   prscore();/*输出得分*/
   setcolor(RED);/*打印出“Game Over”字样*/
   settextstyle(0,0,4);
   outtextxy(200,200,"Game Over!");
   getch();
}

void prscore(void){/*定义分数输出函数*/
   char str1[10];
   char str2[10];
   char str4[20];
   setfillstyle(SOLID_FILL,BLUE);/*用于清除旧的显示信息*/
   bar(49,10,320,37);
   setcolor(WHITE);
   settextstyle(0,0,1);
   sprintf(str1,"score:%d",game.score);/*输出得分*/
   outtextxy(55,20,str1);
   sprintf(str2,"level:%d",game.level);/*输出级别*/
   outtextxy(250,20,str2);
   sprintf(str4,"life:%d",snake.life);/*输出级别*/
   outtextxy(150,20,str4);
}

void close(void){/*定义关闭函数,退出图形模式*/
   getch();
   closegraph();
}


    程序很长,不过我都加了注释,应该很好理解。我是编程爱好者,没有专业训练,希望能和其他编程爱好者们交朋友,我的QQ:349492800 或MSN :yalong510@yahoo.com.cn。欢迎随时找我哦!



回复列表 (共39个回复)

沙发

哇!真不错!c语言的高手,以后请多指教哦.老大!~[em5]

板凳

写了这么多的代码,手应该都写酸了把

3 楼

啊哈哈   的确很常呀!!!!
  不想看了

4 楼

效果怎样还不知道,但程序的结构还不错,支持啊

5 楼

我想实现在每次蛇吃到食物后,障碍物重新随机生成,但我发现,虽然能实现,但重绘出来的障碍物会被goods和蛇擦掉,虽能帮我解决这个问题!

6 楼

aa

7 楼

老哥啊  有问题的程序也来啊

8 楼

昏...居然还出 DOS 下的游戏...精神可嘉

9 楼

程序在tc2.0下编译通过了,没问题的

10 楼

[em1][em13]
编译通过,三天能完成比较成熟的东东,不同一般,真的:)

我来回复

您尚未登录,请登录后再回复。点此登录或注册