交通灯管理系统
张老师的项目思路实在是太清晰了,看完之后我就觉得这个项目很简单,看了一遍视频我也做出来了,张老师视频里说交通灯共有12盏,用枚举,这时我就在想,路线也是12条呀,怎么不用枚举呢?于是我用了,嘿,枚举还真好用,成功了!感觉真好!
这是一个模拟红绿灯的项目。
模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:
· 异步随机生成按照各个路线行驶的车辆。
· 信号灯忽略黄灯,只考虑红灯和绿灯。
· 应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
· 具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
· 每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
· 随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
· 不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
张老师的画图分析如下:

我写的代码:
第一个类:红绿灯类
/**
* 十字路口:每个路口都有直走、左拐、右拐三条路线,四个路口就有12条,每条路线上要设置一盏交通灯。
* 右转不受灯控制,直走时相对的两条路的灯一样,左拐时相对的两条路的灯也一样,所以有4对一样灯的路,
* 所以主要设置4盏灯即可,主灯亮以后让相对的灯跟着亮就行了,灭也跟着灭。
* 谁拥有数据谁叫对外提供操作这些数据的方法,所以灯应该拥有以下方法:
* 1、灯拥有判断自己灯的状态的方法
* 2、把自己点亮的方法,当自己亮的时候相对的灯也要打亮
* 3、把自己熄灭的方法,当自己熄灭时候相对的灯也要熄灭,并且让下一盏灯打亮
*
* 车看是否是红绿灯得问路,所以灯得跟路关联,这样路才能知道灯的状态,并告知车是否能通过,所以下一步定义路的类
*
*/
public enum Lamp {
S2N("N2S","S2W"),S2W("N2E","E2W"),E2W("W2E","E2S"),E2S("W2N","S2N"),//这四盏是主灯,主要控制这四盏灯,通过构造函数保存了与它们相对的灯和它们的下一盏灯
N2S, N2E, W2E, W2N,//这四盏灯在路口与上面四盏一一相对,上面的亮,它就亮,上面的灭,它就灭
S2E(true),E2N(true),N2W(true),W2S(true); //这四盏是右转灯,所以通过构造函数把它们设置为绿灯
private boolean lighted;
private String opposite;
private String next;
private Lamp() {}
private Lamp(boolean lighted) {this.lighted = lighted;}
private Lamp(String opposite,String next) {
this.opposite = opposite;
this.next = next;
}
public boolean isLighted() { //1、灯拥有判断自己灯的状态的方法
return this.lighted;
}
public void light() { //2、把自己点亮的方法,当自己亮的时候相对的灯也要打亮
this.lighted = true;
if(opposite != null){
Lamp.valueOf(opposite).light(); //枚举可以通过名称获得枚举的元素
System.out.println("\n\n\n当前绿灯为:" + this.name() + "、" + opposite + "\n");
}
}
public Lamp blackout() { //3、把自己熄灭的方法,当自己熄灭时候相对的灯也要熄灭,并且让下一盏灯打亮
this.lighted = false;
if(opposite != null) {
Lamp.valueOf(opposite).blackout();
Lamp nextLamp = Lamp.valueOf(next);
nextLamp.light();
return nextLamp;
}
return null;
}
}
第二个类:红绿灯控制系统
/**
* 这是用来控制红绿灯的亮与灭的控制系统
* 一开始就初始化当前灯为S2N,且为绿灯,然后每隔10秒关闭当前的绿灯,并让一下盏灯为绿灯,并让这盏绿灯变成当成灯,就这样循环执行
*/
import java.util.concurrent.*;
public class LampController {
private Lamp currentLamp;
public LampController() {
Lamp.S2N.light();
currentLamp = Lamp.S2N;
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);//创建一个调试线程池
timer.scheduleAtFixedRate(
new Runnable() {
public void run() {
currentLamp = currentLamp.blackout();
}
},
10,
10,
TimeUnit.SECONDS);
}
}
第三个类:路线类/**
* 车是属于路的数据,所以路得提供操作车的方法:
* 1、增加车辆,这些车辆保存到路的一个集合里,车辆增加的时间是不固定的,这里用随机 1~10秒
* 2、绿灯时让车通过,也就是减少一量增加进来的车
* 这里通过两个线程来完成上面两个方法,让路一产生的时候就进行增加车辆和检查绿灯并让车通过
*
* 每条路都得有个路名,取与灯名相同方便与灯进行关联,总共有12条路
*
*/
import java.util.concurrent.*;
import java.util.*;
public enum Road {
S2N,S2W,E2W,E2S,
N2S,N2E,W2E,W2N,
S2E,E2N,N2W,W2S;
List<String> vehicles = new ArrayList<String>();//用于存放车辆
private Road() {
ExecutorService pool = Executors.newSingleThreadExecutor();//产生单个线程的线程池
pool.execute(new Runnable() {
public void run() {
for(int i=1;i<1001;i++) {
try{Thread.sleep( (new Random().nextInt(10)+1)*1000);}catch(Exception e) {e.printStackTrace();}
if(name().equals("S2E")||name().equals("E2N")||name().equals("N2W")||name().equals("W2S"))//如果是右转车则把车名加上"右转"
vehicles.add("-->右转 " + name() + " 第" + i + "辆车");
else
vehicles.add(name() + " 第" + i + "辆车");
}
}
});
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
if(Lamp.valueOf(name()).isLighted()) //如果灯绿,并且有车就删第一辆车,代表开过一辆车
if(!vehicles.isEmpty())
System.out.println(vehicles.remove(0) + " 已通过");
}
},
1,
1,
TimeUnit.SECONDS);
}
}
第四个类:运行类public class MainClass {
public static void main(String[] args) {
new LampController();//把交通灯控制系统打开,红绿灯开始运转。因为灯是枚举,所以这个系统里只要一调用到任意一个灯枚举对象,则12盏灯都有了。
Road road = Road.S2N;//因为Road是枚举,所以只要一调用到Road这个类则里面的枚举元素就全部都有了,里面12条路的线程都启动了。
}
}
截一断我的运行结果,如下:
当前绿灯为:S2N、N2S
-->右转 S2E 第1辆车 已通过
-->右转 W2S 第1辆车 已通过
-->右转 E2N 第1辆车 已通过
-->右转 N2W 第1辆车 已通过
N2S 第1辆车 已通过
S2N 第1辆车 已通过
-->右转 W2S 第2辆车 已通过
-->右转 S2E 第2辆车 已通过
N2E 第1辆车 已通过
S2W 第1辆车 已通过
当前绿灯为:S2W、N2E
-->右转 E2N 第2辆车 已通过
S2W 第2辆车 已通过
-->右转 S2E 第3辆车 已通过
-->右转 N2W 第2辆车 已通过
S2W 第3辆车 已通过
N2E 第2辆车 已通过
-->右转 E2N 第3辆车 已通过
-->右转 E2N 第4辆车 已通过
-->右转 W2S 第3辆车 已通过
-->右转 N2W 第3辆车 已通过
-->右转 N2W 第4辆车 已通过
浙公网安备 33010602011771号