-------------------------------------------android培训、期待与您交流 -------------------------------------
模拟实现十字路口的交通灯系统逻辑,具体需求如下:
异步随机生成按照各个路线形式的车辆.
由南向而来去往北向的车辆---直行车辆
由西向而来去往南向的车辆---右转车辆
由东向而来去往南向的车辆----左转车辆
.....
信号灯忽略黄灯,值考虑红灯和绿灯.
应考虑左转车辆控制信号灯,右转车辆不受信号灯控制.
具体信号灯控制逻辑与现实生活中普通交通灯扩至逻辑相同,不考虑特殊状况
下的控制逻辑.
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直线车辆而
后放行左转车辆.
每辆车通过路口时间为1秒(提示:可通过线程sleep的方式模拟)
随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置.
不要求实现GUI,值考虑系统逻辑实现,可通过log方式
展现程序运行结果.
线路数量分析:
总共有12条线路,为了统一编程模型,可以假设每条路线上都有一个红绿灯对其进行控制,右转弯的4条线路的控制等可以假设为常绿状态,另外其它的8条线路是两两成对的,可以归为4组,所以,程序只需要考虑途中标注了数字号的控制等切换顺序,这4条路线相反的路线的控制等跟随者4条线路切换,不必考虑其它.,
线路对应分析(相对方向亮)
面向对象的分析与设计:
(!!!!!补充:面向对象设计把握一个重要的经验:谁拥有数据,谁就对外提供操作这些数据的方法)
详细设计:(工程名traffic)
一.1Lamp枚举类,灯
1.1 每个枚举元素各表示一个方向的控制灯
S2N("N2S","S2W",false), S2W("N2E","E2W",false), E2W("W2E","E2S",false), E2S("W2N","S2N",false),
1.2 下面元素表示与上面的元素的相反方向的灯,它们的“相反方向灯”和“下一个灯”应忽略不计!
N2S(null,null,false), N2E(null,null,false), W2E(null,null,false), W2N(null,null,false),
1.3 由南向东和由西向北等右拐弯的灯不受红绿灯的控制,所以,可以假想它们总是绿灯
S2E(null,null,true), E2N(null,null,true), N2W(null,null,true), W2S(null,null,true);
2控制系统LampController
2.1获取当前等的变量
2.2获取一定时器,时间到,当前等转为红灯,并且下一个方向的等转为绿灯
3.路Road
二.部分所需类以及方法整理:
1
ExecutorService pool = Executors.newScheduledThreadPool(1);
创建一个线程池,-------------线程池(线程数)
2
Road.this.name
//第一种解决方案:内部类访问外部类成员变量,在外部类名前加final
//返回外部类的成员变量,为了避免与自己内部类的名字打架,所以:Road.this.name
3
new Random().nextInt(10)
//返回0~9的随机数
4
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
//创建并执行在给定延迟后启用的一次性操作。
//(线程,推迟时间,推迟时间单位)
5
ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
//创建并执行开始时间,然后过了多少秒之后继续干,再过多少秒再干, 再过多少秒再干, 再过多少秒再干......
//(线程,过多少秒之后去做,然后过多少秒再去干,时间单位)
6
TimeUnit.SECENDS
//时间单位.事件类型
7
valueOf(Class<T> enumType, String name)
返回带指定名称的指定枚举类型的枚举常量。
代码实现:
----------------Road.class---------------------- package cn.itcast.interview.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 { //车的集合 private List<String> vechicles = new ArrayList<String>();//为了面向接口编程,所以是List集合 private String name=null; //每条路线的名字 public Road(String name)//内部类访问外部类,想访问外部类的局部变量,外部类必须加final(final String name) { this.name = name; //新建一个线程,用于添加汽车 //newScheduledThreadPool线程池(线程数) ExecutorService pool= Executors.newScheduledThreadPool(1); //创建一个线程,定隔多少秒进行休息 pool.execute(new Runnable()//执行池执行,new 了一个Runnable()实现对象 { public void run() { for(int i =1;i<1000;i++)//产生999辆车 { try { Thread.sleep((new Random().nextInt(10)+1)*1000);//返回0~9的随机数,再加一,就可以是1~10秒 } catch (InterruptedException e) { e.printStackTrace(); } vechicles.add(Road.this.name+"_"+i);//返回外部类的成员变量,为了避免与自己内部类的名字打架,所以:Road.this.name } } }); //定时器 ScheduledExecutorService timer = Executors.newScheduledThreadPool(1); //循环定时器 timer.scheduleAtFixedRate(new Runnable(){ public void run() {//首先检查是否有车 if(vechicles.size()>0) { /*定义变量,之后就是在这里修改的..修改去检查这个灯 boolean lighted = true; 检查自己的灯,name为自己路线的名字,然后Lamp.valueOf(Road.this.name)获取自己路线的名字, 把自己的名字传过去,就获得了自己的灯*/ boolean lighted = Lamp.valueOf(Road.this.name).isLighted(); if(lighted) //假如灯是绿的 System.out.println(vechicles.remove(0)+"is traversing !"); } } }, 1,//开始时间 1,//循环时间 TimeUnit.SECONDS);//时间单位 } } -----------------Lamp.class---------------------- package cn.itcast.interview.traffic; //灯 public enum Lamp { //首先定义12个方向变量 //这四个是进行控制的 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 Lamp()//不带参数的构造方法,为了让空值的家伙们不报错,因为有的没有对应的灯 { } //灯是否是亮的变量 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();//传递对应灯的字符串,然后valueOf(), //valueOf()返回带指定名称的指定枚举类型的枚举常量。 } //测试用 System.out.println(name()+"lamp is green.下面共有6个方向的车穿过..."); } //熄灯..变红 public Lamp blackOut() { this.lighted = false; if(opposite !=null) { Lamp.valueOf(opposite).blackOut();//传递对应灯的字符串,然后valueOf(), //valueOf()返回带指定名称的指定枚举类型的枚举常量。 } Lamp nextLamp = null; //如果有下一个灯,那么让下一个灯变绿,下一个等变绿之后,还会返回下一个变绿的灯 if(next !=null) { nextLamp = Lamp.valueOf(next); //测试用 System.out.println("绿灯从"+name()+"-------->切换为"+next); Lamp.valueOf(next).light(); } return nextLamp; } } -----------LampController.class------------------ package cn.itcast.interview.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); } } -----------MainClass.class------------------ package cn.itcast.interview.traffic; /** * * @author Chen_zyan * */ public class MainClass { /** * @param args */ public static void main(String[] args) { //创建一个数组,将这12个方向存入 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();//控制器 } }