黑马程序员_交通灯管理系统

来源:互联网 发布:pad不能更新软件 编辑:程序博客网 时间:2024/06/05 06:45
------- android培训、java培训、期待与您交流! ----------

一、项目需求

模拟实现十字路口的交通管理系统逻辑,具体需求如下:

1)、异步随机生成按照各个路线行驶的车辆。如:

由南向而来去往北向的车辆---->直行车辆

由西向而来去往南向的车辆---->右行车辆

由东向而来去往南向的车辆---->左行车辆

......

2)、信号灯忽略黄灯,只考虑红灯和绿灯;

3)、只需考虑左转车辆控制信号灯,右转车辆控制信号不需考虑;

4)、具体信号控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑;

        注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放直行车辆,而后方左转车辆。

5)、每辆车通过路口时间为1s(提示:可通过线程sleep方式模拟);

6)、随机生成车辆时间间隔以及红绿灯交换时间间隔;

7)、不考虑实现GUI,只考虑系统逻辑实现,可通过log方式展现程序运行结果。

二、交通灯模型分析

1)、交通灯模拟图


注:S2N:表示由南向北去的车辆,2是to的意思。其他依次相同。

通过对交通图的分析知:该十字路口共有12条路线。我们这里以南为起点参考方向,这十二条路线分别为:S2N, S2W, E2W, E2S, N2S, N2E, W2E, W2N, S2E, E2N, N2W, W2S。 

 再进一步联系实际分析,我们可以知道该线路可以进一步优化减少考虑一部分线路。在这里,我们以东南为参考方向,当车辆由南向西行驶时,由西往南的车辆同样在直行,互补干扰。当车辆由南向西行驶时,在由北向东行驶的车辆也同样不受干扰。同理,车辆由东向西行驶是,由西向东行驶的车辆不受干扰;由东向南行驶时,由西向北的车辆也不受干扰。由于我国交通向右行驶时不受交通灯影响,所以由南向东,由东向北,由北向西,由西向南的都不用考虑。综上分析,我们重点考虑的只有四条线路,即:S2N, S2W, E2W, E2S。在现实生活中向右行驶没有灯,但在模型中我们假设向右行驶都有灯,这灯是常亮的,所以就可以统一模型了。

2)、模型分析

通过分析,我们知道该系统中有3个对象:车,路,灯。再通过具体分析,我们并不需要体现车移动的过程,只是捕捉车辆穿过路口的过程,也就是捕捉路上减少一辆车的过程,所以车就不需要单独设计成为一个对象,用一个字符串表示就可以。但是灯还需要一个控制器控制它,所以我们还得创建一个灯控制器对象。所以总共就需要设计三个对象:路,路灯,路灯控制器。

注:面向对象设计把握一个重要的经验:谁拥有数据,谁就对外提供操作这些数据的方法。

3)、分析并创建对象

A、Road类

设计一个Road类来表示路线。该路线上创建一个集合,通过集合来存储路上的车辆,并且每隔一段时间就来一辆车,来一辆车就往集合里面存储。路还要每隔一秒中检查一下控制该路线的灯是否为绿灯,如果是绿灯,则将集合中的第一辆车移除,即表示该辆车穿过了路口。所以还要创建一个定时器来记录时间。

代码体现:

package com.itheima.traffic;import java.util.ArrayList;import java.util.List;import java.util.Random;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class Road {/*使用List集合时为了面向对象编程*/List<String> vechicles = new ArrayList<String>();private String name = null;public Road(String name){this.name = name;//使用一个线程池来控制进入车辆的时间;ExecutorService pool = Executors.newSingleThreadExecutor();pool.execute(new Runnable(){public void run() {for(int i=1; i<1000; i++){try {Thread.sleep((new Random().nextInt(10)+1)*1000);} catch (InterruptedException e) {e.printStackTrace();}vechicles.add(Road.this.name+"_"+i);}}});//定义定时器来监控灯的状态并做处理;ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);timer.scheduleAtFixedRate(new Runnable(){public void run() {if(vechicles.size()>0){boolean lighted = Lamp.valueOf(Road.this.name).islighted();if(lighted){System.out.println(vechicles.remove(0) + " is traversing!!!");//此处的remove是将集合中的车辆移除,remove返回的是移除的那个元素;}}}}, 1, 1, TimeUnit.SECONDS);}}

B、Lamp类

由于该系统涉及到12个路灯,所有我们可以采用枚举方法列举出每个灯的状态。该类中需要定义一个变量来表示灯的状态,还需要定义该灯与之对应灯和下一个灯。还需要定义方法记录各灯的状态。当参考灯为绿时,与之对应的灯也的是绿色,而它的下一个灯则为红灯(注意:参考灯有与之对应的灯,则与参考灯对应的灯就不存在对应的灯了);增加让Lamp变亮和变黑的方法:lightblackOut对于S2NS2WE2WE2N这四个方向上的Lamp对象,,这两个方法内部要让相反方向的灯随之变亮和变黑,blackOut方法还要让下一个灯变亮。

代码体现:

package com.itheima.traffic;public enum Lamp {S2N("N2S","S2W",false), S2W("N2E","E2W",false), E2W("W2E","E2S",false), E2S("W2N","S2N",false),N2S(null,null,false),   N2E(null,null,false),   W2E(null,null,false),   W2N(null,null,false),S2E(null,null,true),    E2N(null,null,true),    N2W(null,null,true),    W2S(null,null,true);private Lamp(String opposite,String next, boolean lighted){this.opposite = opposite;this.next = next;this.lighted = lighted;}private Boolean lighted ;private String opposite;//此处的opposite用字符串表示可以避免上面使用与参考灯对应的灯对象时,出现先定义后使用时的错误情况;private String next;public Boolean islighted(){return lighted;}public void light(){this.lighted = true;if(opposite != null){//如果该灯有与之对应的灯,则与之对应的灯也将变亮;此处如果不做判断则会出现死循环;Lamp.valueOf(opposite).light();//valueOf方法可以返回名字为opposite的对象;}System.out.println(name()+" lamp is green,下面共有6个方向可以看到汽车穿过!");}public Lamp blackOut(){this.lighted = false;if(opposite != null){Lamp.valueOf(opposite).blackOut();}Lamp nextLamp = null;if(next != null){nextLamp =Lamp.valueOf(next);System.out.println("绿灯将从 " + name() + " 切换到-----> " + next);nextLamp.light();}return nextLamp;}}

C、LampController类

该类中需要定义一个当前的灯,我们假设E2N的灯为当前灯。当灯控制器对象一创建时就有当前灯,并设定其状态为绿灯,让后定义一个定时器,每隔10s就当前灯变红,则下一个灯变绿。

代码体现:

package com.itheima.traffic;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class LampController {private Lamp currentLamp;public LampController(){currentLamp = Lamp.S2N;currentLamp.light();ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);timer.scheduleAtFixedRate(new Runnable(){public void run() {currentLamp = currentLamp.blackOut();}}, 10, 10, TimeUnit.SECONDS);}}



D、MainClass测试类

该类中我们需要创建12条线路的12个对象,所以可以选用数组遍历的方法来翻遍创建,然后调用LampController对象使系统运行起来;

代码体现:

package com.itheima.traffic;public class MainClass {/** * @param args */public static void main(String[] args) {String[] directions = new String[]{"S2N","S2W", "E2W", "E2S", "N2S", "N2E", "W2E", "W2N", "S2E", "E2N", "N2W", "W2S"};for(int i=0; i<directions.length; i++){new Road(directions[i]);}new LampController();}}


------- android培训、java培训、期待与您交流! ----------
0 0
原创粉丝点击