总结性Blog01:java单部电梯调度系统迭代

一、前言

  对三周中三次pta题目集进行总结。

难度:中等偏上。在第一周后期老师的点拨之下大致明白了题目想要表达的意思,之后编写代码的过程就相对顺理成章的完成了。一共六个测试点通过了四个。
题量:中等。虽不能通过所有测试点,但能在规定时间内提交。
知识点:look,面向对象设计,队列处理,状态管理,枚举,数组,链表,正则表达式,单一职责。将本阶段所学习的知识进行运用。

二、设计与分析

  本部分将基于报表和类图对源代码进行分析。

·代码设计思路(最终版本):
代码要求对一次性输入的请求进行处理。
1.通过正则表达式,ArrayList等方式将外部请求和内部请求分装,每次仅处理队首。
2.当只有其中一个队列有请求时处理这个队列的请求。
3.以电梯运行方向为优先,优先前往与电梯运行方向相同的请求。
4.当两个请求方向相同时,优先前往去到该请求电梯运行的方向与当前电梯运行方向相同的请求。
5.当上面一个判断条件还相同时,前往更近的楼层。
6.当上面一个判断条件还相同时,同时响应两个请求。
ps1:每次响应外部请求时将电梯运行方向改为与外部请求方向相同。
ps2:标记响应的是外部请求还是内部请求,以免出现错误删除请求的情况。
ps3:第二次实验需要删除重复项。
ps4:第三次实验需要根据楼层判断外部请求方向,并在响应外部请求后添加目标楼层到内部序列中。
1、第一次题目
源代码:

点击查看代码
import java.util.*;

class Elevator
{
    enum Direction{UP,DOWN,IDLE}

    private int minFloor;
    private int maxFloor;
    private int currentFloor = 1;
    private Direction direction = Direction.UP;
    private ArrayList<String> innerQueue = new ArrayList<>();
    private ArrayList<String> outerQueue = new ArrayList<>();
    public Elevator(int minFloor,int maxFloor)
    {
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
    }
    public void addInnerRequest(int floor)
    {
        if (floor >= minFloor && floor <= maxFloor)
        {
            innerQueue.add(String.valueOf(floor));
        }
    }
    public void addOuterRequest(int floor,Direction dir)
    {
        if (floor >= minFloor && floor <= maxFloor)
        {
            outerQueue.add(floor + "," + dir.name());
        }
    }
    public void processRequests()
    {
        while (!innerQueue.isEmpty() || !outerQueue.isEmpty())
        {
            int nextFloor = determineNextFloor();
            setDirection(nextFloor);
            moveToFloor(nextFloor);
            arriveAtFloor(nextFloor);
        }
    }

private int determineNextFloor() {

    if (innerQueue.isEmpty() && outerQueue.isEmpty()) {
        return currentFloor;
    }
    
    // 情况2:只有内部队列有请求
    if (outerQueue.isEmpty()) {
        return Integer.parseInt(innerQueue.get(0));
    }
    
    // 情况3:只有外部队列有请求
    if (innerQueue.isEmpty()) {
        String[] parts = outerQueue.get(0).split(",");
        return Integer.parseInt(parts[0]);
    }
    
    // 情况4:两个队列都有请求
    String[] parts = outerQueue.get(0).split(",");
    int ifloor = Integer.parseInt(innerQueue.get(0));
    int efloor = Integer.parseInt(parts[0]);
    
    // 确定方向
    Direction idir = currentFloor > ifloor ? Direction.DOWN : Direction.UP;
    Direction edir = Direction.valueOf(parts[1]);

    // 决策逻辑
    if (direction == Direction.IDLE || 
        (direction != idir && direction != edir) || 
        (direction == idir && direction == edir)) {
        return nearestgoal();
    }

    if (direction == idir) return ifloor;
    if (direction == edir) return efloor;

    return currentFloor;
}
    private int nearestgoal()
    {
        int nearestFloor = 0;
        int minDistance = 20;

        //内部队列
        if (!innerQueue.isEmpty())
        {
            int floor = Integer.parseInt(innerQueue.get(0));
            int distance = Math.abs(floor - currentFloor);
            if(distance < minDistance)
            {
                minDistance = distance;
                nearestFloor = floor;
            }
        }

        //外部队列
        if(!outerQueue.isEmpty())
        {
            String[] parts = outerQueue.get(0).split(",");
            int floor = Integer.parseInt(parts[0]);
            int distance = Math.abs(floor - currentFloor);
            if(distance < minDistance)
            {
                minDistance = distance;
                nearestFloor = floor;
            }
        }
        return nearestFloor;
    }

