黑马程序员——交通灯管理系统

                                            黑马程序员——交通灯管理系统
 ---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a 
href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! -------------------------------
 一、需求:
 模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:
异步随机生成按照各个路线行驶的车辆。
   例如:


       由南向而来去往北向的车辆 ---- 直行车辆


       由西向而来去往南向的车辆 ---- 右转车辆


       由东向而来去往南向的车辆 ---- 左转车辆


       。。。


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


 应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。   
 
 
 二、面向对象的设计分析
 1.类的分析
   面向对象设计把握一个重要的经验:谁拥有数据,谁就对外提供操作这些数据的方法。例如:
 
火车司机刹车:刹车这个方法是车提供的,刹车动作是刹车系统内部完成的,司机没那么力气是火车停下了,司机发出刹车指令。
人在黑白画圆:画园动作用到 圆心、园半径R  ,人画圆圈需要用到这些数据,这些数据是圆提供的,方法再圆上,不应该定义在人身上。
人关门:关门方法是门提供的,门有转轴,轴心转动,转动关门的方法定义在门身上,人只是提供一外力推一下,调用关门的方法。


  1、“两块石头磨成了一把石刀,石刀可以砍树,砍成木头,木头做成椅子”
分析:石头变成石刀,不是自己变成石到,通过其他磨成刀。如石刀加工成,磨刀方法定义在石刀加工场,接收参数(两块石头)
      石刀来砍树,有砍树方法 ,木头变成椅子,不是自己变成的,是被加工成使用,变成椅子的方法定义在加工场。
  2、“球从一根绳子的一段移动到另一端”分析其有多少个对象。
 分析:绳子,有长度,有两个结束点的坐标。提供一个点到下一个点的方法,球滚动,提供滚动的方法,怎么滚
 
 2.类的功能分析:
 a. 要有红绿灯的控制系统,指挥灯的颜色变化。 
 b.车在这条路上行驶,对应的等是绿色的才通行。其那面还有车,这条路相当于一个集合中有很多车。
 c、路线集合中存储的汽车,车会拐弯,穿过、过程增加和减少车辆,减少的方法是路提供,对象是路线 。
 d.设计类就需要 1.红绿灯、2.红绿灯控制系统,3.路线(车相当于是路线里面的一个元素) 三个类。
 
 分析 路线:1.总共会有12条路线(南到北有(直走、左拐、右拐),四个方向共12条路线) 即系统中总共要产生12个路线实例对象。   
            2.每条路线上随机增加新的车辆,把车子增加到一个集合中保存,每条路线每隔一秒都会检查控制本路线的灯是否为绿,
            是则将本路线保存车的集合中的第一辆车移除,即表示车穿过了路口。 
      灯:  1.既然是12条路线,所以,系统中总共要产生12个交通灯。一个灯由绿变红时,应该将下一个方向的灯变绿。右拐弯的路线本来不受灯的控制
            2.右拐弯方向的其他8条路线的灯,它们是两两成对的,可以归为4组, 南到北灯是绿的、相对的北到南也是绿的。
            所以,只要从这4组中各取出一个灯,对这4个灯依次轮询变亮,与这4个灯方向对应的灯则随之一同变化,因此Lamp类中要有一个变量来记住自己相反方向的灯,、
            在一个Lamp对象的变亮和变黑方法中,将对应方向的灯也变亮和变黑。每个灯变黑时,都伴随者下一个灯的变亮,Lamp类中还用一个变量来记住自己的下一个灯。
            3.设计灯的控制类,定时让绿灯变红
           
 三编写类:
 
  1.编写路线这个Road 类
