------- android培训、java培训、期待与您交流! ----------
下面是项目需求:
模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:
异步随机生成按照各个路线行驶的车辆。
例如:
由南向而来去往北向的车辆 ---- 直行车辆
由西向而来去往南向的车辆 ---- 右转车辆
由东向而来去往南向的车辆 ---- 左转车辆
。。。
信号灯忽略黄灯,只考虑红灯和绿灯。
应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
我刚看到的时候是想啊想,解过想了半天还是好乱,车的转弯行走路线就把我搞乱了,更别提下手写代码了。
所以后来干脆直接看视频,结果真的学到即为重要的一点:当我们感觉事情复杂的时候,不要只用脑袋去想,有时候想破头都没用,
我们可以用笔或记或画,把示意图做出来,在看就简单多了。
public enum Lamp {
//创建12盏灯,把对应的灯和下一盏要亮的灯,和当前等的状态,当作参数传给当前灯。
S2N("N2S","S2W",false),S2W("N2E","E2W",false),E2W("W2E","E2S",false),E2S("W2N","S2N",false),
//因为这4盏灯和上面的想对应,所以就不再传入前面连个参数,不然就回造成死循环。
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);
//用3个变量来接收3个参数。
private boolean lighted;
private String opposite;
private String next;
//创建带3个参数的构造方法
private Lamp(String opposite,String next,boolean lighted){
this.opposite=opposite;
this.lighted=lighted;
this.next=next;
}
//获取当前灯的状态。
public boolean isLighted(){
return lighted;
}
//让当前灯变量,相当于绿灯,如果对应灯不为null,让对应的灯变亮。
public void light(){
this.lighted=true;
if(opposite!=null){
Lamp.valueOf(opposite).light();
}
}
//让当前灯变暗,相当于红灯,如果对应灯不为null,让对应灯变暗。如果下一盏灯不为null;让下一盏灯变亮,并返回下一盏灯。
public Lamp blackOut(){
this.lighted=false;
if(opposite!=null){
Lamp.valueOf(opposite).blackOut();
}
Lamp nextLamp=null;
if(next!=null){
nextLamp=Lamp.valueOf(opposite);
nextLamp.light();
}
return nextLamp;
}
}
这时灯的代码就写完了。下面是路的代码,车是行走在路上,我们可以把路看成一个集合,车就是集合中的元素,车是随即添加的,但是只有绿灯的时候才可以每过一小段时间删除一个。模拟现实生活中车走在路上的情景。
import java.util.*;
import java.util.concurrent.*;
public class Load {
//创建一个集合,用来存放车量。
private List<String> ches=new ArrayList<String>();
String name=null;//每个方向的路名,12个方向,单独看成12条马路。
public Load(String name){
this.name=name;
ExecutorService pool=Executors.newSingleThreadExecutor();//创建一个单一线程池。每条路需要
pool.execute(new Runnable() { //一个单独的线程控制。
int count=1;
public void run() {//用匿名内部类创建一个线程对象并实现run方法。
while(true){
try {
//int i=(int) (Math.random()*10+1);
int j=(new Random().nextInt(10)+1);//用随机数来模拟,每隔一段时来一两车。
Thread.sleep(j*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ches.add(Load.this.name+"_"+count);//将车辆添加到马路上。
count++;//嘿嘿区分车辆的,看做车牌号吧,不然打印程序的时候不好看输出结果。
}
}
});
ScheduledExecutorService acheduled=Executors.newScheduledThreadPool(1);//创建一个定时器线程池。
acheduled.scheduleAtFixedRate(new Runnable() {
//又是匿名内部类,不多说了。
@Override
public void run() {
if(ches.size()>0){//首先判断集合是否为空,即马路上有没有车,
boolean lighted=Lamp.valueOf(Load.this.name).isLighted();
if(lighted){//在判断当前灯是否是绿灯,
System.out.println(ches.remove(0)+"正在通行ing");//是的话就把元素删除,即把车开过去。
}
}
}
},
1, //定时器第一次的执行时间。
1,//以后每隔多长时间执行一次。
TimeUnit.SECONDS);//定时器的时间单位。
}
}
哎,总算吧路也搞定了。写注释也是一个麻烦的事,但是为了以后程序可以随时看懂,这都是必须要做的事。
马上就要完成了,在写一个路灯控制器,用来给路灯的转换定时的。
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 acheduled=Executors.newScheduledThreadPool(1);
acheduled.scheduleAtFixedRate(new Runnable() {//创建一个定时器,让路灯定时改变。
@Override
public void run() {
// TODO Auto-generated method stub
currentLamp=currentLamp.blackOut();//将等变成红灯。下面就不用说了吧。前面讲过了。
}
},
10,
10,
TimeUnit.SECONDS);
}
}
哈哈,总算大功告成了,一切都写完了。
马上写个主程序运行一下吧。
public class MainClass {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
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 Load(directions[i]);//初始化12条马路,条数一定弄对啊
}
new LampController();//初始化路灯控制器
}
}
OK了,以上代码在myeclipse8.5运行没有问题,java版本不能低于1.5。