⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 display.c

📁 《C程序员成长攻略》-黎陡-源代码,书中所有源码
💻 C
字号:
/*-----------------------------Display.c-------------------------------*/
/*------------------动画演示文件----------------------------*/
/*------------初始化图形界面--------------------------*/
void InitGraph()
{
  int gd=DETECT,gm;
  initgraph(&gd,&gm,"c:\tc\tc");
}

/*------------画大本营标志--------------*/
void DrawEagle()
{
  int i=6;
  int x,y;
  x=emp.x; y=emp.y;
  setcolor(CYAN);
  moveto(x-i/2,y-5*i);
  lineto(x-i/2,y-i/2);
  lineto(x-6*i,y-5*i);
  lineto(x-3*i,y+2.5*i);
  lineto(x-i,y+2*i);
  lineto(x-i/2,y+2*i);
  lineto(x-i/2,y+3.5*i);
  lineto(x-2*i,y+5*i);
  lineto(x-i/2,y+4.5*i);
  lineto(x-i/2,y+5*i);

  lineto(x+i/2,y+5*i);
  lineto(x+i/2,y+4.5*i);
  lineto(x+2*i,y+5*i);
  lineto(x+i/2,y+3.5*i);
  lineto(x+i/2,y+2*i);
  lineto(x+i,y+2*i);
  lineto(x+3*i,y+2.5*i);
  lineto(x+6*i,y-5*i);
  lineto(x+i/2,y-i/2);

  lineto(x+i/2,y-4*i);
  lineto(x+i,y-4*i);
  lineto(x-i/2,y-5*i);
  lineto(x-i/2,y-i/2);
  setfillstyle(1,CYAN);
  floodfill(x,y,CYAN);
}

/*--------------画炮台--------------------------------*/
void Emplacement()
{
  int x1,y1;
  emp.x=rect.left+rect.width/2,emp.y=rect.bottom-31;  /*设置炮台中心位置*/
  emp.width=60,emp.lenth=40;  /*设置炮台大小*/
  emp.color=YELLOW;  /*炮台边框颜色*/
  setfillstyle(1,0);
  bar(emp.x-emp.width,emp.y-emp.lenth,emp.x+emp.width,emp.y+emp.lenth); /*先清除这片区域的背景*/
  setcolor(emp.color);
  rectangle(emp.x-emp.width,
emp.y-emp.lenth,
emp.x+emp.width,
emp.y+emp.lenth);
  rectangle(emp.x-emp.width+10,
emp.y-emp.lenth+10,
emp.x+emp.width-10,
emp.y+emp.lenth-10);
  setfillstyle(1,LIGHTGRAY);
  floodfill(emp.x-emp.width+1,emp.y-emp.lenth+1,emp.color);
/*填充两个矩形框之间的部分*/
  DrawEagle();
}

/*--------------将整型转化为字符型--------------------*/
void ShowInt(int data,int x,int y)
{ 
  char *s;
  sprintf(s,"%d",data);
  outtextxy(x,y,s);
}

/*--------------画坦克--------------------------------*/
void DrawTank(struct Target T,int Tcolor,int GunColor)
{
  int i,j;
  int x=T.x,y=T.y,r=T.r,d,t;
  d=r/4;t=d*0.6;
  setcolor(Tcolor);
   /*------------------*/
  line(x-r,y,x+r-t,y);
  line(x-r,y,x-r+d,y+2*d);
  line(x-r+d,y+2*d,x+3*d,y+2*d);
  line(x+3*d,y+2*d,x+r-t,y);
  /*----------------------*/
  line(x-r,y,x-r+t,y-t);
  line(x-r+t,y-t,x-2*d,y-t);
  line(x-2*d,y-t,x-2*d+t,y-d-t);
  line(x-2*d+t,y-d-t,x-3*d,y-d-t);
  line(x-3*d,y-d-t,x-3*d+t,y-2*d);
  line(x-3*d+t,y-2*d,x+r-t,y-2*d);
  line(x+r-t,y-2*d,x+r-t,y);
  /*---------------------------*/
  line(x-3*d,y-d-t,x-2*d,y-t);
  /*------------------------*/
  line(x-r+d-t,y+2*(d-t),x+3*d+r*0.04,y+2*(d-t));
  for(i=0;i<2*(r/d-1);i++)
    line(x-3*d+i*d,y+2*(d-t),x-3*d+i*d,y+2*d);
  /*---------------------------------*/
  setfillstyle(1,Tcolor);
  bar(x-d*1.2,y-d*0.6,x+d*2,y-d*0.2);
  line(x-d*1.2,y-d*0.6,x-d*0.6,y-d*1.8);
  line(x-d*0.6,y-d*1.8,x+d*2.4,y-d*1.8);
  line(x+d*2.4,y-d*1.8,x+d*2,y-d*0.6);
  line(x+d*2.4,y-d*1.8,x+d*2.4,y-d*1.4);
  line(x+d*2,y-d*0.2,x+d*2.4,y-d*1.4);
  sector(x+d*0.6,y-d,0,180,d*1.2,d*1.4);
  for(i=0;i<d*0.3;i++)
      line(x+d*0.2,y-d*1.8+i,x-d*2.5,y-d*1.8+i);
  setfillstyle(1,GunColor);  /*用颜色GunColor画炮头*/
  bar(x-d*3,y-d*1.9,x-d*2.3,y-d*1.3);
  setcolor(Tcolor);
  ShowInt(T.ID,x,y-3*d-t); /*显示该坦克的编号*/
}

