---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------
1. 项目需求:
模拟实现十字路口的交通灯管理系统逻辑:
a) 路线方面:
异步随机生成按照各个路线行驶的车辆。例如:
由南向而来去往北向的车辆----直行车辆
由西向而来去往南向的车辆----右转车辆
由东向而来去往南向的车辆----左转车辆
b) 信号灯方面:
信号灯忽略黄灯,只考虑红灯和绿灯。
应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
c) 每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
d) 随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
e) 不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
2. 需求分析之路线方面:
设计一个Road类来表示路线,把路线的方向(name)作为Road类中的一个属性,用于表示路线的名称,在创建Road对象时对该属性赋初值。由于每个路口对应三条路线(直行,左转,右转),所以共有12条路线,如图:
在Road类中定义一个ArrayList集合(vehicles),用于存储该路线上的车辆。为了保证路线创建时该路线上即有车辆,所以集合元素的添加放置在构造方法中。
路线上车辆的增加:由于车辆增加的行为贯穿在整个程序运行期,所以应当为每条路线上车辆的增加分别单独开辟一个线程,且要使用循环结构(张老师视频中用了for循环,循环次数为1000,不过采用while循环似乎更合适,否则若程序执行时间足够长的话,路线上将不会有车辆增加,这与实际情况不符。本篇内采用while循环结构);又由于路线上车辆的增加是随机的,所以需要用到随机数方法,
路线上车辆通过路口:若本路线的路灯为绿,则车辆穿过路口,就把本路线ArrayList集合中的第一个元素(靠近路口的第一辆车)移除。因此Road类中还要定义一个定时器,用于经常性地检查控制本路线的灯是否为绿,检测频率设置为1秒。该定时器的创建同样要定义在构造方法中,以保证路线一旦被创建,定时器就开始执行;
具体代码示例如下:
importjava.util.*;
importjava.util.concurrent.*;
public classRoad {
private List<String> vechicles =new ArrayList<String>(); //用于存储路线上的车辆;
private String name =null; // name为路线的名字;
public Road(String name){
this.name = name;
//创建一个线程用于为路线随机地增加车辆;
ExecutorService pool =Executors.newSingleThreadExecutor();
pool.execute(new Runnable(){
public void run(){
int vech_num=1;
while(true){
try {
Thread.sleep((newRandom().nextInt(10) + 1) * 1000);
} catch(InterruptedException e) {
e.printStackTrace();
}
vechicles.add(Road.this.name+ "_" + vech_num);
}
}
});
//创建定时器,每隔一秒检查对应的灯是否为绿,是的话就放行一辆车;
ScheduledExecutorService timer= Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
public voidrun(){
if(vechicles.size()>0){
booleanlighted = Lamp.valueOf(Road.this.name).isLighted();
if(lighted){
System.out.println(vechicles.remove(0)+ " is traversing !");
}
}
}
},
1,
1,
TimeUnit.SECONDS);
}
}
3. 需求分析之交通灯方面:
创建一个Lamp类用于表示交通灯,每个交通灯控制一条路线,所以共有12个交通灯对象。这12个交通灯对象从大的方面分为两组:
第一组:共有八个,分别用于控制直行方向和左转方向,这些灯要进行变红和变绿的交替;这八个路灯分别用S2N, S2W, E2W, E2S, N2S,N2E, W2E, W2N表示。
第二组:共有四个,控制右转方向,灯常绿,不需变红;这四个路灯分别用 S2E,E2N,N2W,W2S表示。
第一组中八个交通台并不是相互独立的,它们两两之间存在联动关系,例如:由北向南(N2S)和由南向北(S2N)的交通灯的状态始终保持一致;所以这一组又可分为两组:把其中一组交通灯的状态视为由另外一组决定。这两组交通灯分别标记为:S2N, S2W, E2W, E2S 和 N2S, N2E, W2E, W2N。
交通灯的变红和变绿是有顺序的,比如S2N变红后,S2W变绿;S2W变红后,E2W变绿;E2W变红后,E2S变绿;E2S变红后,S2N变绿。
综上分析:Lamp类共有12个实例对象,故采用枚举的方式定义Lamp。由于交通灯可变红和变绿,故Lamp中用一个boolean型的属性lighted表示红和绿的两种状态;由于第二组的八个交通灯中存在两两联动,故Lamp中用oppsite 属性表示与某一交通灯联动的交通灯;由于交通灯的变红具有顺序,故Lamp中用next属性表示一个交通灯变红后下一个要变绿的交通灯。
由于路线要检测控制它的灯的状态,故Lamp中定义一个方法isLighted()用于返回相应交通灯的状态;同时,Lamp中还需定义两个方法light() 和 blackOut() 分别用于使交通灯变绿和变红;
代码示例如下:
public enumLamp {
S2N("N2S","S2W",false),S2W("N2E","E2W",false),E2W("W2E","E2S",false),E2S("W2N","S2N",false),
/*下面表示与上面相反方向的灯,它们的“相反方向灯”和“下一个灯用null表示*/
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,Stringnext,boolean lighted){
this.opposite = opposite;
this.next = next;
this.lighted = lighted;
}
private boolean lighted; //用于表示等的红绿状态;
private String opposite; //与当前灯同时为绿的对应方向;
private String next; //下一个要变绿的灯;
public boolean isLighted(){
return lighted;
}
public void light(){ //用于使灯变绿的方法;
this.lighted = true;
if(opposite != null){
Lamp.valueOf(opposite).light();
}
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;
}
}
4. 需求分析之交通灯控制系统和main方法:
交通灯控制系统用于控制交通灯变化的时间间隔,使当前为绿的交通灯变红,并使下一个交通灯变绿。所以它的构造方法中需要定义一个定时器,定时器中采用每个10s使交通灯按顺序进行变化;
代码示例如下:
importjava.util.concurrent.Executors;
importjava.util.concurrent.ScheduledExecutorService;
importjava.util.concurrent.TimeUnit;
public classLampController {
private Lamp currentLamp;
public LampController(){
//刚开始让由南向北的灯变绿;
currentLamp = Lamp.S2N;
currentLamp.light();
/*定义定时器,每隔10秒使当前绿灯变为红灯,并让下一个方向的灯变绿*/
ScheduledExecutorService timer= Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
public void run(){
currentLamp= currentLamp.blackOut();
}
},
10,
10,
TimeUnit.SECONDS);
}
}
main方法非常简单,首先创建12个Road示例对象,用于表示12挑路线,之后开启交通灯控制系统即可。
代码如下:
public static void main(String[] args) {
/*产生12个方向的路线*/
String [] directions = newString[]{
"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S"
};
for(inti=0;i<directions.length;i++){
new Road(directions[i]);
}
/*开启交通灯控制系统*/
new LampController();
}
---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------
详细请查看:<a href="http://edu.csdn.net" target="blank">http://edu.csdn.net</a>