    private void setDirection(int targetFloor)//设置电梯方向
    {
        if (targetFloor > currentFloor)
            direction = Direction.UP;
        else if (targetFloor < currentFloor)
            direction = Direction.DOWN;
        else
            direction = Direction.IDLE;
    }

    private void moveToFloor(int targetFloor)//前往目标楼层
    {
        while (currentFloor != targetFloor)
        {
            if(direction == Direction.UP)currentFloor++;
            else if(direction == Direction.DOWN)currentFloor--;
            
            System.out.printf("Current Floor: %d Direction: %s\n",currentFloor,direction == Direction.UP ? "UP" : "DOWN");
        }
    }

    private void arriveAtFloor(int floor)//到达目标楼层后先开关门,再移除相应的队头
    {
        System.out.printf("Open Door # Floor %d\nClose Door\n",floor);
        
        if(!innerQueue.isEmpty() && Integer.parseInt(innerQueue.get(0)) == floor)
            innerQueue.remove(0);
        
        if(!outerQueue.isEmpty())
        {
            String[] parts = outerQueue.get(0).split(",");
            if(Integer.parseInt(parts[0]) == floor)
                outerQueue.remove(0);
        }
    }
}

public class Main
{
    public static void main(String[] args)
    {
        Scanner input = new Scanner(System.in);
        ArrayList<String> inputList = new ArrayList<>();
        
        // 读取输入
        while (input.hasNext()) {
            String data = input.next();
            if (data.equalsIgnoreCase("end")) {
                break;
            }
            inputList.add(data);
        }
        
        int minFloor = Integer.parseInt(inputList.get(0));
        int maxFloor = Integer.parseInt(inputList.get(1));

        Elevator elevator = new Elevator(minFloor, maxFloor);

        // 处理请求
        for (int i = 2; i < inputList.size(); i++) {
            String request = inputList.get(i);
                if (request.contains(",")) { // 外部请求
                    String[] parts = request.replaceAll("[<>]", "").split(",");
                    int floor = Integer.parseInt(parts[0].trim());
                    Elevator.Direction dir = Elevator.Direction.valueOf(parts[1].trim().toUpperCase());
                    elevator.addOuterRequest(floor,dir);
                } else { // 内部请求
                    int floor = Integer.parseInt(request.replaceAll("[<>]", ""));
                    elevator.addInnerRequest(floor);
                }
        }
        System.out.println("Current Floor: 1 Direction: UP");
        elevator.processRequests();
        input.close();
    }
}

类图:

SourceMontor的生成报表:

  对报表进行分析:
  1.控制流复杂:
  最深嵌套块达到5层,逻辑理解难度大。
  ·由于这是迭代前的代码,所有的方法都放置在一个类中,故一些基于方法放置在一个类中的问题不会分析。
  ·其余问题在第三次题目中也有体现,在此不过多赘述。

2、第二次题目
源代码:

点击查看代码
import java.util.*;

class Elevator//电梯类
{
	enum State{MOVING,STOPPED}
	enum Direction{UP,DOWN,IDLE}
	private int maxFloor;
	private int minFloor;
	private int currentFloor = 1;
	private Direction direction = Direction.UP;
	private State state = State.STOPPED; 
	public Elevator(int minFloor,int maxFloor) {this.minFloor = minFloor;this.maxFloor = maxFloor;}
	public int getCurrentFloor() {return currentFloor;}
	public void setCurrentFloor(int currentFloor) {this.currentFloor = currentFloor;}
	public State getState() {return state;}
	public void setState(State state) {this.state = state;}
	public Direction getDirection() {return direction;}
	public void setDirection(Direction direction) {this.direction = direction;}
	public int getMaxFloor() {return maxFloor;}
	public int getMinFloor() {return minFloor;}
	
