小球在矩形框内45°碰撞问题

问题描述:

在一个矩形框内长w, 高h,现在在底边某一点举例左端点x位置处有一弹性小球(可视为质点)向右上方45°发射,碰撞忽略能量损耗,继续45°弹出,输出在前n次碰撞到底边时每次碰撞的位置。

这里写图片描述

首先说一种比较繁琐的思路:

碰撞本身是一个过程,我们只需要将所有的可能性考虑到位就好,首先,我们定义如下几个变量用来确定当前的状态:

  1. pos 表示当前的位置在哪条边上,我们默认从顶上顺时针分别为1, 2, 3, 4

  2. s1, s2, h1, h2:分别用来表示在横和竖的四条边上的位置,默认以左端点或下端点为0, 左边的竖线代表s1,右边的竖线代表s2,上边的横线为h1, 下边的为h2

  3. direction:用来表示当前的方向,逆时针碰撞还是顺时针碰撞

然后我们就能根据题意确定初始状态:

direction = -1;
pos = 3;
h2 = x;

解决代码如下:

    static void ball(int w, int h, int x, int n){
        int s1, s2, h1, h2;
        s1 = s2 = h1 = h2 = 0;
        int direction = -1;
        int pos = 3;
        int count = 0;
        h2 = x;
        //要求输出前n次碰撞到底边的位置
        while(count != n + 1){
            //逆时针
            if(direction == -1){
                //判断当前位置
                if(pos == 1){
                    //判断是否超越临边的长度
                    if(h1 > h){
                        //确定下次的位置(包括在哪条边上,距离端点的位置长度以及下次碰撞的方向)
                        pos = 3;
                        h2 = h1 - h;
                        direction = 1;
                        continue;
                    }else{
                        pos = 4;
                        direction = -1;
                        s1 = h - h1;
                        continue;
                    }

                }else if(pos == 2){
                    if(h - s2 > w){
                        pos = 4;
                        direction = 1;
                        s1 = s2 + w;
                        continue;
                    }else{
                        pos = 1;
                        h1 = w - (h - s2);
                        direction = -1;
                        continue;
                    }
                }else if(pos == 3){
                    count ++;
                    if(count != 1){
                        System.out.printf("%d ", h2);
                    }
                    if(w - h2 > h){
                        h1 = h2 + h;
                        pos = 1;
                        direction = 1;
                        continue;
                    }else{
                        s2 = w - h2;
                        pos = 2;
                        direction = -1;
                        continue;
                    }
                }else{
                    if(s1 > w){
                        pos = 2;
                        s2 = s1 - w;
                        direction = 1;
                        continue;
                    }else{
                        pos = 3;
                        h2 = s1;
                        direction = -1;
                        continue;
                    }
                }
            }else{
                //顺时针
                if(pos == 1){
                    if(w - h1 > h){
                        pos = 3;
                        h2 = h1 + h;
                        direction = -1;
                        continue;
                    }else{
                        pos = 2;
                        s2 = h - (w - h1);
                        direction = 1;
                        continue;
                    }
                }else if(pos == 2){
                    if(s2 > w){
                        s1 = s2 - w;
                        pos = 4;
                        direction = -1;
                        continue;
                    }else{
                        pos = 3;
                        h2 = w - s2;
                        direction = 1;
                        continue;
                    }
                }else if(pos == 3){
                    //当在底边时要考虑输出
                    count ++;
                    //初始位置不计数
                    if(count != 1){
                        System.out.printf("%d ", h2);
                    }
                    if(h2 > h){
                        pos = 1;
                        direction = -1;
                        h1 = h2 - h;
                        continue;
                    }else{
                        pos = 4;
                        direction = 1;
                        s1 = h2;
                        continue;
                    }
                }else{
                    if((h -h1) >  w){
                        pos = 2;
                        direction = -1;
                        s2 = h - h1 - w;
                        continue;
                    }else{
                        pos = 1;
                        direction = 1;
                        h1 = h - s1;
                        continue;
                    }
                }
            }
        }
    }

还有一种比较有技巧的做法,通过题意我们了解到碰撞是45°的,所以三角形—>等腰,我们能想到每次碰撞回到底边时,竖直方向的位移距离等于水平方向的位移距离(无论是否是碰撞到临边还是对边,无论是顺时针碰撞还是逆时针碰撞),所以我们可以根据这个结论得出:当竖直方向运动2×h距离时就会回到底边,并且底边的位移距离也等于2×h,所以到现在我们就将问题转换到了在底边运动2×h后的位置,我们要考虑到到达两端点后的反向问题。