分析:1.每条路线都有一个成员变量name属性代表方向路线 List集合存放该方向上的车辆
      2.在Road对象的构造方法中启动一个线程每隔一个随机的时间,List集合中增加车辆
      3、在Road对象的构造方法中启动一个定时器,每隔一秒检查该方向上的灯是否为绿,
      是则打印车辆集合和将集合中的第一辆车移除掉
  package com.itheima.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 {


/**
* @Author hutian
*/
//每创建一条路线定义个名字
private String name=null;
// 路线的集合存放路上跑的车
private List<String> list=new ArrayList<String>();
  
public  Road(String name){
this.name=name;
//启动一个线程,每隔一个随机的时间向list 集合中添加一辆车

// 提供一个线程池,产出都是一组线程,池来控制线程,那个空闲调用那个。
ExecutorService pool = Executors.newSingleThreadExecutor() ;
     pool.execute(new Runnable(){


@Override
public void run() {
for(int i=1;i<1000;i++){
try {
//1秒到10秒钟内随机会有车经过
Thread.sleep((new Random().nextInt(10)+1)*1000);
} catch (Exception e) {
// TODO: handle exception
}
 //内部类访问外部类的成员变量:
 list.add(Road.this.name+"_"+i) ; 
}

}
     
     });
     
     // 启动一个定时器,每隔一秒检查该方向上的灯是否为绿色,如果是绿灯就放行
     ScheduledExecutorService timer = Executors.newScheduledThreadPool(1) ; 
      timer.scheduleAtFixedRate(new Runnable(){


@Override
public void run() {
//   //该路上的车辆是否大于0,路上有车跑
if(list.size()>0){
//该路上的灯是否为绿;如果为绿则车辆通过路口
//boolean lighted=true;
// 得到路线,确定灯状态
boolean lighted =Lamp.valueOf(Road.this.name).isLighted(); 
if(lighted){
//返回某个车 状态
System.out.println(list.remove(0)+"is running!");
}
}

}
     
      }, 1, 1, TimeUnit.SECONDS);
                        

}



}
 2.编写灯Lamp这个类
 分析:1.使用枚举形式定义,根据灯的名称就可以获得对应的灯的实例对象。
       2.南北向车辆与东西向车辆交替方向,同向等待车辆应该先放行直行车辆
       3.每个Lamp对象都有亮、黑的状态,S2N、S2W、E2W、E2N这四个方向上的Lamp对象依次轮询变亮。
       定义一个相反方向的灯,下一个变亮的灯,用构造方法进行赋值。
       4.定义变亮和变黑的方法light和blackOut,对于S2N、S2W、E2W、E2N这四个方向上的Lamp对象,
       这两个方法内部要让相反方向的灯随之变亮和变黑,(如南往北,北往南相向的灯一致)blackOut方法还要让下一个灯变亮。
       5.S2N、S2W、E2W、E2N这四个方向上的Lamp对象的nextLampName和oppositeLampName属性必须设置为null,
       以便防止light和blackOut进入死循环。
 package com.itheima.traffic;


public enum Lamp {
/**
* @param args
*  。
*/
 //每条路线上对应的灯:true为绿,false为红
S2N(false,"N2S","S2W"),S2W(false,"N2E","E2W"),E2W(false,"W2E","E2S"),E2S(false,"W2N","S2N"),
//下面四条路线对应上面四条路线,它们的“相反方向灯”和“下一个灯”应忽略不计!
N2S(false,null,null),N2E(false,null,null),W2E(false,null,null),W2N(false,null,null),
//应为向右方向的车不受控制,所以,可以假想它们总是绿灯
S2E(true,null,null),E2N(true,null,null),N2W(true,null,null),W2S(true,null,null);

private Lamp(boolean ligthed,String opposite , String next){
this.ligthed=ligthed;  
this.opposite=opposite;
this.next=next;
}

// 设计灯,每条路线上对应的灯:true为绿,false为红灯
private boolean ligthed;

// 定义一个对应灯的变量 如S2N -> N2S 
private String opposite;
// 表示此灯变绿后下一个变绿的灯
     private String next ; 

public static void main(String[] args) {
// TODO Auto-generated method stub


}
//判断灯状态,返回灯
    public boolean isLighted(){
return ligthed;
   
    }
    //灯变亮的方法
    public void light(){
    this.ligthed=true;
    if(opposite!=null){
    ((Lamp) Lamp.valueOf(opposite)).light();//返回枚举对应的名字对象
    //opposite.light(); //对应灯
    }
    System.out.println(name() + " lamp is green,下面总共应该有6个方向能看到汽车穿过!");
    }
    // 灯熄灭变黑
    public Lamp blackOut(){
    this.ligthed=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;
    }
    


}






        
            
            
            
3.灯控制系统LampController 类的编写
分析:
   1、整个系统中只能有一套交通灯控制系统,所以,LampController类最好是设计成单例。
    2、LampController构造方法中要设定第一个为绿的灯。
   3、LampController对象的start方法中将当前灯变绿,然后启动一个定时器,每隔10秒将当前灯变红和将下一个灯变绿。


package com.itheima.traffic;


import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


import javax.swing.Timer;


public class LampController {


/**
* @param args
*/
// 当前为绿的灯
private Lamp currentLamp;

public LampController(){
currentLamp=Lamp.S2N;// 南到北
currentLamp.light();//亮 

//启动一个定时器:每隔10秒将当前灯变红和下一个灯变绿
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
public  void run(){
System.out.println("交通运行开始啦!");
currentLamp = currentLamp.blackOut();
}
},
10,//每隔10秒变换
10,
TimeUnit.SECONDS);
}
public static void main(String[] args) {
// TODO Auto-generated method stub


}


}






编写TestTraffic测试
package com.itheima.traffic;


public class TestTraffic {


/**
* @param args
*/
public static void main(String[] args) {
 String[] directions =  {"S2N","N2S","S2W","N2E","E2W","W2E",
               "E2S","W2N","S2E","N2W","E2N","W2S"};  
 // 1、用for循环创建出代表12条路线的对象。
       for(int i = 0 ; i < directions.length ; i ++) {
           new Road(directions[i]) ; 
       }
       //获取LampController对象并调用其start方法运行交通系统
       new LampController() ;


}


}


打印结果:
N2S lamp is green,下面总共应该有6个方向能看到汽车穿过!
S2N lamp is green,下面总共应该有6个方向能看到汽车穿过!
E2N_1is running!
S2E_1is running!
W2S_1is running!
E2N_2is running!
S2N_1is running!
N2W_1is running!
W2S_2is running!
交通运行开始啦!
S2N变红!S2W下个变绿!
N2E lamp is green,下面总共应该有6个方向能看到汽车穿过!
S2W lamp is green,下面总共应该有6个方向能看到汽车穿过!
S2W_1is running!
N2E_1is running!
E2N_3is running!
N2E_2is running!
N2E_3is running!
S2E_2is running!
E2N_4is running!
S2E_3is running!
S2W_2is running!
N2W_2is running!
S2E_4is running!
S2W_3is running!
W2S_3is running!E2N_5is running!交通运行开始啦!
S2W变红!E2W下个变绿!
W2E lamp is green,下面总共应该有6个方向能看到汽车穿过!
E2W lamp is green,下面总共应该有6个方向能看到汽车穿过!
E2W_1is running!
W2E_1is running!
E2N_6is running!
E2W_2is running!
E2N_7is running!
W2E_2is running!
W2S_4is running!
E2W_3is running!
W2E_3is running!
N2W_3is running!
S2E_5is running!
W2S_5is running!
E2W_4is running!
W2E_4is running!
N2W_4is running!
交通运行开始啦!


总结:主要学会分析思路,没分析清楚是敲不出代码。 
     1.交通灯管理系统,先分清多少路线,东南西北四个方向,每个方向车都右向左、向右、直行的路线对象是路线,共12条。
     2.不是定义车这个对象,不管是摩托车、还是汽车、车始终相当于路线合中的一个元素,路这个对象来控制车,关注的是路线方向。
     3.线程管理中,产出都是一组线程,池来控制线程,那个空闲调用那个。
     4.右拐弯的方向灯可不计影响看做全部绿灯,因为同一线路上前行灯是绿色通行的话,右方向的即可通行。
面向对象思想:路提供各个方向行驶的方法,谁拥有数据谁提供方法。


---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a 
href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! -------------------------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值