黑马程序员7K---交通灯管理系统
交通燈管理系統(tǒng)
-----------?android培訓(xùn)、java培訓(xùn)、java學(xué)習(xí)型技術(shù)博客、期待與您交流!?------------
1.模擬實(shí)現(xiàn)銀交通燈管理系統(tǒng)邏輯
1.1 具體需求如下
(1)異步隨機(jī)生成按照各個(gè)路線行駛的車輛。
例如:
??????由南向而來去往北向的車輛 ---- 直行車輛
??????由西向而來去往南向的車輛 ---- 右轉(zhuǎn)車輛
??????由東向而來去往南向的車輛 ---- 左轉(zhuǎn)車輛
??????。。。
(2)信號燈忽略黃燈,只考慮紅燈和綠燈。
(3)應(yīng)考慮左轉(zhuǎn)車輛控制信號燈,右轉(zhuǎn)車輛不受信號燈控制。
(4)具體信號燈控制邏輯與現(xiàn)實(shí)生活中普通交通燈控制邏輯相同,不考慮特殊情況下的控制邏輯。
注:南北向車輛與東西向車輛交替放行,同方向等待車輛應(yīng)先放行直行車輛而后放行左轉(zhuǎn)車輛。
(5)每輛車通過路口時(shí)間為1秒(提示:可通過線程Sleep的方式模擬)。
(6)隨機(jī)生成車輛時(shí)間間隔以及紅綠燈交換時(shí)間間隔自定,可以設(shè)置。
(7)不要求實(shí)現(xiàn)GUI,只考慮系統(tǒng)邏輯實(shí)現(xiàn),可通過Logic方式展現(xiàn)程序運(yùn)行結(jié)果。
具體實(shí)現(xiàn)線路圖
1.2 概述
方向說明:N(North)---北 ; S(south)-->南方;E(east)--> 東方 ;W(west)-->西方2為英文單詞to的意思N2E意思是由北到東。
對應(yīng)線路:由上圖可知一共有12條線路。
而線路可分為直行線路、左轉(zhuǎn)線路、右轉(zhuǎn)線路。
直行線路有S2N,N2S,E2W,W2E;
右轉(zhuǎn)線路有N2W,E2N,W2S,S2E;
左轉(zhuǎn)線路有S2N,N2E,W2E,E2S;
其中由中國的交通情況可知,右轉(zhuǎn)是不需要交通燈訊號的,但為了面向?qū)ο缶幊趟枷?#xff0c;這里把右轉(zhuǎn)改為有交通燈訊號,且為常綠狀態(tài)。
而且根據(jù)交通知識可知,線程為一對一的關(guān)系,即每次放行時(shí),只有一條線路與其相對應(yīng)的線程通行,其他線路不通行。上圖同色線路為對應(yīng)線路,由上圖可知其有4條一一對應(yīng)線路。(S2N,N2S)、(E2W,W2E)(S2N,N2E) (W2E,E2S)
要求:
這四條一一對應(yīng)的線程必須遵守線路上的交通燈指示運(yùn)行與停止。而右轉(zhuǎn)之線路卻不用理會(huì)。
1.3 簡化線路
1)12條線路,每條線路作為一個(gè)對象;
2)每條線路由一個(gè)紅綠燈控制其通、停狀態(tài);
3)右轉(zhuǎn)之紅綠燈設(shè)為常綠;
4)余下的8條線路(兩兩對應(yīng))分為四組
總結(jié):程序只需考慮圖中的4條(同色)路線的紅綠燈的如何切換即可。
1.4 根據(jù)題目要求進(jìn)行線路切換次序確定
1)將線路分為南北、東西兩部分,同方向等待車輛先放直行再放左轉(zhuǎn)車輛。
因?yàn)榫€路為兩兩對應(yīng)關(guān)系,其實(shí)只需要考慮兩個(gè)方向的線程即可,即S(南)與E(東).
2) 從S方向出發(fā)的車有S2W和S2N這兩個(gè)方向的線路--->要求是先放直行后放左轉(zhuǎn),所以S2N先施行;S2W后放行。
3)從E方向出發(fā)的車有E2W和E2S這兩個(gè)方向的線路---要求先放行直行再放行左轉(zhuǎn),所以E2W先放行,E2S后放行。
總結(jié):因?yàn)榻煌羰茄h(huán)切換的,所以從那個(gè)方向開始是沒有關(guān)系的,這里就由S開始循環(huán)切換。
可得
{2}3. 從S方向或者E方向那個(gè)開始都可以,因?yàn)檫@些線路的交通燈是循環(huán)切換的。因此這里面從S方向開始。While(true){
S2N(N2S)【1】---> S2W(N2E)【2】---> E2W(W2E)【3】 ---> E2S(W2N)【4】--->S2N(N2S)【1】 --->}
由切換關(guān)系可知,由這個(gè)交通燈程序只需要考慮兩條直線與兩條左轉(zhuǎn)線即可(4條線路,忽略同時(shí)進(jìn)行的線路)。
1.5 面向?qū)ο蟮姆治?/span>
1.5.1 類的提取
? ? 交通燈系統(tǒng)中需要用到路線、交通燈與車輛,而交通燈的亮滅不可能是自己決定,所以需要有一個(gè)類來控制其的亮滅,所以得有一個(gè)交通燈控制器類,所以可以將其分為這三個(gè)類 ----- 交通燈類、線路類、車輛類與交通燈控制器類。
1.5.2 模擬過程—車輛穿過一條線路的過程
? ? 首先應(yīng)該先有一輛車,才能在線路上啟動(dòng)運(yùn)行,所以車輛類的實(shí)例應(yīng)在線路類的實(shí)例中產(chǎn)生。一輛車產(chǎn)生后就在線路實(shí)例中運(yùn)行。而且當(dāng)這條線路上的交通燈為紅時(shí),不得通行,這輛車前面有車輛也不得通行。。
1.5.3 類的分析
1.線路類的分析
成員分析:由上思想可得,車輛類一定要在線路的實(shí)例中生成,而線路中必然包括一個(gè)交通燈類的實(shí)例,這個(gè)實(shí)例是與線路一一對應(yīng)的。所以可得每條線路的實(shí)例都包括相應(yīng)的車輛與交通燈類的實(shí)例。
關(guān)系分析:由現(xiàn)實(shí)可知,一條交通線路上可以讓無數(shù)的車輛通過,而每條線路上只有一個(gè)交通燈在作用,當(dāng)然這只是指這個(gè)實(shí)例上的十字路口。所以可得交通燈類與線路類是一一對應(yīng)關(guān)系,而車輛類與線路類則是N對1的關(guān)系。
方法分析:
??? 在本實(shí)例中,汽車只是存在于通過線路時(shí),即在通過線路時(shí)產(chǎn)生出現(xiàn),而通過線路后則會(huì)自動(dòng)銷毀。所以線路類中有車輛的減少與增加方法。汽車看到前面綠燈了,就可以通行了嗎,當(dāng)然不是,在現(xiàn)實(shí)中,就算前面綠燈了,也需要看看自己前面有沒有車輛才可通過,當(dāng)前面沒有車輛,且是綠燈時(shí),方可通過,怎么判斷車輛位置是不是第一位呢,很明顯是用集合的下標(biāo)表示為佳,所以線路類對象中汽車是以集合形式存儲(chǔ)的。
2.交通燈類分析
成員分析:
交通燈如現(xiàn)實(shí)上有三種顏色,但實(shí)際只是兩種顏色起作用,紅或綠,因?yàn)閮煞N顏色是相互切換的,即---紅燈亮?xí)r,綠燈滅;紅燈滅時(shí),綠燈亮。所以只需要一種燈的狀態(tài)即可,用綠燈的亮滅表示其線路的通閉狀態(tài)。
方法分析:
如果線路問題,每個(gè)交通燈指揮著相應(yīng)的線路的通閉,而每個(gè)交通燈都應(yīng)該有其切換交通燈切換通閉的方法,即決定下一個(gè)通行的線路的切換。其順序就是對圖分析時(shí)的,先真行后左拐,再到另一方向上的直行,左拐。
具體分析:
有12條線路則有12個(gè)交通燈,但右拐之燈為常綠狀態(tài),其他八條線路為一一對應(yīng)狀態(tài),則只需要4組燈的訊號即可。只需要在4組中各取出一個(gè)燈,對這4個(gè)燈進(jìn)行依次輪流變亮,而其對應(yīng)的燈也相應(yīng)地一同變亮,燈的輪流變亮,則意味著,每一個(gè)交通燈需要知道自己的后一個(gè)交通燈,這樣才能達(dá)到輪流的效果,所以交通燈類中應(yīng)該有一個(gè)變量來記錄自己的下一個(gè)交通燈。
3.車輛類分析
車輛類在這里只是一個(gè)體現(xiàn)車輛穿過線路的過程,也是并不需要車輛類中有相應(yīng)的方法,所以車輛輛不需要單獨(dú)設(shè)計(jì)成一個(gè)對象,用一個(gè)字符串表示即可。----使用Java內(nèi)建String類對象來替代自定義的車輛類。
4.交通燈控制器類分析
功能分析:需求:紅綠燈切換時(shí)間間隔可以是任意的,所以交通燈控制器類中的方法就應(yīng)該有相應(yīng)的時(shí)間屬性并且有設(shè)置該時(shí)間的方法。而且有切換交通燈的功能的方法。
2.程序編寫
2.1 交通燈類Lamp的程序編寫
1.由上例的分析可知Lamp類的功能應(yīng)采用枚舉;
分析:12個(gè)交通燈對應(yīng)著枚舉中的12個(gè)成員對象,Lamp類中的表示對應(yīng)線路的屬性和下一條線路的屬性是一一對應(yīng)關(guān)系的,這種一一對應(yīng)關(guān)系可以采用String類型來替代Lamp類聚合的表示對應(yīng)的Lamp類的實(shí)例和表示下一條交通燈的Lamp實(shí)例。
2. Lamp類代碼示例
1).Lamp的亮滅方法
增加讓Lamp變亮和變黑的方法:light和blackOut,對于S2N、S2W、E2W、E2N這四個(gè)方向上的Lamp對象,這兩個(gè)方法內(nèi)部要讓相反方向的燈隨之變亮和變黑,blackOut方法還要讓下一個(gè)燈變亮。
2). Lamp類示例代碼
注:編寫程序時(shí)的包名:因這是面試題,而對方公司為軟通公司,所以我們把包名改為com.isoftstone.interview.traffic(面試小技巧);
package com.isoftstone.interview.traffic;/*** 每個(gè)Lamp元素代表一個(gè)方向上的燈,總共有12個(gè)方向,所有總共有12個(gè)Lamp枚舉元素。 * 程序代碼只需要控制每組燈中的一個(gè)燈即可:----括號中的表示該線路的交通燈對應(yīng)的線路的交通燈* S2N(N2S)、S2W(N2E)、 E2W(W2E)、 E2S(W2N) -----受紅綠燈控制的交通燈* S2E(N2W) 和E2N(W2S) -----不受紅綠燈控制的交通燈* */ public enum Lamp { //每個(gè)枚舉元素各表示一個(gè)線路方向上的控制燈 //左轉(zhuǎn)的兩條主路+ 兩條直行線 ----初始化這些主路的燈光是滅的---Red S2N("N2S", "S2W", false), S2W("N2E", "E2W", false), E2W("W2E", "E2S", false), E2S("W2N", "S2N", false), //對應(yīng)線路的燈隨著變化就行,忽略掉“反方向燈”和“下一個(gè)燈” N2S(null, null, false), N2E(null, null, false), W2E(null, null, false), W2N(null, null, false), //四條右拐的路常綠 ---四個(gè)右轉(zhuǎn)彎方向的燈,因?yàn)槠洳皇芗t綠燈控制,所以可以假設(shè)它們總是綠燈 N2W(null, null, true), W2S(null, null, true), S2E(null, null, true), E2N(null, null, true); //當(dāng)前燈的狀態(tài),是否為綠 private boolean lighted =false; //當(dāng)前線路交通燈的對應(yīng)線路的交通燈 //一對一所以使用String的name替代 private String opposite =null; //當(dāng)前線路交通燈的被切換到下一個(gè)交通燈 private String next =null; //一對一所以使用String的name替代 /*** 構(gòu)造函數(shù)* @param opposite ----當(dāng)前線路對應(yīng)線路的交通燈的名字* @param next --------當(dāng)前線路的下一條線路的交通燈的名字* @param lighted -----這條線路的交通燈初始化的時(shí)候被點(diǎn)亮(代表綠燈)*/ private Lamp(String opposite, String next, boolean lighted){ this.lighted =lighted; this.opposite =opposite; this.next =next; } /*** lighted屬性的Getter* @return---獲取當(dāng)前線路的交通燈的狀態(tài)*/ public boolean isLighted() { return lighted; } /*** 點(diǎn)亮該燈----點(diǎn)亮表示將燈變成綠色的* 某個(gè)燈變綠時(shí),它對應(yīng)方向的燈也要變綠*/ public void light(){ this.lighted =true; //同時(shí)要點(diǎn)亮對應(yīng)路段的交通燈 if(this.opposite !=null){ Lamp oppositeLamp =Lamp.valueOf(opposite); oppositeLamp.light(); } System.out.println(name()+" lamp is green, 下面可以看到6個(gè)方向看到汽車穿過!"); } /*** 滅掉該燈----也就是將該路段的交通燈變紅* @return----返回下一站切換的路燈*/ public Lamp blackOut(){ //當(dāng)前燈變紅,對應(yīng)方向的燈也變紅 this.lighted =false; //同時(shí)要滅掉對應(yīng)路段的燈 if(this.opposite !=null){ Lamp oppositeLamp =Lamp.valueOf(opposite); oppositeLamp.blackOut(); } //點(diǎn)亮下一對應(yīng)的燈 Lamp nextLamp =null; if(next !=null){ nextLamp=Lamp.valueOf(next); nextLamp.light(); System.out.println("綠燈從"+ name()+"--->切換為"+next); } return nextLamp; } }2.2 線路類Road程序編寫
1. 相應(yīng)方法
1). 刪除方法 ------代表車輛穿過這條線路
每條路線每隔一秒都會(huì)檢查控制本路線的燈是否為綠,是則將本路線保存車的集合中的第一輛車移除,即表示車穿過了路口。
2). 增加車輛和刪除車輛的方法
??? 在上面的分析可知車輛的增刪不過是集合的增刪而已,所以這兩個(gè)方法不需要其實(shí)方法調(diào)用,可以直接放到Road類的構(gòu)造方法即可。
3). Road類示例代碼
package com.isoftstone.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; /*** 每個(gè)Road對象代表一條路線,總共有12條路線,即系統(tǒng)中總共要產(chǎn)生12個(gè)Road實(shí)例對象。* 每條路線上隨機(jī)增加新的車輛,增加到一個(gè)集合中保存。* 每條路線每隔一秒都會(huì)檢查控制本路線的燈是否為綠,是則將本路線保存車的集合中的第一輛車移除,即表示車穿過了路口。*/ public class Road { //模擬該條路上的汽車集合 private List<String> vehichles =new ArrayList<String>(); //使用List接口 ---面相接口編程 //線路的線路名稱 ----- 實(shí)際聚合的是Lamp類實(shí)例 private String name; //實(shí)際通過這個(gè)name獲取這條線路一對一的Lamp類對象 /*** Road類的構(gòu)造方法* @param name ----該條線路的線路名稱*/ public Road(String name){ this.name =name; //啟動(dòng)另一個(gè)線程來創(chuàng)建該條路上的車輛 ---模擬車輛不斷隨機(jī)上路的過程,使用線程池,通過產(chǎn)生單個(gè)線程的方法,創(chuàng)建一個(gè)線程池 ExecutorService pool =Executors.newSingleThreadExecutor(); pool.execute(new Runnable(){ //通過for循環(huán)來模擬車輛的增加 ----隨機(jī)時(shí)間間隔生成一輛車 間隔不固定 @Override public void run() { for(int i=0; i< 1000; i++){ try { //按照一個(gè)隨機(jī)的時(shí)間間隔生成車輛 int randomTime =(new Random().nextInt(10)+ 1)*1000; Thread.sleep(randomTime); Road.this.vehichles.add(Road.this.name+"_"+ i); }catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }); //啟動(dòng)另一個(gè)線程來減少當(dāng)前這條路上的車以模擬這輛車通過了這條路 ScheduledExecutorService timer =Executors.newScheduledThreadPool(1); timer.scheduleAtFixedRate( new Runnable(){ @Override public void run() { // TODO Auto-generated method stub if(vehichles.size() >0){ //查看當(dāng)前路段對應(yīng)的交通燈是不是已經(jīng)亮了亮了的話讓該條路上的車輛通過 boolean lighted = Lamp.valueOf(Road.this.name).isLighted(); if(lighted){ System.out.println(vehichles.remove(0)+" is traversing!"); } } } }, 1, 1, TimeUnit.SECONDS); } }2.3 LampController程序編寫
1. 切換線路的方法
要求:每隔10s切換一下交通燈。
這個(gè)方法僅僅被使用一次之后即可,不需要被其他的方法調(diào)用。因此簡化程序,就直接放入到LampController類的構(gòu)造方法即可。
2.LampController 類的設(shè)計(jì)規(guī)范
因?yàn)樵谡麄€(gè)交通燈系統(tǒng)中,交通燈控制器只能有一個(gè),所以LampController類設(shè)計(jì)為單例模式。
3.LampController類的示例代碼
import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit;/**** LampController類用來切換不同線路的交通燈每隔10秒將當(dāng)前燈變紅,并按順序?qū)⑾乱粋€(gè)方向的燈變綠**/ public class LampController {private Lamp currentLamp;/*** 初始化第一盞要變綠的紅綠燈之后啟動(dòng)新的線程進(jìn)行線程切換* LampController設(shè)計(jì)成單例模式 StepI: 私有化構(gòu)造方法*/private LampController() {// 指定第一盞亮的交通燈currentLamp = Lamp.S2N;currentLamp.light();// 設(shè)置定時(shí)器ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);timer.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {// 每隔10s切換下一盞亮的交通燈currentLamp = currentLamp.blackOut();}}, 10, 10, TimeUnit.SECONDS);}// 單例模式 ---- StepII:餓漢式構(gòu)建全局訪問點(diǎn)public static final LampController lampController = new LampController(); }2.4 測試類MainClass程序編寫
?MainClass類的示例代碼
public class MainClass { public static void main(String[] args) { //實(shí)例化交通燈控制器實(shí)例 //在實(shí)例化LampController的過程中,會(huì)對相應(yīng)道路的交通燈進(jìn)行無限循環(huán)的切換 //-----啟動(dòng)了新的線程進(jìn)行切換 LampController lampController =LampController.lampController; //給出所有的方向 String[]directions =new String[]{ "S2N", "S2W", "E2W", "E2S", "N2S", "N2E", "W2E", "W2N", "N2W", "W2S", "S2E", "E2N" }; //實(shí)例化Road的過程 //---- 每一條路的new的過程中會(huì)查看這條路的交通燈的顏色并穿過馬路 ---- 一個(gè)新的線程 //---- 每一條路的自動(dòng)增加車輛 ---- 有一個(gè)新的線程 for(int i=0; i< directions.length; i++){ new Road(directions[i]); } } }?-----------?android培訓(xùn)、java培訓(xùn)、java學(xué)習(xí)型技術(shù)博客、期待與您交流!?------------
總結(jié)
以上是生活随笔為你收集整理的黑马程序员7K---交通灯管理系统的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 北邮计算机学院五组夏森,前辈种树 | 从
- 下一篇: 网络中的计算机访问不了,win7系统不能