也就是说我们要在底边滑动2×h后输出当前位置,解决代码如下:

    static void ball2(int w, int h, int x, int n){
        //记录当前位置
        int pos = x;
        //记录当前移动的方向
        char flag = 'r';
        //每次需要移动2 × h的距离
        int temp = 2 * h;
        //nwhile(n-- != 0){
            temp = 2 * h;
            while(temp != 0){
                if(flag == 'l'){
                    if(temp > pos){
                        temp -= pos;
                        pos = 0;
                        flag = 'r';
                        continue;
                    }else{
                        pos -= temp;
                        System.out.printf("%d ", pos);
                        break;
                    }
                }else{
                    if(temp > w - pos){
                        temp -= (w - pos);
                        pos = w;
                        flag = 'l';
                        continue;
                    }else{
                        pos += temp;
                        System.out.printf("%d ", pos);
                        break;
                    }
                }
            }
        }
    }

========================
两种方法及测试代码汇总如下:

import java.util.Scanner;

/**
 * Created by zhuxinquan on 17-3-9.
 * 一个矩形内从底边一点开始斜向上45°发出一个小球(直径忽略),然后反弹
 * 求在n次碰撞到底边时每次的位置
 */

public class Crash{

    static void ball2(int w, int h, int x, int n){
        int pos = x;
        char flag = 'r';
        int temp = 2 * h;
        while(n-- != 0){
            temp = 2 * h;
            while(temp != 0){
                if(flag == 'l'){
                    if(temp > pos){
                        temp -= pos;
                        pos = 0;
                        flag = 'r';
                        continue;
                    }else{
                        pos -= temp;
                        System.out.printf("%d ", pos);
                        break;
                    }
                }else{
                    if(temp > w - pos){
                        temp -= (w - pos);
                        pos = w;
                        flag = 'l';
                        continue;
                    }else{
                        pos += temp;
                        System.out.printf("%d ", pos);
                        break;
                    }
                }
            }
        }
    }

    static void ball(int w, int h, int x, int n){
        int s1, s2, h1, h2;
        s1 = s2 = h1 = h2 = 0;
        int direction = -1;
        int pos = 3;
        int count = 0;
        h2 = x;
        while(count != n + 1){
            //逆时针
            if(direction == -1){
                if(pos == 1){
                    if(h1 > h){
                        pos = 3;
                        h2 = h1 - h;
                        direction = 1;
                        continue;
                    }else{
                        pos = 4;
                        direction = -1;
                        s1 = h - h1;
                        continue;
                    }

                }else if(pos == 2){
                    if(h - s2 > w){
                        pos = 4;
                        direction = 1;
                        s1 = s2 + w;
                        continue;
                    }else{
                        pos = 1;
                        h1 = w - (h - s2);
                        direction = -1;
                        continue;
                    }
                }else if(pos == 3){
                    count ++;
                    if(count != 1){
                        System.out.printf("%d ", h2);
                    }
                    if(w - h2 > h){
                        h1 = h2 + h;
                        pos = 1;
                        direction = 1;
                        continue;
                    }else{
                        s2 = w - h2;
                        pos = 2;
                        direction = -1;
                        continue;
                    }
                }else{
                    if(s1 > w){
                        pos = 2;
                        s2 = s1 - w;
                        direction = 1;
                        continue;
                    }else{
                        pos = 3;
                        h2 = s1;
                        direction = -1;
                        continue;
                    }
                }
            }else{
                //顺时针
                if(pos == 1){
                    if(w - h1 > h){
                        pos = 3;
                        h2 = h1 + h;
                        direction = -1;
                        continue;
                    }else{
                        pos = 2;
                        s2 = h - (w - h1);
                        direction = 1;
                        continue;
                    }
                }else if(pos == 2){
                    if(s2 > w){
                        s1 = s2 - w;
                        pos = 4;
                        direction = -1;
                        continue;
                    }else{
                        pos = 3;
                        h2 = w - s2;
                        direction = 1;
                        continue;
                    }
                }else if(pos == 3){
                    count ++;
                    if(count != 1){
                        System.out.printf("%d ", h2);
                    }
                    if(h2 > h){
                        pos = 1;
                        direction = -1;
                        h1 = h2 - h;
                        continue;
                    }else{
                        pos = 4;
                        direction = 1;
                        s1 = h2;
                        continue;
                    }
                }else{
                    if((h -h1) >  w){
                        pos = 2;
                        direction = -1;
                        s2 = h - h1 - w;
                        continue;
                    }else{
                        pos = 1;
                        direction = 1;
                        h1 = h - s1;
                        continue;
                    }
                }
            }
        }
    }

    public static void main(String[] args){
        int w, h, x, n;
        Scanner in = new Scanner(System.in);
        w = in.nextInt();
        h = in.nextInt();
        x = in.nextInt();
        n = in.nextInt();
        ball2(w, h, x, n);
    }
}

猜你喜欢

转载自blog.csdn.net/zhuxinquan61/article/details/61194440