电梯运行程序模拟

​ 日常生活中,大家都坐过电梯,有时候会想想电梯在每个人按下键之后是怎么运行的呢?这是个看起来似乎简单但想清楚却也不容易的问题。

​ 给电梯的运行进行建模。电梯在运行过程中会载人同时接受外部的请求,这样我们可以用两个队列来表示载人信息和请求信息。对于乘客来说,其信息主要是当前楼层和目标楼层,为了方便打印,给每个乘客命名。电梯的运行有三种状态:WAIT(停),UP(上),DOWN(下)。电梯根据载人队列和请求队列来更新自己的状态,在每一层都判断是否可以进人(针对请求队列),出人(针对载人队列)。下面是运行算法图示。

电梯运行程序模拟_第1张图片
image-20190714143300244

​ 当电梯处于上行/下行状态时,到达新的楼层时(本次循环开始),每次循环检查是否需要有人进出,根据载人列表、请求列表及当前运行状态判断出接下来的状态,如果是上行/下行,沉睡1s作为上行/下行一层楼的时间。算法的特征是,先来先服务,在上行/下行过程中尽可能接到或者放出更多的人,在上行/下行过程中只接受与电梯运行方向一致的人。

​ 代码如下:

import java.io.*;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
/*
从文件中读入输入命令及参数
*/
public class Elevator {
    private static List infoList = new LinkedList<>();

    public static void main(String[] args) throws FileNotFoundException {
        start();
        new EleRunner(infoList).start();
    }

    public static void start() throws FileNotFoundException {
        int minFloor = 0;
        int maxFloor = 0;
        boolean started = false;
        boolean inputValid = false;
        Scanner in = new Scanner(
                new FileInputStream("/Users/macbook/programming/Java/leetcode/src/com/test/input.txt"),"UTF-8");
        PrintWriter out = new PrintWriter(
                new FileOutputStream("/Users/macbook/programming/Java/leetcode/src/com/test/log.txt",true),true);
        while(!inputValid) {
            out.println("电梯模拟运行开始,请输入参数(最低楼层,最高楼层):");
            try {
                minFloor = Integer.parseInt(in.next());
                maxFloor = Integer.parseInt(in.next());
                inputValid = true;
            } catch (Exception e) {
                System.out.println("输入异常!");
            }
        }

        while(true) {
            out.println("请输入命令(up/down/stop/start):");
            String cmd = in.next();
            if(started && cmd.equals("start")) {
                //已经开始但输入命令仍是start, 报错
                System.out.println("已经开始,不能再输入start!");
                continue;
            }
            if(!started && !cmd.equals("start")) {
                //没有开始但是输入命令不是start,报错
                out.println("请输入start开始!");
                continue;
            }
            if (cmd.equals("start")) {//开始
                started = true;
                infoList.add(new EleInfo(null, minFloor, maxFloor, "start"));
            } else if (cmd.equals("stop")) {//结束,跳出循环
                infoList.add(new EleInfo(null, 0, 0, "stop"));
                break;
            } else if(cmd.equals("up") || cmd.equals("down")) {
                String name = in.next();
                try {
                    int curFloor = Integer.parseInt(in.next());
                    int targetFloor = Integer.parseInt(in.next());
                    if (curFloor>=minFloor&&curFloor<=maxFloor&&targetFloor>=minFloor
                            &&targetFloor<=maxFloor&&targetFloor!=curFloor) {
                        if((cmd.equals("up")&&curFloor>=targetFloor) || (cmd.equals("down")&&curFloor<=targetFloor)) {
                            out.println("命令与输入楼层不匹配");
                        } else if(curFloor==targetFloor) {
                            out.println("目标楼层与当前楼层不一致!");
                        } else if(!isNameDuplicated(name)) {
                            out.println("人名重复!");
                        } else {//一切输入合法
                            infoList.add(new EleInfo(name, curFloor, targetFloor, cmd));
                        }
                    } else {
                        if(curFloor < minFloor || curFloor > maxFloor) {
                            out.println("当前楼层不合法!");
                        }
                        if(targetFloor < minFloor || targetFloor > maxFloor) {
                            out.println("目标楼层不合法!");
                        }
                        if(targetFloor==curFloor) {
                            out.println("当前楼层与目标楼层不能相同!");
                        }
                    }
                } catch (Exception e) {
                    out.println("输入楼层异常!");
                }
            } else {
                out.println("输入命令出错!");
            }

        }
        in.close();
    }
  