	public boolean isValidFloor(int floor)//判断楼层是否有效
	{
		if(floor>maxFloor||floor<minFloor)return false;
		return true;
	}
	public Elevator getElevatorInstance(int minFloor,int maxFloor) //返回新实例
	{
		return new Elevator(minFloor, maxFloor);
	}
}
class Controller//控制类
{
	private Elevator elevator;
	private RequestQueue queue;
	public Controller() {}
	public Controller(Elevator elevator,RequestQueue queue) {this.elevator = elevator;this.queue = queue;}
	public Elevator getElevator() {return elevator;}
	public void setElevator(Elevator elevator) {this.elevator = elevator;}
	public RequestQueue getQueue() {return queue;}
	public void setQueue(RequestQueue queue) {this.queue = queue;}
	
	public void processRequests()//处理请求
	{
		while (!queue.getInternalRequests().isEmpty() || !queue.getExternalRequests().isEmpty())
        {
			int next = getNextFloor();
            ditermineDirection(next);
            move(next);
            removeRequests(next);
        }
	}
	private void ditermineDirection(int next)//确定方向
	{
		if (next > elevator.getCurrentFloor())
			elevator.setDirection(Elevator.Direction.UP);
        else if (next < elevator.getCurrentFloor())
        	elevator.setDirection(Elevator.Direction.DOWN);
        else
        	elevator.setDirection(Elevator.Direction.IDLE);
	}
	private void move(int next)//电梯移动
	{
		while (shouldStop(next))
        {
            if(elevator.getDirection() == Elevator.Direction.UP)
            {
            	int n = elevator.getCurrentFloor();
            	n++;
            	elevator.setCurrentFloor(n);
            }
            else if(elevator.getDirection() == Elevator.Direction.DOWN)
            {
            	int n = elevator.getCurrentFloor();
            	n--;
            	elevator.setCurrentFloor(n);
            }
            
            System.out.printf("Current Floor: %d Direction: %s\n",elevator.getCurrentFloor(),elevator.getDirection() == Elevator.Direction.UP ? "UP" : "DOWN");
        }
	}
	private boolean shouldStop(int next)//判断电梯是否应该停下
	{
		if(elevator.getCurrentFloor() != next)return true;
		return false;
	}
	private Integer getNextFloor()//获取下一次要去的楼层
	{
		if (queue.getInternalRequests().isEmpty() && queue.getExternalRequests().isEmpty()) {
	        return elevator.getCurrentFloor();
	    }
	    
	    //只有内部队列有请求
	    if (queue.getExternalRequests().isEmpty()) {
	    	return queue.getInternalRequests().get(0);
	    }
	    
	    //只有外部队列有请求
	    if (queue.getInternalRequests().isEmpty()) {
	    	ExternalRequest externalRequest = queue.getExternalRequests().get(0);
	        return externalRequest.getFloor();
	    }
	    
	    //两个队列都有请求
	    ExternalRequest externalRequest = queue.getExternalRequests().get(0);
        int ifloor = queue.getInternalRequests().get(0);
        int efloor = externalRequest.getFloor();
	    
	    //确定方向
	    Elevator.Direction idir = elevator.getCurrentFloor() > ifloor ? Elevator.Direction.DOWN : Elevator.Direction.UP;
	    ExternalRequest.Direction edir = externalRequest.getDirection();

	    //决策逻辑
	    if (elevator.getDirection() == Elevator.Direction.IDLE || 
	            (elevator.getDirection() != idir && elevator.getDirection() != Elevator.Direction.valueOf(edir.name())) || 
	            (elevator.getDirection() == idir && elevator.getDirection() == Elevator.Direction.valueOf(edir.name()))) {
	            return getClosest(0,200000);
	        }

	    if (elevator.getDirection() == idir) return ifloor;
	    if (elevator.getDirection() == Elevator.Direction.valueOf(edir.name())) return efloor;

	    return elevator.getCurrentFloor();
	}
	private Integer getClosest(Integer a,Integer b)//获得最近的楼层
	{
		int nearestFloor = a;
        //int minDistance = b;
        
        //改
        ExternalRequest externalRequest = queue.getExternalRequests().get(0);
        int ifloor = queue.getInternalRequests().get(0);//内部请求
        int efloor = externalRequest.getFloor();//外部请求
        int idistance = Math.abs(ifloor - elevator.getCurrentFloor());//内部距离
        int edistance = Math.abs(efloor - elevator.getCurrentFloor());//外部距离
        /*
        if(idistance!=edistance)
        nearestFloor = (idistance > edistance ) ? efloor :ifloor;
        else 
        {
        	Elevator.Direction idir = elevator.getCurrentFloor() > ifloor ? Elevator.Direction.DOWN : Elevator.Direction.UP;
        	//Elevator.Direction edir = elevator.getCurrentFloor() > efloor ? Elevator.Direction.DOWN : Elevator.Direction.UP;
        	nearestFloor = (elevator.getDirection() == idir ) ? ifloor :efloor;
        }
       */
        Elevator.Direction idir = elevator.getCurrentFloor() > ifloor ? Elevator.Direction.DOWN : Elevator.Direction.UP;
        Elevator.Direction edir = elevator.getCurrentFloor() > efloor ? Elevator.Direction.DOWN : Elevator.Direction.UP;
        
        if(idir==edir)
        {
        	nearestFloor = (idistance > edistance ) ? efloor :ifloor;
        }
        else nearestFloor = (elevator.getDirection() == idir ) ? ifloor :efloor;
        return nearestFloor;
	}
	private void openDoors()//输出开门
	{
		System.out.printf("Open Door # Floor %d\nClose Door\n",elevator.getCurrentFloor());
	}
	private void removeRequests(int next)//移除请求
	{
		openDoors();
		
		if(!queue.getInternalRequests().isEmpty() && queue.getInternalRequests().get(0) == next)
			queue.getInternalRequests().remove(0);
        
        if(!queue.getExternalRequests().isEmpty())
        {
        	ExternalRequest externalRequest = queue.getExternalRequests().get(0);
            if(externalRequest.getFloor() == next)//路过的狗都被你删掉了
            {
            	elevator.setDirection(Elevator.Direction.valueOf(externalRequest.getDirection().name()));
            	queue.getExternalRequests().remove(0);
            }
        }
	}
	
}
class RequestQueue//请求队列
{
	private Elevator elevator;
	private LinkedList<Integer> internalRequests = new LinkedList<>();
	private LinkedList<ExternalRequest> externalRequests = new LinkedList<>();
	public RequestQueue() {}
	public RequestQueue getQueueInstance() {return new RequestQueue();}
	public LinkedList<Integer> getInternalRequests(){return internalRequests;}
	public void setInternalRequests(LinkedList<Integer> internalRequests) {this.internalRequests = internalRequests;}
	public LinkedList<ExternalRequest> getExternalRequests(){return externalRequests;}
	public void setExternalRequests(LinkedList<ExternalRequest> externalRequests) {this.externalRequests = externalRequests;}
	public void setElevator(Elevator elevator) {this.elevator = elevator;}
	
