您的位置:首页 > 职场人生

黑马程序员_7K面试题:十字路口的交通灯管理系统

2014-04-29 09:11 363 查看
----------------------
ASP.Net+Unity开发、.Net培训、期待与您交流! ---------------------- 
 
 模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:
     异步随机生成按照各个路线行驶的车辆。
例如:
       由南向而来去往北向的车辆 ----直行车辆
       由西向而来去往南向的车辆 ----右转车辆
       由东向而来去往南向的车辆 ----左转车辆
信号灯忽略黄灯,只考虑红灯和绿灯。
应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
感觉交通灯管理系统相对于“银行”与“移动”那两个需要的逻辑思维较低,思路的整理一张图就可以解决



 
图中重要考虑的是线路的问题,一条路有三个分支,左右直走,虽然右拐是不需要考虑交通灯的,但是,为了逻辑上的统一,判定车子右拐时全部为绿灯。
面向对象的设计
初步设想对象
红绿灯
汽车
路线

汽车看到自己所在路线对应的灯绿了就穿过路口吗?
不是,还需要看其前面是否有车,看前面是否有车,该问哪个对象呢?该问路,路中存储着车辆的集合,显然路上就应该有增加车辆和减少车辆的方法了。
面向对象设计把握一个重要的经验:
谁拥有数据,谁就对外提供操作这些数据的方法。{
案例:
人在黑板上画圆:
       事件发生在黑板上黑板提供圆心半径等数据
售货员统计收获小票的金额,
       小票提供统计金额的方法
你把门关上了
       “关”发生在门上门内部产生旋转等方法才可关上门
}
所以,设计上”路线”施行”汽车”通过的过程,”汽车”只是”路线”中的一组数据,用字符串表示就可以
 心想:如”
汽车A = 路线A(S,1,2)”
红路灯的设计:
交通灯的状态数量固定为方便管理各个状态的特性所以用枚举
       交通灯的特点:
某个灯变绿时,它对应方向的灯也要变绿
某个灯变红时,对应方向的灯也要变红,并且下一个方向的灯要变绿
实际灯只有四个,但为了判定12个车道车子的通过,所以设定为12个灯,根据四个灯的特点来判定12个灯得的状态。
 
Road类
 
