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

📄 display.c

📁 < c程序员成长攻略>>源代码,一本很好的书,原书全部的代码都有讲解,是c程序员的福星
💻 C
字号:
/*=======================Display.c========================*/
/*=====================动画演示文件======================*/

#include"head.h"
void InitGraph()
{
	int gd=DETECT,gm;
	initgraph(&gd,&gm,"c:\tc\tc");
}

/*--------------画炮台--------------------------------*/
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); /*填充两个矩形框之间的部分*/
	
}

/*--------------将整型转化为字符型--------------------*/
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;
	/*--------画演示矩形框----------*/
	setbkcolor(0);
	setcolor(LIGHTGRAY);
	rect.width=600;
	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);
}

/*----------------在坐标(x,y)处的闪烁效果------------------------------*/
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 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(10000);
			DrawShineStar(x,y,j,DisplayColor);
		}
		delay(1000);
	}
}

/*----------------动画演示函数--------------------------*/
void Display()
{
	int i,t,x,y;
	int count=0;
	char ch;
	DisplayBG();
	DrawStarBG();
	InitTarget();

Repeat:
	while(1)
	{
		if(kbhit())  /*如果用户按Enter键则锁定目标*/
		{
			ch=getch();
			if(ch==Enter)
				break;
		}
		/*以下是显示星空闪现效果*/
		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;
		}
		}
	}
	/*在此添加寻最优目标的算法调用*/
	if(Lock(Tank[best])==0)/*表示用户按了ESC键,则取消此次攻击,返回到多目标动态显示的画面*/
		goto Repeat;
	Attack(emp.x,emp.y,Tank[best].x,Tank[best].y);
	Blast(Tank[best].x,Tank[best].y,Tank[best].r,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);
	}
}

/*---------------主函数-------------------------------*/
main()
{ 
	int i;
	InitGraph();
	Display();
	getch();
}

⌨️ 快捷键说明

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