/*--------------演示背景框的绘制------------------*/
void DisplayBG()
{
  int i;
  clearviewport();
  /*--------画演示矩形框----------*/
  setbkcolor(0);
  setcolor(LIGHTGRAY);
  rect.width=550;
  rect.height=450;
  rect.d=70;
  rect.left=30;
  rect.top=20;
  rect.right=rect.left+rect.width;
  rect.bottom=rect.top+rect.height;
  rectangle(rect.left,rect.top,rect.right,rect.bottom);
  rectangle(rect.left-10,rect.top-10,rect.right+10,rect.bottom+10);
  setfillstyle(1,LIGHTGRAY);
  floodfill(rect.left-1,rect.top-2,LIGHTGRAY);
  /*--------画炮台----------------*/
  Emplacement();
}

/*--------------------初始化目标并显示-------------------*/
void InitTarget()
{
  int i,t;
  randomize();
  for(i=0;i<n;i++)  /*给n辆坦克各成员变量预先赋初值*/
  {
      Tank[i].color=color[random(3)];
/*从预先定义的三种颜色中随机产生一种赋给该坦克*/
      Tank[i].r=20;   /*坦克半径均设为20(当然也可设为不同的值)*/
      Tank[i].x=rect.left+Tank[i].r+random(rect.width-2*Tank[i].r);
/*坦克初始x坐标为在矩形框范围内一随机的坐标*/
      Tank[i].y=rect.top+Tank[i].r+
random(rect.height-2*emp.lenth-2*Tank[i].r);
/*坦克y坐标范围为矩形框内炮台之上的任意值*/
      Tank[i].ID=i+1;   /*坦克标识符ID值为从1号依次递增*/
      t=random(2);
/*随机产生初始方向值。由于方向值没有0,且关于0对称,
因而采用如下方式来随机产生*/
      if(t==0) 
        Tank[i].direction=1+random(4);      /*产生正的方向值*/
      else     
        Tank[i].direction=0-(1+random(4));  /*产生负的方向值*/
      DrawTank(Tank[i],Tank[i].color,RED);         /*显示该坦克*/
  }
}

/*----------------画初始星空背景------------------------*/
void DrawStarBG()
{
  int i,pixel_x,pixel_y;
  for(i=0;i<100;i++)   /*初始状态下共随机产生100个点*/
  {
      do
      { /*在演示矩形框内随机产生坐标点*/
          pixel_x=rect.left+10+random(rect.width-20);
          pixel_y=rect.top+10+random(rect.height-20);
      }while((pixel_x>emp.x-emp.width) && (pixel_x<emp.x+emp.width)
&& (pixel_y>emp.y-emp.lenth));
/*如果产生的该坐标位于大本营区域内,则重新产生一个坐标,
直到位于大本营区域外*/
      putpixel(pixel_x,pixel_y,StarColor);   /*在产生的坐标处画一个点*/
  }
}

/*----------------在坐标(x,y)处画闪烁的星的图案------------------------*/
void DrawShineStar(int x,int y,int i,int color)
{
  setcolor(color);
  line(x+i,y-i,x+4*i,y);
  line(x+i,y-i,x,y-4*i);
  line(x-i,y-i,x-4*i,y);
  line(x-i,y-i,x,y-4*i);
  line(x+i,y+i,x+4*i,y);
  line(x+i,y+i,x,y+4*i);
  line(x-i,y+i,x-4*i,y);
  line(x-i,y+i,x,y+4*i);
}

/*----------------星空闪烁效果------------------------------*/
void Shine()
{
  int i,r=2,x,y;
  do
  { /*在演示矩形框内随机产生坐标点*/
      x=rect.left+10+random(rect.width-20);
      y=rect.top+10+random(rect.height-20);
  }while((x>emp.x-emp.width-15) && (x<emp.x+emp.width+15)
	&& (y>emp.y-emp.lenth-15));
/*如果产生的该坐标位于大本营区域内,则重新产生一个坐标,
直到位于大本营区域外*/

  for(i=0;i<r;i++)
  {  
     /*由小到大画闪烁的星图,i代表该图的一个基本单位*/
     DrawShineStar(x,y,i,StarColor);
     delay(3000);
     DrawShineStar(x,y,i,DisplayColor);   /*延时后再将原星图用背景色清除*/
  }
  for(i=r;i>=0;i--)
  { 
    /*再从大到小画闪烁的星图*/
     DrawShineStar(x,y,i,StarColor);
     delay(3000);
     DrawShineStar(x,y,i,DisplayColor);
  }
  /*闪烁之后在该坐标处画一个点*/
  putpixel(x,y,StarColor);
}

/*-------决定当前坦克是否按当前方向值运动,或是碰到边框而须改变方向------*/
int IsXYValid(struct Target T,int x,int y)
{
  int i;
  if((x>rect.left+T.r) && (x<rect.right-T.r) &&
	 (y>rect.top+T.r) && (y<rect.bottom-T.r*5/6))
/*判断尝试改变后的坐标如果位于演示矩形框内*/
  {
      if((x+T.r<emp.x-emp.width) || (x-T.r>emp.x+emp.width) ||
	 (y+T.r<emp.y-emp.lenth))                      /*如果未碰到大本营边框*/
      {  
       /*则表示可以向该方向运动,在这个新的位置画出该坦克*/
         return 1;  /*函数返回1*/
      }
      else  /*否则,如果碰到大本营边框,则函数返回0*/
         return 0;
    }
    else /*否则,如果碰到演示矩形边框,则函数返回0*/
      return 0;
}
/*--------------锁定目标的效果-------------------------*/
int Lock(struct Target T)
{
  int i,r=T.r,x,y;
  int s;
  char ch;
  s=r/4;
  for(i=0;i<3;i++)
     circle(T.x,T.y,r+i);
  line(T.x-r-2*s,T.y,T.x+r+2*s,T.y);
  line(T.x,T.y-r-2*s,T.x,T.y+r+2*s);
  line(T.x+r+2*s,T.y,T.x+r+2*s-5,T.y-5);
  line(T.x+r+2*s,T.y,T.x+r+2*s-5,T.y+5);
  line(T.x,T.y-r-2*s,T.x-5,T.y-r-2*s+5);
  line(T.x,T.y-r-2*s,T.x+5,T.y-r-2*s+5);
  while(1)  /*显示目标闪烁效果,并等待用户按键*/
  {
     if(kbhit())
     {
	    ch=getch();
        if(ch==Enter) return 1;   /*如果按Enter键则开始攻击*/
        if(ch==ESC)   return 0;   /*如果按ESC键则取消此次攻击*/
     }
     DrawTank(Tank[best],DisplayColor,DisplayColor);
     delay(30000);
     DrawTank(Tank[best],Tank[best].color,LockColor);
     delay(30000);
  }
}

/*--------------绘制导弹---------------------------*/
void DrawMissile(int x,int y,int r,int color)
{ 
  int i;
  setcolor(color);
  for(i=0;i<r;i++)
   circle(x,y,i);
}

/*---------------攻击效果-------------------------*/
void Attack(int x1,int y1,int x2,int y2,int color)
{
    int i,size,trackColor,missileR,missileColor=WHITE;
    int x,y;
    void *buf;
    x=x1; 
    y=y1; 
    missileR=5; 
    trackColor=BLUE;
    setcolor(trackColor);
    line(x1,y1,x2,y2);
    if(y1==y2)
    while(x!=x2)
    {
       size=imagesize(x-100,y-missileR,x+100,y+missileR);
       buf=malloc(size);
       getimage(x-100,y-missileR,x+100,y+missileR,buf);
       DrawMissile(x,y,missileR,missileColor);
       delay(3000);
       putimage(x-100,y-missileR,buf,COPY_PUT);
       if(x>x2)
          x--;
       else
          x++;
       free(buf);
    }
    else
    while(y!=y2)
    {
       size=imagesize(x-100,y-missileR,x+100,y+missileR);
       buf=malloc(size);
       getimage(x-100,y-missileR,x+100,y+missileR,buf);
       for(i=-50;i<=50;i++)
	 if(getpixel(x+i,y)==trackColor)
	  {  
         DrawMissile(x+i,y,missileR,missileColor);
	     delay(3000);
	     putimage(x-100,y-missileR,buf,COPY_PUT);
	     x=x+i;
	     break;
	  }
      if(y>y2)
	    y--;
      else
        y++;
       free(buf);
    }
}