  private boolean isNameDuplicated(String name) {
    for(EleInfo e:infoList) {
      if(e.name.equals(name)) return true;
    }
  }
}

class EleInfo {
    String name;
    int curFloor;
    int targetFloor;
    String cmd;

    public EleInfo(String name, int curFloor, int targetFloor, String cmd) {
        this.name = name;
        this.curFloor = curFloor;
        this.targetFloor = targetFloor;
        this.cmd = cmd;
    }
}
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.*;

/*
电梯运行过程状态变化
*/
public class EleRunner {

    private List requestList;
    private List inElevatorList = new LinkedList<>();
    PrintWriter out;
    private ElevatorState state = ElevatorState.WAIT;
    private int curFloor = 0;
    private boolean started = false;
    private boolean stop = false;
    public EleRunner(List infoList) throws FileNotFoundException {
        this.requestList = infoList;
        out = new PrintWriter(new FileOutputStream("/Users/macbook/programming/Java/leetcode/src/com/test/output.txt",true),true);
    }
    public void start() {
        while(true) {
            if(requestList.isEmpty()) continue;
            while(started) {
                if(requestList.isEmpty()) {
                    state = ElevatorState.WAIT;
                    continue;
                }
                if(requestList.size()==1 && inElevatorList.isEmpty() && requestList.get(0).cmd.equals("stop")) {
                    out.println("电梯停止运行!");
                    requestList.remove(0);
                    started = false;
                    stop = true;
                    break;
                }
                switch(state) {
                    case WAIT:
                        waitProc();
                        break;
                    case UP:
                        upProc();
                        break;
                    case DOWN:
                        downProc();
                        break;
                    default:
                        throw new IllegalArgumentException();
                }

                if(!requestList.isEmpty()) personIn();//状态更新,可能还可以有人进来
                if(state==ElevatorState.UP || state==ElevatorState.DOWN) {
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    curFloor = (state==ElevatorState.UP)?(curFloor+1):(curFloor-1);
                    String stateStr = (state==ElevatorState.UP)?"上升":"下降";
                    out.println("电梯到达"+curFloor+"楼,处于"+stateStr);
                }
            }
            if(stop) break;
            if(requestList.get(0).cmd.equals("start")) {
                started = true;
                curFloor = requestList.get(0).curFloor;
                out.println("电梯启动!");
                requestList.remove(0);
            }
        }
    }

    private void waitProc() {
        if(requestList.isEmpty()&&inElevatorList.isEmpty()) return;
        else {
            //没有请求但是电梯还载着人
            if(!requestList.isEmpty()) personIn();
            if(!inElevatorList.isEmpty()) personOut();
            if(!inElevatorList.isEmpty()) {
                state = inElevatorList.get(0).targetFloor > curFloor ? state = ElevatorState.UP:ElevatorState.DOWN;
            } else if(isOnlyStopReq()){
                state = ElevatorState.WAIT;
                out.println("电梯处于等待状态");
            } else if(!requestList.isEmpty()){
                if(!requestList.get(0).cmd.equals("stop"))
                    state = requestList.get(0).curFloor > curFloor ? state = ElevatorState.UP:ElevatorState.DOWN;
            }
        }
    }