	public void addInternalRequest(int floor)//添加内部请求
	{
		if (elevator != null &&elevator.isValidFloor(floor))
        {
			internalRequests.add(floor);
        }
	}
	public void addExternalRequest(int floor,ExternalRequest.Direction direction)//添加外部请求
	{
		if (elevator != null &&elevator.isValidFloor(floor))
        {
			externalRequests.add(new ExternalRequest(floor,direction));
        }
	}
}
class ExternalRequest//外部请求
{
	enum Direction{UP,DOWN,IDLE}
	private Integer floor;
	private Direction direction;
	public ExternalRequest(Integer floor,Direction direction)
	{
		this.floor = floor;
		this.direction = direction;
    }
	public Integer getFloor() {return floor;}
	public Direction getDirection() {return direction;}
}
public class Main {
	
	public static void removeConsecutiveDuplicates(ArrayList<String> list) {
        if (list.isEmpty()) {
            return;
        }
        int i = 0;
        while (i < list.size() - 1) {
            if (list.get(i).equals(list.get(i + 1))) {
                list.remove(i + 1);
            } else {
                i++;
            }
        }
    }
	
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		ArrayList<String> inputList = new ArrayList<>();
        
        // 读取输入
        while (input.hasNext()) {
            String data = input.next();
            if (data.equalsIgnoreCase("end")) {
                break;
            }
            inputList.add(data);
        }
        
        int minFloor = Integer.parseInt(inputList.get(0));
        int maxFloor = Integer.parseInt(inputList.get(1));
        
        removeConsecutiveDuplicates(inputList);//去重
        
        Elevator elevator = new Elevator(minFloor, maxFloor);
        RequestQueue queue = new RequestQueue();
        queue.setElevator(elevator);
        Controller controller = new Controller(elevator, queue);
        
        for (int i = 2; i < inputList.size(); i++) 
        {
            String request = inputList.get(i);
            if (request.contains(",")) 
            { // 外部请求
                String[] parts = request.replaceAll("[<>]", "").split(",");
                int floor = Integer.parseInt(parts[0].trim());
                ExternalRequest.Direction dir = ExternalRequest.Direction.valueOf(parts[1].trim().toUpperCase());
                queue.addExternalRequest(floor,dir);
            } 
            else 
            { // 内部请求
                int floor = Integer.parseInt(request.replaceAll("[<>]", ""));
                queue.addInternalRequest(floor);
            }
        }
        
        System.out.println("Current Floor: 1 Direction: UP");
        controller.processRequests();
        input.close();
	}

}

类图:

SourceMontor的生成报表:

  对报表进行分析:
  1.代码坏味道:
  ditermineDirection()存在拼写错误,getClosest(a,b)包含未使用参数。
  ·其余问题在第三次题目中也有体现,在此不过多赘述。

3、第三次题目
源代码:

点击查看代码

import java.util.*;
class Elevator
{
	enum Direction{UP,DOWN,IDLE}
	private int maxFloor;
	private int minFloor;
	private int currentFloor = 1;
	private Direction direction = Direction.UP;
	public Direction getDirection(){return direction;}
	public void setDirection(Direction direction) {this.direction = direction;}
	public int getCurrentFloor(){return currentFloor;}
	public void setCurrentFloor(int currentFloor){this.currentFloor = currentFloor;}
	public Elevator(int maxFloor,int minFloor)
	{
		this.maxFloor = maxFloor;
		this.minFloor = minFloor;
	}
	public boolean isVaildFloor(int floor)
	{
		if(floor>maxFloor||floor<minFloor)return false;
		return true;
	}
}
class Passenger
{
	enum Direction{UP,DOWN}
	private int sourceFloor = 0;
	private int destinationFloor = 0;
	public Passenger(int sourceFloor)//内部乘客
	{
		this.sourceFloor = sourceFloor;
	}
	public Passenger(int sourceFloor,int destinationFloor) //外部乘客
	{
		this.sourceFloor = sourceFloor;
		this.destinationFloor = destinationFloor;
	}
	public int getSourceFloor() {
		return sourceFloor;
	}
	public void setSourceFloor(int sourceFloor) {
		this.sourceFloor = sourceFloor;
	}
	public int getDestinationFloor() {
		return destinationFloor;
	}
	public void setDestinationFloor(int destinationFloor) {
		this.destinationFloor = destinationFloor;
	}
	public Direction getDirection()
	{
		if(sourceFloor>destinationFloor)return Direction.DOWN;
		else return Direction.UP;
	}
}
class RequestQueue
{
	LinkedList<Passenger> externalrequests = new LinkedList<>();
	LinkedList<Passenger> internalrequests = new LinkedList<>();
	public RequestQueue() {}
	public LinkedList<Passenger> getExternalRequests() {
		return externalrequests;
	}

	public void setExternalRequests(LinkedList<Passenger> externalrequests) {
		this.externalrequests = externalrequests;
	}

	public LinkedList<Passenger> getInternalRequests() {
		return internalrequests;
	}

	public void setInternalRequests(LinkedList<Passenger> internalrequests) {
		this.internalrequests = internalrequests;
	}