1.  /Road类的初步编写  
2.    
3.  public class Road {  
4.    
5.  //泛型集合,存储车辆,list是为了面向接口编程,vechicles并不是一个具体的对象,好处就是可以令vechicles更好的遵循一种原则。  
6.    
7.      private List<String> vechicles = new ArrayList<String>();  
8.      private String name =null;  
9.      public Road(String name){  
10.   
11.        this.name = name;  
12.        //模拟车辆不断随机上路的过程  
13.        //ExecutorService线程池  
14.   
15.        ExecutorService pool = Executors.newSingleThreadExecutor();  
16.   
17.        pool.execute(new Runnable(){  
18.            public void run(){  
19.               for(int i=1;i<1000;i++){  
20.                  try {//在1-10s内随即产生一辆车子  
21.                      Thread.sleep((new Random().nextInt(10) + 1) * 1000);  
22.   
23.                   } catch (InterruptedException e) {  
24.                      e.printStackTrace();  
25.   
26.                   }//访问外部类成员变量的一种写法,防止与前者打架  
27.   
28.                   vechicles.add(Road.this.name + "_" + i);  
29.   
30.               }              
31.   
32.            }            
33.   
34.        });  
35.   
36. //每隔一秒检查对应的灯是否为绿,是则放行一辆车  
37. //线程定时器  
38.   
39. ScheduledExecutorService timer =  Executors.newScheduledThreadPool(1);  
40.   
41.         timer.scheduleAtFixedRate(  
42.               new Runnable(){  
43.                   public void run(){  
44.                      if(vechicles.size()>0){  
45. //valueOf 返回带指定名称的指定枚举类型的枚举常量  
46.   
47. //路线名对应Lamp名  
48.                          boolean lighted = Lamp.valueOf(Road.this.name).isLighted();  
49.                          if(lighted){  
50.                             System.out.println(vechicles.remove(0) + " is traversing !");  
51.                          }  
52.   
53.                      }  
54.   
55.                     
56.   
57.                   }  
58.   
59.               },  
60.   
61.               1,  
62.   
63.               1,  
64.   
65.               TimeUnit.SECONDS);  
66.   
67. }  
/Road类的初步编写
 
public class Road {
 
//泛型集合,存储车辆,list是为了面向接口编程,vechicles并不是一个具体的对象,好处就是可以令vechicles更好的遵循一种原则。
 
   private List<String> vechicles = new ArrayList<String>();
   private String name =null;
   public Road(String name){
 
      this.name = name;
      //模拟车辆不断随机上路的过程
      //ExecutorService线程池
 
      ExecutorService pool = Executors.newSingleThreadExecutor();
 
      pool.execute(new Runnable(){
          public void run(){
             for(int i=1;i<1000;i++){
                try {//在1-10s内随即产生一辆车子
                    Thread.sleep((new Random().nextInt(10) + 1) * 1000);
 
                 } catch (InterruptedException e) {
                    e.printStackTrace();
 
                 }//访问外部类成员变量的一种写法,防止与前者打架
 
                 vechicles.add(Road.this.name + "_" + i);
 
             }           

 
          }         

 
      });
 
//每隔一秒检查对应的灯是否为绿,是则放行一辆车
//线程定时器
 
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
 
       timer.scheduleAtFixedRate(
             new Runnable(){
                 public void run(){
                    if(vechicles.size()>0){
//valueOf返回带指定名称的指定枚举类型的枚举常量
 
//路线名对应Lamp名
                        boolean lighted = Lamp.valueOf(Road.this.name).isLighted();
                        if(lighted){
                           System.out.println(vechicles.remove(0) + " is traversing !");
                        }
 
                    }
 
                   
 
                 }
 
             },
 
             1,
 
             1,
 
             TimeUnit.SECONDS);
 
}
 
Lamp类
 
1.  //Lamp类的编写,
2.    
3.  /** 
4.   
5.   * 每个Lamp元素代表一个方向上的灯,总共有12个方向,所有总共有12个Lamp元素。 
6.   
7.   * 有如下一些方向上的灯,每两个形成一组,一组灯同时变绿或变红,所以, 
8.   
9.   * 程序代码只需要控制每组灯中的一个灯即可: 
10.  
11.  * s2n,n2s    
12.  
13.  * s2w,n2e 
14.  
15.  * e2w,w2e 
16.  
17.  * e2s,w2n 
18.  
19.  * s2e,n2w 
20.  
21.  * e2n,w2s 
22.  
23.  * 上面最后两行的灯是虚拟的,由于从南向东和从西向北、以及它们的对应方向不受红绿灯的控制, 
24.  
25.  * 所以,可以假想它们总是绿灯。 
26.  
27.  * @author 张孝祥 www.it315.org 
28.  
29.  * 
30.  
31.  */  
32.   
33. /**/  
34.   
35.   
36. public enum Lamp {  
37.   
38.     /*每个枚举元素各表示一个方向的控制灯*/    
39.   
40.     //灯的三个属性的关系(向对(对应)方向:灯的状态相同,不同状态的灯,是否为绿:初始都为blackOut)  
41.   
42.     S2N("N2S","S2W",false),S2W("N2E","E2W",false),E2W("W2E","E2S",false),E2S("W2N","S2N",false),  
43.   
44.     /*下面元素表示与上面的元素的相反方向的灯,它们的“相反方向灯”和“下一个灯”应忽略不计!*/  
45.   
46.     N2S(null,null,false),N2E(null,null,false),W2E(null,null,false),W2N(null,null,false),  
47.   
48.     /*由南向东和由西向北等右拐弯的灯不受红绿灯的控制,所以,可以假想它们总是绿灯*/  
49.   
50.     S2E(null,null,true),E2N(null,null,true),N2W(null,null,true),W2S(null,null,true);  
51.   
52.     private Lamp(String opposite,String next,boolean lighted){  
53.   
54.        this.opposite = opposite;  
55.   
56.        this.next = next;  
57.   
58.        this.lighted = lighted;  
59.   
60.     }  
61.    
62.     /*当前灯是否为绿*/   
63.   
64.     private boolean lighted;  
65.   
66.     /*与当前灯同时为绿的对应方向*/    
67.   
68.     private String opposite;  
69.   
70.     /*当前灯变红时下一个变绿的灯*/    
71.   
72.     private String next;  
73.   
74.     public boolean isLighted(){  
75.   
76.        return lighted;  
77.   
78.     }  
79.   
80.     /** 
81.  
82.      * 某个灯变绿时,它对应方向的灯也要变绿 
83.  
84.      */  
85.   
86.     public void light(){  
87.   
88.        this.lighted = true;  
89.   
90.        if(opposite != null){  
91.   
92.            Lamp.valueOf(opposite).light();  
93.   
94.        }  
95.   
96.        System.out.println(name() + " lamp is green,下面总共应该有6个方向能看到汽车穿过!");  
97.   
98.         
99.   
100.    }  
101.  
102.    /** 
103. 
104.     * 某个灯变红时,对应方向的灯也要变红,并且下一个方向的灯要变绿 
105. 
106.     * @return 下一个要变绿的灯 
107. 
108.     */  
109.  
110.    public Lamp blackOut(){  
111.  
112.       this.lighted = false;  
113.  
114.       if(opposite != null){  
115.  
116.           Lamp.valueOf(opposite).blackOut();  
117.  
118.       }       
119.  
120.        
121.  
122.       Lamp nextLamp= null;  
123.  
124.       if(next != null){  
125.  
126.           nextLamp = Lamp.valueOf(next);  
127.  
128.           System.out.println("绿灯从" + name() + "-------->切换为" + next);        
129.  
130.           nextLamp.light();  
131.  
132.       }  
133.  
134.       return nextLamp;  
135.  
136.    }  
137.  
138.}  
//Lamp类得编写, (我只能说:老师注释写的很详细,没有自己要表达的内容了)
 
/**
 
 *每个Lamp元素代表一个方向上的灯,总共有12个方向,所有总共有12个Lamp元素。
 
 *有如下一些方向上的灯,每两个形成一组,一组灯同时变绿或变红,所以,
 
 *程序代码只需要控制每组灯中的一个灯即可:
 
 * s2n,n2s  
 
 * s2w,n2e
 
 * e2w,w2e
 
 * e2s,w2n
 
 * s2e,n2w
 
 * e2n,w2s
 
 *上面最后两行的灯是虚拟的,由于从南向东和从西向北、以及它们的对应方向不受红绿灯的控制,
 
 *所以,可以假想它们总是绿灯。
 
  
 *
 
 */
 
/**/
 
 
public enum Lamp {
 
   /*每个枚举元素各表示一个方向的控制灯*/ 

 
   //灯的三个属性的关系(向对(对应)方向:灯的状态相同,不同状态的灯,是否为绿:初始都为blackOut)
 
   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 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个方向能看到汽车穿过!");
 
     
 
   }
 
   /**
 
    *
某个灯变红时,对应方向的灯也要变红,并且下一个方向的灯要变绿
 
    * @return
下一个要变绿的灯
 
    */
 
   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;
 
   }
 
}
 
