一:項目名稱:
電梯調度模擬程序
二:項目參與人員:
周其范 胡寶月
三:項目開發語言和工具:
Java語言和eclipse,涉及內容:面向對象技術、基於Swing的圖形化用戶界面、多線程啟動和休眠
四:問題陳述:
1、電梯要正常運行,能響應內部、外部按鈕
2、要怎樣選擇哪部電梯電梯,使乘坐者和電梯的距離更近,已達到更省電、更快、更經濟。
3、同一部電梯可以響應多位乘客的請求
五:任務需求:
1、要模擬一棟6層樓中兩部電梯的調度,模擬乘坐電梯的過程.
2、乘坐者在最低層樓:只能乘坐電梯上樓,在電梯內部按下要去的樓層。
3、乘坐者在中間層:可以乘坐電梯上樓和下樓,在電梯內部按下要去的樓層。
4、乘坐者在最上層:只能乘坐電梯下樓,在電梯內部按下要去的樓層。
5、在同一部電梯內部中,乘坐者的目的地不同。例如,有人要上5樓,有的人要上6樓。
6、在界面中要顯示電梯的狀態:所在樓層和上樓還是下樓。
7、電梯開門3秒,電梯運行速度1.5秒每層,電梯到達目的樓層時,開門3秒后才關門,當乘客發出請求后1秒,電梯才運行
六:任務描述:
1、根據2部電梯的運行狀態,尋找離當前樓層最近,並和請求同方向的電梯,給予響應,將任務分配給此電梯。
2、每個電梯如果在它的上層或者下層沒有相應請求的情況下,則在原地保持不動。所有電梯的初始狀態都在第一層。
3、每個電梯內部均有數字鍵、關門鍵、開門鍵、所在樓層顯示及運行狀態顯示。
4、 每部電梯都有所在樓層顯示及運行狀態顯示。
5、電梯外部要顯示電梯所在樓層和運行狀態,每層樓的電梯門處要顯示所在樓層和上、下鍵按鈕
---------------- 下面介紹一下我們的程序主要界面---------------
程序開始界面
左側是電梯外部界面,
例如,如果在四樓要下,則在四樓按下
;
如果在四樓下,則按下
;
開門鍵:
;
關門鍵;
此界面顯示電梯狀態的初始狀態:顯示樓層按鈕
為;
顯示運行狀態的按鈕為
;
程序運行界面:
表示目的地樓層;
表示正在開門;
表示電梯內部顯示電梯運行狀態和顯示樓層
;
表示電梯和電梯外部運行狀態和顯示樓層。
主要類和方法介紹:
class Found extends Thread //任務分配線程
實現了尋找哪部電梯最省的功能,主要成員如下:
public void addTask(int i, boolean flag)//添加任務
將任務添加到任務列表中
class Task//任務:要到幾樓,上去還是下去
內部類,包括目標樓層、要上樓還是下樓
public void run()//線程體
實現了尋找哪部電梯最省的功能
如果上樓,並且電梯的狀態是暫停的或者電梯正在從下往上運行,則計算目標樓層與電梯當前樓層之間的距離,判斷這個距離是否比另一個電梯與目標樓層的距離小。如果是,則將線程分配給這個電梯,然后等此線程運行完畢后(調用),將此任務從目的地列表里移除。否則,將線程分配給另一個電梯。
線程休眠一秒才運行,1秒后才執行任務,意思是乘坐者請求任務后,1秒鍾后,電梯才開始運行
class Elevator extends Thread //電梯主類
此類繼承了thread類,其構造方法構造2部樓梯的界面,主要成員如下:
public void addFloor(int i) //響應外部按鈕
此方法響應乘坐者在電梯外部請求,將分配到此電梯的任務加入到目的地列表destinations中。
public void wantToFloor(int i) //響應內部按鈕
此方法響應乘坐着在電梯內部的請求,將符合當前運行狀態的樓層加入到目的地列表destinations中,不符合的不予處理。
public void setStateB() //設置運行狀態按鈕
此方法實現了顯示電梯外部、電梯、電梯內部的運行狀態按鈕。電梯在上時顯示“上”,否則顯示“下”,初始狀態是“---”
public void run()
run()方法是線程體,根據當前電梯運行狀態state,決定電梯的運行處理,通過對界面中樓層顏色的改變來表示電梯的運行狀態。此方法通過sleep()休眠線程,來設置開門時間,電梯速度。此方法完成了電梯外部、電梯、電梯內部顯示樓層功能。
class CanvasOuter extends JPanel //顯示外部按鈕的畫布類,位於左側
電梯外部界面顯示,將其設置在總界面的左側。其中有上行按鈕監聽器(class UpAction implements ActionListener)和下行按鈕監聽器(class DownAction implements ActionListener)。
class CanvasInner extends JPanel //顯示內部按鈕的畫布,位於右側
電梯內部部界面顯示,將其設置在總界面的右側。其中有要去樓層數字鍵按鈕監聽器(class goFloor implements ActionListener)、開門鍵監聽器(class OpenAction implements ActionListener)、關門鍵監聽器(class CloseAction implements ActionListener)。
-----------下面是完成設計的時間安排------------
時間日期 | 周其范 | 胡寶月 |
3.4 | 春暉樓體驗電梯 | 春暉樓體驗電梯 |
3.6 | 分析題目,確定用java完成 | 分析題目,確定用java完成 |
3.8 | 設計界面 | 構建類成員和具體方法 |
3.10—3.15 | 完成界面和代碼連接 | 類的具體實現 |
3.16——3.19 | 完善整個程序,並對設計中存在的問題進行修改 | 完善整個程序,並對設計中存在的問題進行修改 |
3.21 | 確認完成,整個項目完成 | 確認完成,整個項目完成 |
--------下面是實驗代碼--------
import java.awt.*; import javax.swing.*; import java.awt.event.*; import java.util.*; public class TestElevator { public static void main(String[] args) { SimpleFrame frame = new SimpleFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //退出模式,退出應用程序后的默認窗口關閉操作 frame.setLocation(40, 40); //窗口位置坐標 frame.show(); } } class SimpleFrame extends JFrame { public SimpleFrame() { setSize(690, 510); setTitle("電梯模擬"); SimplePanel panel = new SimplePanel(); this.add(panel); } } class SimplePanel extends JPanel { private CanvasOuter myCanvasOuter;//顯示外部按鈕的畫布類,位於左側 private CanvasInner myCanvasInner;//顯示內部按鈕的畫布類,位於右側 private Elevator[] s;//電梯數組 private Found foundThread = new Found();//任務分配線程 public final static int NUM = 2; //電梯數 public final static int FLOOR = 6; //樓層 final int UP = 0; //電梯狀態初始化 final int DOWN = 1; final int PAUSE = 2; final int OPEN = 3; final int CLOSE = 4; public SimplePanel() { setLayout(null); myCanvasOuter = new CanvasOuter(); myCanvasInner = new CanvasInner(); add(myCanvasOuter); add(myCanvasInner); s = new Elevator[NUM]; for (int i = 0; i < s.length; i++) { s[i] = new Elevator(i); } for (int i = 0; i < s.length; i++) { s[i].start();//線程啟動 } foundThread.start();//線程啟動 } class Found extends Thread //任務分配線程 { private ArrayList tasks; private Task task; public Found() { tasks = new ArrayList(); } public void addTask(int i, boolean flag)//添加任務 { tasks.add(new Task(i, flag)); } public void run()//線程體 { while (true) { if (!tasks.isEmpty()) { task = (Task) (tasks.get(0)); int i = task.floor; int minFloor = FLOOR;// int id = 0; boolean f = task.isUp; boolean isFound = false; if (f)//要上樓 { for (int j = 0; j < NUM; j++)//電梯數 { if ((s[j].state == PAUSE) || (s[j].current < i && s[j].state == UP))//停或者電梯正在從下往上 { int distance = Math.abs(i - s[j].current); if (distance < minFloor) { id = j; minFloor = distance; isFound = true; } } } } else//下樓 { for (int j = 0; j < NUM; j++) { if ((s[j].state == PAUSE) || (s[j].current > i && s[j].state == DOWN))//停或正在從上往下 { int distance = Math.abs(i - s[j].current); if (distance < minFloor) { id = j; minFloor = distance; isFound = true; } } } } if (isFound) { s[id].addFloor(i); tasks.remove(0); } } try { sleep(1000); } catch (InterruptedException e) { System.out.println("Interrupted"); } } } class Task//任務:要到幾樓,上去還是下去 { private int floor; private boolean isUp; public Task(int i, boolean flag) { floor = i; isUp = flag; } } } public void resetOuterB(int floor) //設置外部的按鈕 { myCanvasOuter.bUp[floor].setEnabled(true); myCanvasOuter.bDown[floor].setEnabled(true); myCanvasOuter.bUp[floor].setForeground(null); myCanvasOuter.bDown[floor].setForeground(null); } public void drawButtons(int id)//設置內部按鈕 { for (int i = 0; i < FLOOR; i++) { if (s[id].destinations.contains(new Integer(i))) { myCanvasInner.interPanels[id].interB[i].setBackground(Color.YELLOW); } else { myCanvasInner.interPanels[id].interB[i].setBackground(null); } } } class Elevator extends Thread //電梯主類 { private int id; //電梯標識號 private int floor = FLOOR; //總層數 private JPanel myPanel = new JPanel(); private JPanel myPanel1 = new JPanel(); private JButton numB; private JButton stateB = new JButton("---"); private JButton[] buttons; //電梯組成 public int current = 1; //所在樓層 public int state = PAUSE; //上下行標志 private JButton floorB = new JButton("1"); private ArrayList destinations; //目的地鏈表 public Elevator(int x) { id = x; myPanel1.setLayout(new GridLayout()); numB = new JButton("第"+(x+1)+"號電梯"); myPanel1.add(numB); myPanel.setLayout(new GridLayout(floor + 2, 1)); floorB.setBackground(Color.WHITE); myPanel.add(floorB); myPanel.add(stateB); buttons = new JButton[FLOOR]; for (int i = buttons.length - 1; i >= 0; i--) { buttons[i] = new JButton(); buttons[i].setBackground(Color.LIGHT_GRAY); myPanel.add(buttons[i]); } buttons[0].setBackground(Color.RED); myPanel1.setBounds(100 * id + 250, 10, 100, 50); myPanel.setBounds(100 * id + 250, 60, 100, 400); add(myPanel1); add(myPanel); destinations = new ArrayList(); } public void addFloor(int i) //響應外部按鈕 { if (destinations.contains(new Integer(i))) return; if (state == PAUSE) { destinations.add(new Integer(i)); buttons[i].setBackground(Color.YELLOW); if (current > i) { state = DOWN; } else { state = UP; } return; } if (state == UP) { for (int j = 0; j < destinations.size(); j++) { if (i < ((Integer) (destinations.get(j))).intValue()) { destinations.add(j, new Integer(i)); buttons[i].setBackground(Color.YELLOW); } } } if (state == DOWN) { for (int j = 0; j < destinations.size(); j++) { if (i > ((Integer) (destinations.get(j))).intValue()) { destinations.add(j, new Integer(i)); buttons[i].setBackground(Color.YELLOW); } } } destinations.add(new Integer(i)); buttons[i].setBackground(Color.YELLOW); } public void wantToFloor(int i) //響應內部按鈕 { if (destinations.contains(new Integer(i))) return; if (state == PAUSE) { destinations.add(new Integer(i)); buttons[i].setBackground(Color.YELLOW); if (current > i + 1) { state = DOWN; } else { state = UP; } return; } if (state == UP) { if (current > i + 1) return; for (int j = 0; j < destinations.size(); j++) { if (i < ((Integer) (destinations.get(j))).intValue()) { destinations.add(j, new Integer(i)); buttons[i].setBackground(Color.YELLOW); return; } } } if (state == DOWN) { if (current < i) return; for (int j = 0; j < destinations.size(); j++) { if (i > ((Integer) (destinations.get(j))).intValue()) { destinations.add(j, new Integer(i)); buttons[i].setBackground(Color.YELLOW); return; } } } destinations.add(new Integer(i)); buttons[i].setBackground(Color.YELLOW); } public void setStateB() //設置運行狀態按鈕 { if (state == PAUSE) { stateB.setText("---"); stateB.setForeground(null); myCanvasInner.interPanels[id].stateB.setText("---"); myCanvasInner.interPanels[id].stateB.setForeground(null); myCanvasOuter.stateB1.setText("---"); myCanvasOuter.stateB1.setForeground(null); myCanvasOuter.stateB2.setText("---"); myCanvasOuter.stateB2.setForeground(null); } else if (state == UP) { stateB.setText("上"); stateB.setForeground(Color.RED); myCanvasInner.interPanels[id].stateB.setText("上"); myCanvasInner.interPanels[id].stateB.setForeground(Color.RED); if(id==0) { myCanvasOuter.stateB1.setText("上"); myCanvasOuter.stateB1.setForeground(Color.RED); } if(id==1) { myCanvasOuter.stateB2.setText("上"); myCanvasOuter.stateB2.setForeground(Color.RED); } } else { stateB.setText("下"); stateB.setForeground(Color.RED); myCanvasInner.interPanels[id].stateB.setText("下"); myCanvasInner.interPanels[id].stateB.setForeground(Color.RED); if(id==0) { myCanvasOuter.stateB1.setText("下"); myCanvasOuter.stateB1.setForeground(Color.RED); } if(id==1) { myCanvasOuter.stateB2.setText("下"); myCanvasOuter.stateB2.setForeground(Color.RED); } } } public void run() { while (true) { if (state != PAUSE) //運行中 { if (state == OPEN)//開門建對應 { buttons[(current + FLOOR - 1) % FLOOR].setBackground(Color.BLACK);//開門狀態中 try { sleep(3000); } catch (InterruptedException e) { System.out.println("Interrupted"); } buttons[(current + FLOOR - 1) % FLOOR].setBackground(Color.RED);//關門狀態中 state = PAUSE; } else { int i =((Integer) (destinations.get(0))).intValue() + 1; //當前所在樓層 if (current == i) //到達一個樓層 { destinations.remove(0); if (destinations.isEmpty()) { state = PAUSE; } setStateB(); drawButtons(id); buttons[(current + FLOOR - 1) % FLOOR].setBackground(Color.BLACK);//到達目的地時開門狀態中 try { sleep(3000);//休眠3秒 } catch (InterruptedException e) { System.out.println("Interrupted"); } buttons[(current + FLOOR - 1) % FLOOR].setBackground(Color.RED); resetOuterB(current - 1); } else { int follow = current; //運行前的樓層 if (state == UP) { current++; } else { current--; } floorB.setText(Integer.toString(current)); floorB.setForeground(Color.green); myCanvasInner.interPanels[id].floorB.setText(Integer.toString(current)); myCanvasInner.interPanels[id].floorB.setForeground(Color.green); if(id==0) { myCanvasOuter.floorB1.setText(Integer.toString(current)); myCanvasOuter.floorB1.setForeground(Color.green); } if(id==1) { myCanvasOuter.floorB2.setText(Integer.toString(current)); myCanvasOuter.floorB2.setForeground(Color.green); } buttons[(current + FLOOR - 1) % FLOOR].setBackground(Color.RED); buttons[(follow + FLOOR - 1) % FLOOR].setBackground(Color.LIGHT_GRAY); setStateB(); } } } try { sleep(1500); } catch (InterruptedException e) { System.out.println("Interrupted"); } } } } class CanvasOuter extends JPanel //顯示外部按鈕的畫布類,位於左側 { private JPanel[] oneFloor;//樓層畫布 private int num = SimplePanel.FLOOR; private JButton[] bFloor; //樓層 private JPanel jp; private JPanel[] updownpanel;//顯示上下按鈕 private JButton[] bUp; //上行按鈕 private JButton[] bDown; //下行按鈕 private JPanel outp;//顯示“電梯外部” private JPanel statePanel1;//顯示1號和2號電梯的狀態 private JPanel statePanel2; private JButton state1; private JButton state2; private JButton floorB1;//顯示1號電梯樓層按鈕 private JButton stateB1;//顯示1號電梯上、下按鈕 private JButton floorB2;//顯示2號電梯樓層按鈕 private JButton stateB2;//顯示2號電梯上、下按鈕 CanvasOuter() { setLayout(null); jp = new JPanel(new GridLayout(8,1)); jp.setBounds(20,160,225,400); outp=new JPanel(new GridLayout()); JButton out = new JButton("電梯外部"); outp.setBounds(20, 10, 225, 60); outp.add(out); bFloor = new JButton[num];//定義數組長度 bUp = new JButton[num]; bDown = new JButton[num]; oneFloor = new JPanel[num]; updownpanel = new JPanel[num]; statePanel1 = new JPanel(new GridLayout(3,1)); statePanel1.setBounds(20, 70, 110, 90); state1 = new JButton("一號電梯"); floorB1 = new JButton("1");//顯示1號電梯樓層按鈕 stateB1 = new JButton("---");//顯示1號電梯上、下按鈕 floorB1.setBackground(Color.WHITE); statePanel2 = new JPanel(new GridLayout(3,1)); statePanel2.setBounds(134, 70, 110, 90); state2 = new JButton("二號電梯"); floorB2 = new JButton("1");//顯示2號電梯樓層按鈕 stateB2 = new JButton("---");//顯示2號電梯上、下按鈕 floorB2.setBackground(Color.WHITE); statePanel1.add(state1); statePanel1.add(floorB1); statePanel1.add(stateB1); statePanel2.add(state2); statePanel2.add(floorB2); statePanel2.add(stateB2); for(int i=num-1;i>=0;i--) { updownpanel[i] = new JPanel(new GridLayout(2,1)); bFloor[i] = new JButton(i+1+"樓"); bUp[i] = new JButton(); if (i != num - 1) { bUp[i].setText("▲"); bUp[i].addActionListener(new UpAction(i)); } bDown[i] = new JButton(); if (i != 0) { bDown[i].setText("▼"); bDown[i].addActionListener(new UpAction(i)); } updownpanel[i].add(bUp[i]); updownpanel[i].add(bDown[i]); oneFloor[i]= new JPanel(new GridLayout(1,2));// oneFloor[i].add(bFloor[i]); oneFloor[i].add(updownpanel[i]); jp.add(oneFloor[i]); } add(jp); add(statePanel1); add(statePanel2); add(outp); this.setBounds(0, 0, 250, 550); } class DownAction implements ActionListener { private int floor; public DownAction(int i) { floor = i; } public void actionPerformed(ActionEvent e) { foundThread.addTask(floor, true); } } class UpAction implements ActionListener { private int floor; public UpAction(int i) { floor = i; } public void actionPerformed(ActionEvent e) { foundThread.addTask(floor, true); } } } class CanvasInner extends JPanel //顯示內部按鈕的畫布,位於右側 { private int num = NUM; private InterButton[] interPanels; public final static int WIDTH = 200; private JPanel panel2 = new JPanel(); private JButton inviewB = new JButton("電梯內部"); public CanvasInner() { this.setLayout(null); interPanels = new InterButton[num]; panel2.setLayout(new GridLayout()); panel2.add(inviewB); panel2.setBounds(0, 0, 200, 60); add(panel2); for (int i = 0; i < num; i++) { interPanels[i] = new InterButton(i); add(interPanels[i]); } setBounds(455, 10, WIDTH, 450); } class InterButton extends JPanel //表示每部電梯內部按鈕的類 { private int id; //電梯標識號 private JPanel panel = new JPanel(); private JPanel panel1 = new JPanel(); private JButton numB; private JButton floorB = new JButton("1"); private JButton stateB = new JButton("---"); private JButton openB = new JButton("<>"); private JButton closeB = new JButton("><"); private JButton[] interB; //內部按鈕數組 public InterButton(int j) { id = j; this.setLayout(null); numB = new JButton("第"+(j+1)+"號電梯"); int width = CanvasInner.WIDTH; floorB.setBackground(Color.WHITE); panel1.setLayout(new GridLayout()); panel1.add(numB); panel1.setBounds(0, 60, width, 40); panel.setLayout(new GridLayout(5, 2)); panel.add(stateB); panel.add(floorB); panel.setBounds(0, 100, width, 150); interB = new JButton[FLOOR]; for (int i = 0; i < FLOOR; i++) { interB[i] = new JButton(); interB[i].setText(i+1+"樓"); panel.add(interB[i]); interB[i].addActionListener(new goFloor(i)); } panel.add(openB); panel.add(closeB); openB.addActionListener(new OpenAction()); closeB.addActionListener(new CloseAction()); this.add(panel); this.add(panel1); this.setBounds(0, j * 200, width, 260); } class goFloor implements ActionListener { private int floor; //目的地樓層 public goFloor(int i) { floor = i; } public void actionPerformed(ActionEvent e) { interB[floor].setBackground(Color.YELLOW); s[id].wantToFloor(floor); } } class OpenAction implements ActionListener //開門鍵對應監聽器 { public void actionPerformed(ActionEvent e) { if (s[id].state == PAUSE) { s[id].state = OPEN; } } } class CloseAction implements ActionListener //關門鍵對應監聽器 { public void actionPerformed(ActionEvent e) { int i = s[id].current - 1; s[id].buttons[i].setBackground(Color.RED); } } } } }