/*---------------爆炸效果----------------------------*/
void Blast(int x,int y,int r,int color)
{
  int i,j;
  for(i=0;i<r;i++)
  {
     for(j=0;j<i;j++)
     {
        DrawShineStar(x,y,j,color);
	    delay(3000);
        DrawShineStar(x,y,j,DisplayColor);
     }
     delay(1000);
  }
}

/*------显示目标全部清除-------------------*/
void ShowClear()
{
   int x=150,y=150;
   setfillstyle(1,WHITE);
   bar(x,y,x+5,y+100);
   setcolor(RED);
   line(x,y+5,x,y+45);
   line(x,y+5,x+70,y+45);
   line(x,y+45,x+70,y+45);
   setfillstyle(1,RED);
   floodfill(x+1,y+20,RED);
   settextstyle(0,0,5);
   setcolor(WHITE);
   outtextxy(x+100,y+50,"Clear!");
}

/*----------------动画演示函数--------------------------*/
int Display()
{
  int i,t,x,y;
  int count=0;
  char ch;
  DisplayBG();
Repeat:
  DrawStarBG();
  while(1)
  {
     if(kbhit())  /*如果用户按Enter键则锁定目标*/
     {
        ch=getch();
        if(ch==Enter)
        break;
        if(ch==ESC)
            return 0;
     }
    /*以下是显示星空闪现效果*/
     count++;    /*循环的次数*/
     if((count=count%5)==0)    /*如果循环次数正好是5的倍数,则*/
     {
	if(random(5)==1)       /*如果产生的随机数恰好等于1*/
	    Shine();           /*那么闪烁一次*/
     }
    /*各目标按照预定的当前方向运动*/
     for(i=0;i<n;i++)
     {
        l1:
        x=Tank[i].x;  /*首先保留原目标的坐标而用x,y代替*/
        y=Tank[i].y;
        switch(Tank[i].direction) /*根据当前方向值来试着改变坐标*/
        { 
          /*以下是根据八个方向来改变坐标值*/
           case -1: x--;break;         /*左*/
	       case 1:  x++;break;         /*右*/
	       case -2: y--;break;         /*上*/
	       case 2:  y++;break;         /*下*/
	       case -3: x--; y--;break;    /*左上*/
	       case 3:  x++; y++; break;   /*右下*/
	       case -4: x--; y++;break;    /*左下*/
	       case  4: x++; y--;break;    /*右上*/
	       default: break;
        }
      /*尝试改变后,如果改变后的坐标未超过边界,则在新的坐标处显示该目标,
并擦去原坐标点的目标。同时将改变后的坐标作为该目标的新的当前坐标*/
	if(IsXYValid(Tank[i],x,y))  /*如果坐标合法,则在新的坐标处画该坦克*/
	{
	   DrawTank(Tank[i],DisplayColor,DisplayColor);
	   Tank[i].x=x;
	   Tank[i].y=y;
	   DrawTank(Tank[i],Tank[i].color,GunColor);
	   delay(100);
	}
	else
	{
         /*否则,重新产生一个方向值,并返回根据新的方向值重新尝试改变坐标*/
           t=random(2);
           if(t==0) 
              Tank[i].direction=1+random(4);
           else     
              Tank[i].direction=0-(1+random(4));
           goto l1;
	}
   }
  }
  Arithmetic();  /*调用算法求得当前最优目标*/
  if(Lock(Tank[best])==0)
/*表示用户按了ESC键,则取消此次攻击,返回到多目标动态显示的画面*/
  {
     setfillstyle(1,DisplayColor);
     bar(Tank[best].x-Tank[best].r*4,Tank[best].y-
Tank[best].r*4,Tank[best].x+Tank[best].r*4,Tank[best].y+
Tank[best].r*4);
     DisplayBG();
     for(i=0;i<n;i++)
	DrawTank(Tank[i],Tank[i].color,GunColor);
     goto Repeat;
  }
  Attack(emp.x,emp.y,Tank[best].x,Tank[best].y,TankColor);
/*攻击最优目标*/
  Blast(Tank[best].x,Tank[best].y,Tank[best].r-5,LockColor);  /*爆炸效果*/
  /*以下为重新画界面和剩余的坦克,以显示攻击了最优目标后的效果*/
  setcolor(DisplayColor);
  line(emp.x,emp.y,Tank[best].x,Tank[best].y);
  setfillstyle(1,DisplayColor);
  bar(Tank[best].x-Tank[best].r*4,Tank[best].y-
Tank[best].r*4,Tank[best].x+Tank[best].r*4,Tank[best].y+
Tank[best].r*4);
  DisplayBG();
  for(i=0;i<n;i++)
  {
     if(i==best)
        continue;
     DrawTank(Tank[i],Tank[i].color,GunColor);
  }
  if(n==0)
  {   
     ShowClear();
     getch();
  }
  return 1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -