解题思路:
简单来说,球的起步可以分成8个大方向,分别为0°、0°-90°、90°、90°-180°、180°、180°-270°、270°、270°-360°;先说水平和竖直方向,球的运动轨迹单一,只是横向或竖向移动,碰壁返回,只会在一个方向上产生分速度;而其余4种情况球的运动轨迹相对复杂些,每种情况均会产生两种方式的碰撞反弹,比如a<90°时,可能会先在右侧碰壁往左上反弹,又或者可能先在上壁碰撞往右下反弹,每种情况只需确定好反射角就好;而产生碰撞的时候有一个方向的坐标便可以确定下来,从而顺藤摸瓜求出路径以及另一个坐标。如此反复直至v*s=0结束。
注意事项:
三角函数sin,cos,tan参数为弧度制的度数。
如果要用到pi,精度要写高点。
弧度=角度*pi/180。
参考代码:
//问题 1075: 台球碰撞
#include<stdio.h>
#include<math.h>
int main()
{
//const double pi=3.141592653; //定义pi的值
double L,W,x,xx,y,yy,R,a,v,vv,s,aa; //xx,yy,vv,表示碰壁前各个方向的分路程。
scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&L,&W,&x,&y,&R,&a,&v,&s);
while(L!=0||W!=0||x!=0||y!=0||R!=0||a!=0||v!=0||s!=0)
{
for(v=v*s;v>0;)
{
if(0<a&&a<90)
{
aa = a*asin(1)*2/180; //度数转化成弧度制的角度
yy=v*sin(aa);
xx=v*cos(aa);
if((yy+y+R>=W)||(xx+x+R>=L))
{
if(yy+y+R>=W) //碰上边
{
yy=W-R-y;
y=W-R;
xx=yy/tan(aa);
x+=xx;
v-=yy/sin(aa);
a=360-a;
}
else //碰右边
{
xx=L-R-x;
x=L-R;
yy=xx*tan(aa);
y+=yy;
v-=yy/sin(aa);
a=180-a;
}
}
else
{
y+=yy;
x+=xx;
v-=v;
}
}
else if(a==90)
{
if(v+y+R>=W)
{
v-=W-y-R;
a=270;
y=W-R;
}
else
{
y+=v;
v-=v;
}
}
else if(90<a&&a<180)
{
aa = a*asin(1)*2/180;
yy=v*sin(aa);
xx=-v*cos(aa);
if((yy+y+R>=W)||(x-R-xx<=0))
{
if(yy+y+R>=W) //碰上边
{
aa = (180-a)*asin(1)*2/180;
yy=W-R-y;
y=W-R;
xx=yy/tan(aa);
x-=xx;
v-=yy/sin(aa);
a=360-a;
}
else //碰左边
{
aa = (180-a)*asin(1)*2/180;
xx=x-R;
x=R;
yy=xx*tan(aa);
y+=yy;
v-=yy/sin(aa);
a=180-a;
}
}
else
{
y+=yy;
x-=xx;
v-=v;
}
}
else if(a==180)
{
if(x-v<=R)
{
v-=x-R;
a=0;
x=R;
}
else
{
x-=v;
v-=v;
}
}
else if(180<a&&a<270)
{
aa = a*asin(1)*2/180;
yy=-v*sin(aa);
xx=-v*cos(aa);
if((y-R-yy<=0)||(x-R-xx<=0))
{
if(y-R-yy<=0) //碰下边
{
aa = (a-180)*asin(1)*2/180;
yy=y-R;
y=R;
xx=yy/tan(aa);
x-=xx;
v-=yy/sin(aa);
a=360-a;
}
else //碰左边
{
aa = (a-180)*asin(1)*2/180;
xx=x-R;
x=R;
yy=xx*tan(aa);
y-=yy;
v-=xx/cos(aa);
a=540-a;
}
}
else
{
y-=yy;
x-=xx;
v-=v;
}
}
else if(a==270)
{
if(y-v<=R)
{
v-=y-R;
a=90;
y=R;
}
else
{
y-=v;
v-=v;
}
}
else if(270<a&&a<360)
{
aa = a*asin(1)*2/180;
yy=-v*sin(aa);
xx=v*cos(aa);
if((y-R-yy<=0)||(x+R+xx>=L))
{
if(y-R-yy<=0) //碰下边
{
aa = (360-a)*asin(1)*2/180;
yy=y-R;
y=R;
xx=yy/tan(aa);
x+=xx;
v-=yy/sin(aa);
a=360-a;
}
else //碰右边
{
aa = (360-a)*asin(1)*2/180;
xx=L-R-x;
x=L-R;
yy=xx*tan(aa);
y-=yy;
v-=yy/sin(aa);
a=540-a;
}
}
else
{
y-=yy;
x+=xx;
v-=v;
}
}
else //0°
{
if(v+x+R>=L)
{
v-=L-x-R;
a=180;
x=L-R;
}
else
{
x+=v;
v-=v;
}
}
}
printf("%.2lf %.2lf\n",x,y);
scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&L,&W,&x,&y,&R,&a,&v,&s);
}
return 0;
}
0.0分
0 人评分
简单的for循环浏览:1498 |
C语言程序设计教程(第三版)课后习题1.5 (C语言代码)浏览:593 |
C语言考试练习题_保留字母 (C语言代码)浏览:743 |
C语言程序设计教程(第三版)课后习题9.2 (C语言代码)浏览:573 |
用筛法求之N内的素数。 (C语言代码)浏览:711 |
Minesweeper (C语言描述,蓝桥杯)浏览:1177 |
C语言程序设计教程(第三版)课后习题5.6 (C语言代码)浏览:594 |
陈教主的三角形 (C语言代码)浏览:1196 |
简单的事情 (C语言代码)浏览:679 |
C语言程序设计教程(第三版)课后习题8.3 (C语言代码)浏览:465 |