    private void upProc() {
        if(requestList.isEmpty()&&inElevatorList.isEmpty()) {
            state = ElevatorState.WAIT;
        } else {
            if(!requestList.isEmpty()) personIn();//请求队列不空,看是否可以进人
            if(!inElevatorList.isEmpty()) personOut();//在电梯队列不空,看是否可以放人
            if(!inElevatorList.isEmpty()) {
                for(EleInfo e:inElevatorList) {
                    if(e.targetFloor > curFloor) return;
                }
                state = ElevatorState.DOWN;
            } else if(isOnlyStopReq()){
                state = ElevatorState.WAIT;
                out.println("电梯处于等待状态");
            } else if(!requestList.isEmpty()){
                for(EleInfo e:requestList) {
                    if(!e.cmd.equals("stop")&&e.curFloor > curFloor) return;
                }
                state = ElevatorState.DOWN;
            }
        }
    }

    private void downProc() {
        if(requestList.isEmpty()&&inElevatorList.isEmpty()) {
            state = ElevatorState.WAIT;
            out.println("电梯处于等待状态");
        } else {
            if(!requestList.isEmpty()) personIn();
            if(!inElevatorList.isEmpty()) personOut();
            if(!inElevatorList.isEmpty()) {
                for(EleInfo e:inElevatorList) {
                    if(e.targetFloor < curFloor) return;
                }
                state = ElevatorState.UP;
            } else if(isOnlyStopReq()){
                state = ElevatorState.WAIT;
                out.println("电梯处于等待状态");

            } else if(!requestList.isEmpty()){
                for(EleInfo e:requestList) {
                    if(!e.cmd.equals("stop")&&e.curFloor < curFloor) return;
                }
                state = ElevatorState.UP;
            }
        }
    }

    private void personIn() {
        Iterator iterator = requestList.iterator();
        while(iterator.hasNext()) {//将curFloor等于电梯curFloor的请求删除,并放入inElevatorList中
            EleInfo e = iterator.next();
            if(e.curFloor==curFloor&&(state==ElevatorState.UP?(e.cmd.equals("up")):e.cmd.equals("down"))) {
                out.println(e.name+"在"+curFloor+"楼进电梯了!");
                iterator.remove();
                inElevatorList.add(e);
            }
        }
    }
    private void personOut() {
        Iterator iterator = inElevatorList.iterator();
        while(iterator.hasNext()) {//首先把在电梯上目标楼层是当前楼层的人放出
            EleInfo e = iterator.next();
            if(e.targetFloor == curFloor) {
                out.println(e.name+"在"+curFloor+"楼出电梯了!");
                iterator.remove();
            }
        }
    }
    private boolean isOnlyStopReq() {
        return requestList.size()==1&&requestList.get(0).cmd.equals("stop");
    }

}


enum ElevatorState {
    WAIT,
    UP,
    DOWN
}


输入示例:

1 20
start
up
hjx 2 10
down
hyk 6 2
up
hyk1 1 8
down
hjx2 15 2
stop

输出结果:

电梯启动!
hyk1在1楼进电梯了!
电梯到达2楼,处于上升
hjx在2楼进电梯了!
电梯到达3楼,处于上升
电梯到达4楼,处于上升
电梯到达5楼,处于上升
电梯到达6楼,处于上升
电梯到达7楼,处于上升
电梯到达8楼,处于上升
hyk1在8楼出电梯了!
电梯到达9楼,处于上升
电梯到达10楼,处于上升
hjx在10楼出电梯了!
电梯到达11楼,处于上升
电梯到达12楼,处于上升
电梯到达13楼,处于上升
电梯到达14楼,处于上升
电梯到达15楼,处于上升
hjx2在15楼进电梯了!
电梯到达14楼,处于下降
电梯到达13楼,处于下降
电梯到达12楼,处于下降
电梯到达11楼,处于下降
电梯到达10楼,处于下降
电梯到达9楼,处于下降
电梯到达8楼,处于下降
电梯到达7楼,处于下降
电梯到达6楼,处于下降
hyk在6楼进电梯了!
电梯到达5楼,处于下降
电梯到达4楼,处于下降
电梯到达3楼,处于下降
电梯到达2楼,处于下降
hjx2在2楼出电梯了!
hyk在2楼出电梯了!
电梯处于等待状态
电梯停止运行!

可以观察一下输入的记录和电梯运行的结果,还是挺符合生活习惯的。

你可能感兴趣的:(电梯运行程序模拟)