JAVA模拟堵车情况

jiaotong
  这个问题是帮别人做的一个题目,虽然我压根不会怎么做,但是还是得硬着头皮上,写啊,改啊,数据测试啊,各种问题,反正问题多多吧。最后的结果还是一个很不准确的数字。回想上一次模拟银行业务,这一次更加不靠谱。上一次是完全没有做出来,有可能是上次是C语言的关系吧,这次是java省去了构建队列的问题,反正也没有那么顺利,要让车堵上都不容易。
  看一下,代码,很像零时工的感觉,实际上还称不上零时工。运行结果那个波动叫一个神奇,我自己都不相信这是可能的结果。

import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;

public class Start120 {
    public static void main(String[] args) {

        int i = 50;
        while (i-- > 0) {

            Car.SID = 0;
            Data data = new Data();
            data.getState(240);// 获取车祸发生状态
            while (data.exit(120) == false) {
                data.run();// 执行状态
            }
            data.outTime();
        }
    }

}
class Data {
    LinkedList<Car> lane1 = new LinkedList<>();
    LinkedList<Car> lane2 = new LinkedList<>();
    LinkedList<Car> lane3 = new LinkedList<>();
    Random random = new Random();
    double distance = 0;
    public int runTime = 1000;// 每一秒运行的次数
    public double carMinnuter = 17.6;// 每一分钟出现的车辆数
    double location = 0;// 事故点
    public int count = 0;
    int d_count = -1;// 需要等待前面一辆车通过的时间次数
    int d_lane = 0;// 通行车道
    double d_speed = 1;// 通行速度,默认1
    int count_waiting = -1;// 通行等待时间

    public void addCar() {
        Car car = getCar();
        if (car == null)
            return;
        if (count > 0) {
            // 修改车辆车道
            int n = getMinLane();
            if (n > 0)
                car.lane = n;
        }
        switch (car.lane) {
        case 1:
            lane1.offer(car);
            break;
        case 2:
            lane2.offer(car);
            break;
        case 3:
            lane3.offer(car);
            break;
        }
    }

    private int getMinLane() {
        // 获取堵车最短车道
        return 0;
//      double d1 = 0, d2 = 0, d3 = 0;
//      d1 = getOneLaneDistance(lane1);
//      d2 = getOneLaneDistance(lane2);
//      d3 = getOneLaneDistance(lane3);
//      if(Math.abs(d1 - d2) < 20){
//          if(Math.abs(d1 - d3) < 20 && Math.abs(d2 - d3) < 20)return 0;
//      }
//      if (d1 > d2) {
//          if (d2 < d3)
//              return 2;
//          return 3;
//      } else {
//          if (d1 < d3)
//              return 1;
//          else
//              return 3;
//      }
    }
   
    private double getOneLaneDistance(LinkedList<Car> lane){
        double d = 0;
        Car car;
        for (int i = 0; i < lane.size(); i++) {
            car = lane.get(i);
            if (car.speed == 0)
                d = location - car.location + car.length;
        }
        return d;
    }

    public double outTime() {
        double n = (double) count / runTime;
        System.out.println("RunTime:" + n / 60);
        return n;
    }

    public void run() {
        ++count;
        if (d_count != -1) {
            --d_count;
        }
        addCar();// 获取一辆车
        UpCarLine(lane3);
        UpCarLine(lane2);
        UpCarLine(lane1);
        if (d_count == -1) {
            setPassLane();
        }
        getStopDistance();
    }

    private void setPassLane() {
        // 设置通行的线路
        Car c1, c2, c3;
        c1 = getFirstCar(lane1);
        c2 = getFirstCar(lane2);
        c3 = getFirstCar(lane3);
        if (c1 == null && c2 == null && c3 == null)
            return;
        if (c1 != null) {
            if (c2 == null)
                c2 = c1;
            if (c3 == null)
                c3 = c1;
        } else {
            if (c2 != null) {
                c1 = c2;
                if (c3 == null)
                    c3 = c2;
            } else if (c3 != null) {
                c1 = c3;
                c2 = c3;
            }
        }

        if (c1.spacing < c2.spacing) {
            if (c1.spacing < c3.spacing) {
                setPass(c1);
            } else {
                setPass(c3);
            }
        } else {
            if (c2.spacing < c3.spacing) {
                setPass(c2);
            } else {
                setPass(c3);
            }
        }
    }

    private void setPass(Car car) {
        // 设置堵车时通过的车道
        d_lane = car.lane;
        d_speed = 2;// 计算通行速度
        d_count = (int) ((location + car.length - car.location) / d_speed)
                * runTime;
    }

    private void UpCarLine(LinkedList<Car> lane) {
        // 更新一条堵车道速度
        Car last = null, now = null;
        double n = 0;
        for (int i = 0; i < lane.size(); i++) {
            now = lane.get(i);
            if (now.speed > 0) {
                // 非在堵车辆,即后排车辆
                if (last != null) {
                    n = location - distance - now.location;
                    if (n < now.spacing) {
                        now.speed = 0;
                    } else if (n < 50) {
                        now.speed = 1;
                    } else if (n < 100) {
                        now.speed = 1.8;
                    } else if (n < 150) {
                        now.speed = 3;
                    }
                    if (last.location - last.length - now.location < now.speed
                            / (double) runTime + now.spacing) {
                        now.speed = last.speed;
                        now.location = last.location + now.spacing;
                    } else {
                        now.location += now.speed / (double) runTime;
                    }
                    if (now.location + now.spacing > location) {
                        now.speed = 0;
                    }
                } else {
                    // 第一辆车且速度大于0,判断那一辆车应该通过
                    if (d_count == -1 && now.lane == 3
                            && now.location > location) {
                        setPass(now);// 设置要通过的车辆信息
                    }
                    now.location += now.speed / (double) runTime;
                }
            } else {
                // 在堵车辆
                if (now.lane == d_lane) {
                    now.location += d_speed / (double) runTime;
                }
            }
            last = now;
        }
    }

    private double getStopDistance() {
        // 获取堵车距离
        double d1 = 0, d2 = 0, d3 = 0;
        d1 = getOneLaneDistance(lane1);
        d2 = getOneLaneDistance(lane2);
        d3 = getOneLaneDistance(lane3);
        distance = Math.max(d1, Math.max(d2, d3));
        return distance;
    }

    public boolean exit(double distance) {
        if (this.distance > 0 && count % 1000 == 0) {
            // System.out.println("Distance:" + this.distance);
        }
        return distance < this.distance;
    }

    private void SetStateUpdate() {
        // 设置状态时候的更新
        SetStateUpdate(lane1);
        SetStateUpdate(lane2);
        SetStateUpdate(lane3);
    }

    private void SetStateUpdate(LinkedList<Car> lane) {
        // 更新某一条线路的状态
        Car last = null, now = null;
        for (int i = 0; i < lane.size(); i++) {
            now = lane.get(i);
            if (last != null
                    && (last.location - last.length - now.location) < (now.speed
                            / (double) runTime + now.spacing)) {
                now.speed = last.speed;
                now.location = last.location + now.spacing;
            } else {
                now.location += now.speed / (double) runTime;
            }
            last = now;
        }
        Car car = lane.peek();
        if (car != null && car.location > location)
            lane.poll();
    }

    private void Stoping() {
        // 开始进行事故之后的减速
        StopingSet(lane1);
        StopingSet(lane2);
        StopingSet(lane3);
    }

    private void StopingSet(LinkedList<Car> lane) {
        // 设置出事后线路车速
        Car car;
        double n = 0;
        for (int i = 0; i < lane.size(); i++) {
            car = lane.get(i);
            n = location - car.location;
            if (n < car.spacing) {
                car.speed = 0;
            } else if (n < 50) {
                car.speed = 2;
            } else if (n < 100) {
                car.speed /= 3;
            } else if (n < 150) {
                car.speed /= 1.5;
            }
        }
    }

    public void getState(double location) {
        // 获取出事状态
        this.location = location;
        while (carCollide() == false) {
            addCar();
            SetStateUpdate();
        }
        // System.out.println(lane1.poll());
        // System.out.println(lane2.poll());
        Stoping();
    }

    private Car getCar() {
        // 获取一辆车,没有返回null
        int r = random.nextInt(60 * runTime);
        if (r < carMinnuter
                && (count == -1 || !isRedLight() || isTurnRightCar()))
            return new Car();
        return null;
    }

    private boolean isRedLight() {
        // 判断是否为红绿灯
        int n = count / runTime % 60;
        if (n < 27)
            return false;
        return true;
    }

    private boolean isTurnRightCar() {
        // 判断右转过来的车
        int r = random.nextInt(60 * runTime);
        if (r < carMinnuter * 0.21) {
            return true;
        }
        return false;
    }

    private boolean carCollide() {
        // 判断车是否有相撞
        Car car1 = getFirstCar(lane1);
        Car car2 = getFirstCar(lane2);
        if (car1 == null || car2 == null
                || Math.abs(car1.location - location) > 0.5)
            return false;
        return Math.abs(car1.location - car2.location) < 1;
    }

    private Car getFirstCar(Queue<Car> lane) {
        // 获取第一辆车
        return lane.peek();
    }
}
class Car {
    public double length;// 车长
    public double speed;// 车速m/s
    public int lane;// 车道
    public double spacing;// 前面车间距
    public double location;
    private double[] len_arr = { 4, 7, 9 };// 车长度数组
    private double[] speed_arr = { 13, 11, 9 };
    private int leng_rand = 0;
    private Random random = new Random();
    static int SID = 0;
    public int id = 0;

    public Car() {
        length = rand_length();
        speed = rand_speed();
        lane = rand_lane();
        spacing = rand_spacing();
        location = 0;
        id = ++SID;
    }

    public String toString() {
        return "Lane:" + lane + ", ID:" + id + ", Length:" + length
                + ", location:" + location + ", spacing:" + spacing + ",speed:"
                + speed;
    }

    private double rand_spacing() {
        return random.nextDouble() / 2 + 0.5;
    }

    private double rand_speed() {
        // 根据车长获取不同的车速
        double r = random.nextDouble();
        return speed_arr[leng_rand] * (r + 0.5);
    }

    private int rand_lane() {
        // 1车道为内车道
        // 车道比例35,44,21
        int r = random.nextInt(100);
        if (r < 35)
            return 1;
        if (r < 79)
            return 2;
        return 3;
    }

    private double rand_length() {
        // weight 229 2 10
        int r = random.nextInt(241);

        if (r < 229) {
            leng_rand = 0;
            return len_arr[0];
        }
        if (r < 231) {
            leng_rand = 1;
            return len_arr[1];
        }
        leng_rand = 2;
        return len_arr[2];
    }
}

在来段运行结果:

RunTime:9.520983333333334
RunTime:13.563916666666668
RunTime:7.457316666666667
RunTime:10.62815
RunTime:17.374633333333335
RunTime:9.623
RunTime:7.438633333333333
RunTime:8.292533333333333
RunTime:7.6368
RunTime:12.537633333333334
RunTime:7.449816666666666
RunTime:7.528416666666667
RunTime:9.586233333333332
RunTime:11.7128
RunTime:10.59445
RunTime:7.732583333333333
RunTime:10.59975
RunTime:8.428533333333332
RunTime:10.436633333333333
RunTime:14.574283333333334
RunTime:11.3939
RunTime:10.549483333333335
RunTime:8.381733333333333
RunTime:8.5556
RunTime:8.67445
RunTime:9.6765
RunTime:10.2606
RunTime:11.406849999999999
RunTime:11.507233333333334
RunTime:10.420133333333332
RunTime:10.442716666666666
RunTime:7.657033333333334
RunTime:9.650749999999999
RunTime:11.352883333333333
RunTime:11.5995
RunTime:10.296349999999999
RunTime:7.401750000000001
RunTime:11.341283333333333
RunTime:9.291133333333333
RunTime:8.535
RunTime:8.556783333333334
RunTime:13.445616666666666
RunTime:11.4889
RunTime:10.424766666666667
RunTime:13.704316666666667
RunTime:12.603533333333333
RunTime:13.289116666666667
RunTime:9.544466666666667
RunTime:7.360133333333334
RunTime:11.62355

2条评论在“JAVA模拟堵车情况”

回复 恋羽   取消