LampController类
 
1.  //LampController类得编写  
2.    
3.  public class LampController {  
4.    
5.      private Lamp currentLamp;  
6.    
7.       
8.    
9.      public LampController(){  
10.   
11.        //刚开始让由南向北的灯变绿;       
12.   
13.        currentLamp = Lamp.S2N;  
14.   
15.        currentLamp.light();  
16.   
17.         
18.   
19.        /*每隔10秒将当前绿灯变为红灯,并让下一个方向的灯变绿*/     
20.   
21.        ScheduledExecutorService timer =  Executors.newScheduledThreadPool(1);  
22.   
23.        timer.scheduleAtFixedRate(  
24.   
25.               new Runnable(){  
26.   
27.                   public  void run(){  
28.   
29.                      currentLamp = currentLamp.blackOut();  
30.   
31.               }  
32.   
33.               },  
34.   
35.               10,  
36.   
37.               10,  
38.   
39.               TimeUnit.SECONDS);  
40.   
41.     }  
42.   
43. }  
44.   
45. 主函数  
46. public static void main(String[] args) {  
47.     
48.   
49.        /*产生12个方向的路线*/       
50.   
51.        String [] directions = new String[]{  
52.   
53.               "S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S"       
54.   
55.        };  
56.   
57.        for(int i=0;i<directions.length;i++){  
58.   
59.            new Road(directions[i]);  
60.   
61.        }  
62.   
63.        /*产生整个交通灯系统*/       
64.   
65.        new LampController();  
66.   
67.     } 
 
----------------------
ASP.Net+Unity开发、.Net培训、期待与您交流! ---------------------- 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: