java

位置:IT落伍者 >> java >> 浏览文章

java面试题之一:交通灯管理系统


发布日期:2021年08月06日
 
java面试题之一:交通灯管理系统

背景介绍 软件开发公司现在都越来越精明和狡猾了他们把日后工作中要解决的问题并且是他们自己都很难解决的问题拿出来让面试求职者去搞 不管面试求职者的水平怎样他们都说谁能搞定谁就来上班这样至少求职者在进公司之前就已经为公司做了贡献 软件公司这招够狠够高!
题目来源 前一阵子的某一天中午有一个学员打电话给我说他去国内某大型的软件外包公司应聘了要求的薪水是k该公司给了他一道面试题就是要做一个模拟的交通灯管理系统 并说公司外包了一个法国交通系统的项目现在就是在替做这个交通系统的项目组招人这个交通灯管理系统就是招聘进来的人上班后要开发的项目模型如果他在家三天内能够做出来他就可以入职上班了并且他要求的薪水则不是任何问题还可以更高一些这个同学做了两天感到很困难于是打电话向我求助我让他把题目发到我的邮箱晚上又有一个学员给我打电话说是去某公司面试了该公司让他做一个交通灯管理系统 三天内做出来就可以直接去上班我马上告诉他已经有一个同学先他一步来找我了我只能满足他们两人中的一人否则他们就会出现答案雷同最后对他们两人都造成不利影响 后来又有几个学员拿着不同公司的面试题找我题目如出一辙都是公司要求把日后的项目拿回家做什么时候做好就什么时候上班看来以后靠背我们的面试宝典来突击找工作的方式越来越困难了软件公司把他们项目中的复杂问题拿出来让面试者做如果面试者正好是传智播客的学员他们必将求助于我们我们这批老师也就顺理成章地成为这些公司免费使用的超级劳工
这些软件公司精心策划的项目题确实都有很强的技术性和实用价值在此感谢奉献了这些题目的学员在征得这些学员们的同意后我将逐步公布和讲解这些项目面试题下面是某公司的交通灯管理系统的需求
交通灯管理系统

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

异步随机生成按照各个路线行驶的车辆

例如
由南向而来去往北向的车辆&#; 直行车辆
由西向而来去往南向的车辆&#; 右转车辆
由东向而来去往南向的车辆&#; 左转车辆

信号灯忽略黄灯只考虑红灯和绿灯

应考虑左转车辆控制信号灯右转车辆不受信号灯控制

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

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

每辆车通过路口时间为秒(提示可通过线程Sleep的方式模拟)

随机生成车辆时间间隔以及红绿灯交换时间间隔自定可以设置

不要求实现GUI只考虑系统逻辑实现可通过Log方式展现程序运行结果

解题思路

首先为了较好地理解和分析问题切不可空想一定要画图!画图非常有助于理解和分析问题你还有比画图更好的办法吗?

我画的交通灯路线图如下

接着进行面向对象的分析和设计

(一)每条路线上都会出现多辆车路线上要随机增加新的车在灯绿期间还要每秒钟减少一辆车
设计一个Road类来表示路线每个Road对象代表一条路线总共有条路线即系统中总共要产生个Road实例对象
每条路线上随机增加新的车辆增加到一个集合中保存
每条路线每隔一秒都会检查控制本路线的灯是否为绿是则将本路线保存车的集合中的第一辆车移除即表示车穿过了路口
(二)每条路线每隔一秒都会检查控制本路线的灯是否为绿一个灯由绿变红时应该将下一个方向的灯变绿
设计一个Lamp类来表示一个交通灯每个交通灯都维护一个状态亮(绿)或不亮(红)每个交通灯要有变亮和变黑的方法并且能返回自己的亮黑状态
总共有条路线所以系统中总共要产生个交通灯右拐弯的路线本来不受灯的控制但是为了让程序采用统一的处理方式故假设出有四个右拐弯的灯只是这些灯为常亮状态即永远不变黑
除了右拐弯方向的其他条路线的灯它们是两两成对的可以归为所以在编程处理时只要从这组中各取出一个灯对这个灯依次轮询变亮与这个灯方向对应的灯则随之一同变化因此Lamp类中要有一个变量来记住自己相反方向的灯在一个Lamp对象的变亮和变黑方法中将对应方向的灯也变亮和变黑每个灯变黑时都伴随者下一个灯的变亮Lamp类中还用一个变量来记住自己的下一个灯
无论在程序的什么地方去获得某个方向的灯时每次获得的都是同一个实例对象所以Lamp类改用枚举来做显然具有很大的方便性永远都只有代表个方向的灯的实例对象
设计一个LampController类它定时让当前的绿灯变红

类的编码实现

(一)Road类
每个Road对象都有一个name成员变量来代表方向有一个vehicles成员变量来代表方向上的车辆集合
在Road对象的构造方法中启动一个线程每隔一个随机的时间向vehicles集合中增加一辆车(用一个路线名_id形式的字符串进行表示)
在Road对象的构造方法中启动一个定时器每隔一秒检查该方向上的灯是否为绿是则打印车辆集合和将集合中的第一辆车移除掉
源码如下
package orgitinterviewtraffic;import javautilArrayList;import javautilList;import javautilRandom;import javautilconcurrentExecutors;import javautilconcurrentTimeUnit;/** * 每个Road对象代表一条路线总共有条路线即系统中总共要产生个Road实例对象 * 每条路线上随机增加新的车辆增加到一个集合中保存 * 每条路线每隔一秒都会检查控制本路线的灯是否为绿是则将本路线保存车的集合中的第一辆车移除即表示车穿过了路口 * @author IBM * */public class Road {private String direction;private List vehicles = new ArrayList();public Road(String dir){thisdirection = dir;//模拟车辆不断上路的过程ExecutorsnewSingleThreadExecutor()execute(new Runnable(){public void run(){for(int i=;i<;i++){vehiclesadd(direction + &#;:&#; + i);//Systemoutprintln(&#;add &#; + direction + &#;:&#; + i);try {Threadsleep(new Random()nextInt());} catch (InterruptedException e) {eprintStackTrace();}}}});//每隔一秒检查对应的灯是否为绿是则放行一辆车ExecutorsnewScheduledThreadPool()scheduleAtFixedRate(new Runnable(){public void run(){Lamp lamp = LampvalueOf(direction);if(lampisLighted()){if(vehiclessize() >)Systemoutprintln(vehiclesremove() + &#; is traversing &#;);}}} TimeUnitSECONDS);}}
(二)Lamp类
系统中有个方向上的灯在程序的其他地方要根据灯的名称就可以获得对应的灯的实例对象综合这些因素将Lamp类用java中的枚举形式定义更为简单
每个Lamp对象中的亮黑状态用lighted变量表示选用SNSWEWEN这四个方向上的Lamp对象依次轮询变亮Lamp对象中还要有一个oppositeLampName变量来表示它们相反方向的灯再用一个nextLampName变量来表示此灯变亮后的下一个变亮的灯这三个变量用构造方法的形式进行赋值因为枚举元素必须在定义之后引用所以无法再构造方法中彼此相互引用所以相反方向和下一个方向的灯用字符串形式表示
增加让Lamp变亮和变黑的方法light和blackOut对于SNSWEWEN这四个方向上的Lamp对象这两个方法内部要让相反方向的灯随之变亮和变黑blackOut方法还要让下一个灯变亮
除了SNSWEWEN这四个方向上的Lamp对象之前其他方向上的Lamp对象的nextLampName和oppositeLampName属性设置为null即可并且SNSWEWEN这四个方向上的Lamp对象的nextLampName和oppositeLampName属性必须设置为null以便防止light和blackOut进入死循环
源码如下
package orgitinterviewtraffic;/** * 每个Lamp元素代表一个方向上的灯总共有个方向所有总共有个Lamp元素 * 有如下一些方向上的灯每两个形成一组一组等同时变绿或变红所以 * 程序代码只需要控制每组灯中的一个灯即可 * snns * swne * ewwe * eswn * senw * enws * 上面最后两行的灯是虚拟的由于从南向东和从西向北以及它们的对应方向不受红绿灯的控制 * 所以可以假想它们总是绿灯 * @author IBM * *//**/public enum Lamp{/*每个枚举元素各表示灯控制的一个方向*/SN(&#;NS&#;false&#;SW&#;)SW(&#;NE&#;false&#;EW&#;)EW(&#;WE&#;false&#;ES&#;)ES(&#;WN&#;false&#;SN&#;)/*由南向东和由西向北不受红绿灯的控制所以可以假想它们总是绿灯*/SE(&#;NW&#;true&#;SE&#;)EN(&#;WS&#;true&#;EN&#;)/*下面元素表示与上面的元素的相反方向的灯其中所有的参数值不重要应忽略不计!*/NS(nullfalsenull)NE(nullfalsenull)WE(nullfalsenull)WN(nullfalsenull)NW(nulltruenull)WS(nulltruenull);/*灯是否为绿*/private boolean lighted;/*与灯同时为绿的对应方向*/private String opposite;/*灯变红时下一个变绿的灯*/private String next;private Lamp(String oppositeboolean lightedString next){thisopposite = opposite;thislighted = lighted;thisnext = next;}/** * 灯变绿时它对应方向的灯也要变绿 */public void light(){thislighted = true;if(opposite!=null){Lamp lampOpposite = LampvalueOf(opposite);lampOppositelight();}Systemoutprintln(name() + &#; lamp is green下面总共应该有个方向能看到汽车穿过!&#;);}public boolean isLighted(){return lighted;}/** * 灯变红时对应方向的灯也要变红并且下一个方向的灯要变绿 * @return 下一个要变绿的灯 */public Lamp blackOut(){thislighted = false;if(opposite!=null){Lamp lampOpposite = LampvalueOf(opposite);lampOppositeblackOut();}Lamp nextLamp = null;if(next != null){nextLamp = LampvalueOf(next);nextLamplight();Systemoutprintln(&#;绿灯从&#; + name() + &#;&#;&#;&#;>切换为&#; + next);}return nextLamp;}}
(三)LampController类
整个系统中只能有一套交通灯控制系统所以LampController类最好是设计成单例
LampController构造方法中要设定第一个为绿的灯
LampController对象的start方法中将当前灯变绿然后启动一个定时器每隔将当前灯变红和将下一个灯变绿
源码如下
package orgitinterviewtraffic;import javautilconcurrentExecutors;import javautilconcurrentTimeUnit;public class LampController {private static LampController instance = new LampController();public static LampController getInstance(){return instance;}private Lamp currentLamp = null;private LampController(){//刚开始让由南向北的灯变绿;currentLamp = LampSN;}public void start(){currentLamplight();/*每隔秒将当前绿灯变为红灯并让下一个方向的灯变绿*/ExecutorsnewScheduledThreadPool()scheduleAtFixedRate(new Runnable(){public void run(){currentLamp = currentLampblackOut();}} TimeUnitSECONDS);}}
(四)MainClass类
用for循环创建出代表条路线的对象
接着再获得LampController对象并调用其start方法
源码如下
package orgitinterviewtraffic;public class MainClass {/** * @param args */public static void main(String[] args) {/*产生个方向的路线*/String [] directions = {&#;SN&#;&#;NS&#;&#;SW&#;&#;NE&#;&#;EW&#;&#;WE&#;&#;ES&#;&#;WN&#;&#;SW&#;&#;NW&#;&#;EN&#;&#;WS&#;};for(int i=;i<directionslength;i++){new Road(directions);}/*产生整个交通灯系统*/LampControllergetInstance()start();}}

               

上一篇:2012年遇到的最新的Java面试题 请参考

下一篇:用Java写出一段string和stringbuffer的代码