	public void addExternalRequest(int sourceFloor,int destinationFloor)
	{
		externalrequests.add(new Passenger(sourceFloor,destinationFloor));
	}
	public void addInternalRequest(int Floor)
	{
		internalrequests.add(new Passenger(Floor));
	}
}
class Controller
{
	enum Lift{inter,exter,all}
	private Lift lift;
	private Elevator elevator;
	private RequestQueue requestQueue;
	public Controller(Elevator elevator, RequestQueue requestQueue) 
	{
		this.elevator = elevator;
        this.requestQueue = requestQueue;
	}
	public int getNextFloor()
	{
		if (requestQueue.getInternalRequests().isEmpty() && requestQueue.getExternalRequests().isEmpty()) {
	        return elevator.getCurrentFloor();
	    }
	    
	    //只有内部队列有请求
	    if (requestQueue.getExternalRequests().isEmpty()) {
	    	lift = Lift.inter;
	    	return requestQueue.getInternalRequests().getFirst().getSourceFloor();
	    }
	    
	    //只有外部队列有请求
	    if (requestQueue.getInternalRequests().isEmpty()) {
	    	lift = Lift.exter;
	        return requestQueue.getExternalRequests().getFirst().getSourceFloor();
	    }
	    
	    //两个队列都有请求
	    int ifloor = requestQueue.getInternalRequests().getFirst().getSourceFloor();
        int efloor = requestQueue.getExternalRequests().getFirst().getSourceFloor();
		
	    //确定方向
	    Elevator.Direction cdir = elevator.getDirection();
	    Elevator.Direction idir = elevator.getCurrentFloor() > ifloor ? Elevator.Direction.DOWN : Elevator.Direction.UP;
	    Elevator.Direction edir = Elevator.Direction.valueOf(requestQueue.getExternalRequests().getFirst().getDirection().name());

	    //决策逻辑
	    if (cdir == idir && cdir != edir) {lift = Lift.inter;return ifloor;}
	    if (cdir == edir && cdir != idir) {lift = Lift.exter;return efloor;}
	    
	    if ( cdir == Elevator.Direction.IDLE || (cdir != idir && cdir != edir) || (cdir == idir && cdir == edir) ) 
	    {
	        return getClosest();
	    }
	    return elevator.getCurrentFloor();

	}
	public void removeRequests()
	{
		if(lift == Lift.inter && !requestQueue.getInternalRequests().isEmpty())
		{
			requestQueue.getInternalRequests().remove(0);
		}
		if(lift == Lift.exter && !requestQueue.getExternalRequests().isEmpty())
		{
			requestQueue.getExternalRequests().remove(0);
		}
        if(lift==Lift.all && !requestQueue.getExternalRequests().isEmpty() && !requestQueue.getInternalRequests().isEmpty() )
        {
            requestQueue.getInternalRequests().remove(0);
            requestQueue.getExternalRequests().remove(0);
        }
	}
	public int getClosest()
	{
		int cfloor = elevator.getCurrentFloor();
		int ifloor = 0;
		int efloor = 0;
		if(!requestQueue.getInternalRequests().isEmpty()&&!requestQueue.getExternalRequests().isEmpty()) 
		{
			ifloor = requestQueue.getInternalRequests().getFirst().getSourceFloor();
			efloor = requestQueue.getExternalRequests().getFirst().getSourceFloor();
		}
		Elevator.Direction idir = elevator.getCurrentFloor() > ifloor ? Elevator.Direction.DOWN : Elevator.Direction.UP;
		//if(elevator.getCurrentFloor() == ifloor)  idir = Elevator.Direction.IDLE;
		Elevator.Direction edir = elevator.getCurrentFloor() > efloor ? Elevator.Direction.DOWN : Elevator.Direction.UP;
		//if(elevator.getCurrentFloor() == efloor)  edir = Elevator.Direction.IDLE;
		Elevator.Direction cdir = elevator.getDirection();
		
		if( cdir == idir && cdir != edir) {lift = Lift.inter;return ifloor;}
		if( cdir != idir && cdir == edir) {lift = Lift.exter;return efloor;}
		if( cdir == idir && cdir == edir) 
		{
			int idistance = Math.abs(cfloor-ifloor);
			int edistance = Math.abs(cfloor-efloor);
            if(idistance==edistance){lift=Lift.all;return ifloor;}
			else if(idistance>edistance){lift = Lift.exter;return efloor;}
			else {lift = Lift.inter;return ifloor;}
		}
		return cfloor;
	}
	public void show(int goalFloor) 
	{
		int curFloor = elevator.getCurrentFloor();
		System.out.printf("Current Floor: %d Direction: %s\n",curFloor,elevator.getDirection());
		if(curFloor==goalFloor)
		{
			System.out.printf("Open Door # Floor %d\n",curFloor);
			System.out.println("Close Door");
		}
	}
	public void determineDirection(int goalFloor)
	{
		if(elevator.getCurrentFloor()<goalFloor)elevator.setDirection(Elevator.Direction.UP);
		else if(elevator.getCurrentFloor()>goalFloor)elevator.setDirection(Elevator.Direction.DOWN);
		else elevator.setDirection(Elevator.Direction.IDLE);
	}
	public void move()
	{
		if(elevator.getDirection()==Elevator.Direction.UP)
		{
			elevator.setCurrentFloor(elevator.getCurrentFloor()+1);
		}
		else if(elevator.getDirection()==Elevator.Direction.DOWN)
		{
			elevator.setCurrentFloor(elevator.getCurrentFloor()-1);
		}
	}
	public void processRequests()
	{
		int goalFloor = getNextFloor();
		while(elevator.getCurrentFloor() != goalFloor)
		{
			determineDirection(goalFloor);
			move();
			show(goalFloor);
		}
		if((lift == Lift.exter||lift==Lift.all) &&!requestQueue.getExternalRequests().isEmpty())
		{
			elevator.setDirection(Elevator.Direction.valueOf(requestQueue.getExternalRequests().getFirst().getDirection().name()));
			requestQueue.addInternalRequest(requestQueue.getExternalRequests().getFirst().getDestinationFloor());
		}
		removeRequests();
	}
}

public class Main {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		ArrayList<String> input = new ArrayList<>();
		while (sc.hasNext()) 
		{
            String data = sc.next();
            if (data.equalsIgnoreCase("end"))
                break;
            input.add(data);
        }
		//Iterator<String> iterator = input.iterator();
		
		int minFloor = Integer.parseInt(input.get(0));
        int maxFloor = Integer.parseInt(input.get(1));
        
        RequestQueue requestQueue = new RequestQueue();
        Elevator elevator = new Elevator(maxFloor,minFloor);
        Controller controller = new Controller(elevator,requestQueue);
        
        for(int i=2;i<input.size();i++)
        {
        	String request = input.get(i);
        	if(request.contains(","))
        	{
        		String[] parts = request.replaceAll("[<>]", "").split(",");
        		int sourceFloor = Integer.parseInt(parts[0]);
        		int destinationFloor = Integer.parseInt(parts[1]);
        		if(elevator.isVaildFloor(sourceFloor)&&elevator.isVaildFloor(destinationFloor))
        		requestQueue.addExternalRequest(sourceFloor,destinationFloor);
        	}
        	else
        	{
        		int Floor = Integer.parseInt(request.replaceAll("[^0-9]", ""));
        		if(elevator.isVaildFloor(Floor))
        		requestQueue.addInternalRequest(Floor);
        	}
        }
        System.out.println("Current Floor: 1 Direction: UP");
        while(!requestQueue.getInternalRequests().isEmpty() || !requestQueue.getExternalRequests().isEmpty())
        {
        	controller.processRequests();
        }
        sc.close();

	}

}

类图:

SourceMontor的生成报表:

  对报表进行分析:
  1.代码复杂度问题:
  主方法复杂度最高,复杂度为11,承担了输入解析、初始化、请求处理等多项职责,违反单一职责原则。
  2.注释不足:
  注释行占比仅3.0%
  3.方法粒度过大:
  平均每个方法4.24条语句,但主方法明显过长。
  4.异常处理缺失:
  Integer.parseInt()可能抛出NumberFormatException。
  5.分支语句占比大:
  分支语句占比18.1%,getNextFloor()和getClosest()中多层嵌套if-else。
  6.Metric提示:
  高方法调用数(91次)。

三、踩坑心得

 本部分将基于编码过程中出现的问题给出心得。

1.错误移除请求
在第二次实验中,发现当外部请求楼层和内部请求楼层相同时,由于我一开始写的代码是当前楼层与目标楼层相同就移除请求,出现了错误移除请求的情况,于是在第三次实验中改进了这个问题。具体改进方法在设计代码思路中已经阐明。
2.正常测试无法得到预期结果
在第二次实验中,由于第一个测试用例一直不通过,我自己写了一个测试用例,发现只要第一个请求为<1,UP>或者<1,DOWN>,那么程序一定会陷入无限循环。原因可能是因为我写的判断方法无法处理这种情况。虽然因为测试用例不是因为运行超时而得不出正确答案,但是也让我认识到我的代码有很多逻辑漏洞,促使我在第三次编码的时候更加谨慎的使用if语句。
3.思路错误导致到不了的彼岸
第二次和第三次都有一个测试的无法通过,通过观察pta的反馈发现,程序在运行测试用例1的时候用了130+ms,在运行其他三个测试用例都只用了120+ms,猜测是因为在某个判断节点判断错误,导致电梯像踢皮球一样在某些楼层中多移动了几次。一旦出现这种情况基本无法在规定时间内排查出错误根源。

四、改进建议

 本部分将基于分析给出自己的见解。

1.将主方法进行细化拆分
将输入处理、系统初始化、运行电梯这三个职责委托出去,降低主方法的复杂度,提高可读性和可维护性。
2.去除硬编码依赖
当前代码中关于电梯初始状态的输出存在硬编码问题,直接固定输出 Current Floor: 1 Direction: UP。这种处理方式源于循环逻辑设计的缺陷,暴露出程序在初始化流程与业务逻辑衔接上的不足。
由于循环设计不合理的问题导致第一行输出采用了硬编码的形式。在先循环再输出和先输出再循环之间选择了先循环再输出,导致第一层楼是输出无法正常进行,于是偷懒直接在循环开始前输出第一层楼的信息。这是不正确的。这种处理方式破坏了代码逻辑的连贯性。
修改建议是修改循环逻辑提升代码的灵活性和逻辑正确性。
3.增加注释
完善代码注释,尤其是关键逻辑和算法部分,便于自己和他人理解代码。由于本次项目时间较长,同时代码修改的次数较多,很多注释在修改的过程中就被删除了。这导致代码的注释覆盖率较低。即使是本人完全明白某个函数是用来干什么的,也需要用注释适当说明函数的用途,方便他人和自己查看。
4.简化分支逻辑
在getNextFloor()和getClosest()等方法中,存在多层嵌套的if语句,导致代码的可读性和可维护性较差。可以考虑采用策略模式或状态模式来重构这些方法,将复杂的决策逻辑封装到独立的策略类或状态类中。
例如,对于电梯选择下一个目标楼层的逻辑,可以定义不同的策略类,如SameDirectionPriorityStrategy(相同方向优先策略)、NearestFloorStrategy(最近楼层优先策略)等,每个策略类实现具体的决策逻辑。在getNextFloor()方法中,根据不同的条件选择合适的策略类来确定下一个目标楼层,这样可以有效减少if语句的嵌套层数,使代码结构更加清晰,逻辑更加简洁,便于后续的修改和扩展。

五、总结

 本部分将对个人的学习习惯和代码上的不足进行反思总结。

1.惯性思维严重
由于第一个题目集只有一个测试点,当这个测试点通过之后,我并没有发现我的代码可能一开始就在逻辑上出现了根本错误,导致后面两次都有测试点无法通过。一但我认定一个事物的逻辑,我就很难改变它,我的思维会不自觉的朝向这个错误的方向进行探索,即使我知道这个方向得不到正确答案。
2.对单一职责的理解不到位
第二次题目集要求在第一次的基础上实现类设计和单一职责,但我仅仅将第一次实验中主方法以外的方法分装了出去,忽视了主方法里面没有做到单一职责。这也导致了在第三次实验中也出现了这个问题。我对单一职责原则的应用不够熟练,需加强理论学习和实践,合理拆分类和方法。
3.异常处理能力的缺失
当代码出现bug或者警告的时候,我不能理解报错的语句,同时也不能理解异常处理的含义,因为平时写代码的时候不会进行错误输入的检测,同时因为大部分编程在pta上进行,不像在eclipse中一有错误就会用波浪线标出,没有系统深入的了解过代码报错和异常等种种原因,导致我在面对此类问题的时候,没有合适的解决方法,甚至完全没有意识到有问题。后续的学习中面对报错的代码,不能再之间通过询问ai来判断代码的问题所在,而因该尝试自己解决。
4.做事拖拉
在长达三周的项目中,我每次都在最后时间卡点完成。例如pta和本次blog的提交都在最后一天完成。这是我本人一个长期以来的坏习惯,事情不到最后都不完成,喜欢踩ddl。这种习惯导致我做事情都会因为时间不足在最后进行取舍,一件事情我最多有80%的完成度。这是一个不好的习惯,我将在下一轮的项目中努力改掉。

 给老师的建议:
 建议老师在发布新一轮迭代作业时,能为前一轮作业提供相应指导与支持。
 进入新一轮时,给出上一轮的测试用例,这样方便同学们发现自己上一轮的不足和错误。
 同时避免错误从上一轮一直带到下一轮,像滚雪球一样越来越多。
 更具体的错误提示,将极大提升我们排查和解决问题的效率。
 拒绝当谜语人,说什么工作了谁给测试用例之类的话。
 如果我们不能确保自己的逻辑是正确的,写出来的测试用例不就是空中楼阁,吃力又不讨好吗?
posted @ 2025-04-20 23:22  有人在做白日梦  阅读(45)  评论(0)    收藏  举报