题目集5~7总结blog
一、前言
总得来说这三次的题目集 特别是三次电梯题目,对我来说就是一个感觉那就是困难,我也不怕老师瞧不起我,我可以诚实的告诉老师,我一次电梯题目都没有拿过满分,这几次的题目集都是每次做完电梯题目之前的题目后我都会小有成就感,但是每当看到电梯题目又成功的浇灭了我来之不易的一点小小的成就感,虽然说这几次的电梯题目非常困难,但也培养了我的逻辑思维和抽象思维、现在我就来总结一下这几次的题目集
1.第五次题目集:题目包括身份证的校验、求解一元二次方程、和利用正则表达式校验验证码、最后就是电梯题目,这次的电梯题目主要是实现单部电梯的基本调度问题,需要我们整理出初步的电梯运行逻辑,主要考察类的基本设计、队列管理和简单调度算法。
2.第六次题目集:题目包括点与线求点之间的距离、雨刷器调档问题、和电梯题目的迭代升级,此次的电梯题目相比于去第一次中的Elevator类,此次要求我们将一个类的功能拆分成多个类来实现,并增加了增加了输入验证和去重功能。主要考察对于不同类的调用能力。
3.第七次题目集:题目包括销售步枪问题、求圆周率问题、和电梯题目的再一次迭代升级,此次电梯题目增加的Passenger类,完善修改了外部请求功能,使逻辑关系变得更加精密,但是也更难以实现。
二、设计与分析
第五次电梯:
这是电梯题目的类图关系:

当我第一次看到这个类图关系,着实被下了一大跳,这么难的题目居然要我这个大一的学生来写,不过现在看来,一步一步的去解决也能做到,虽然我没有得到满分但是我相信我能够做到,
这是我的电梯题目的源码:
import java.util.LinkedList;
import java.util.Scanner;
import java.util.ArrayList;
import java.util.regex.Pattern;
enum Direction {
UP, DOWN
}
enum State {
MOVING, STOPPED
}
class ExternalRequest {
private int floor;
private Direction direction;
public ExternalRequest(int floor, Direction direction) {
this.floor = floor;
this.direction = direction;
}
public int getFloor() {
return floor;
}
public Direction getDirection() {
return direction;
}
}
class RequestQueue {
private LinkedList<Integer> internalRequests = new LinkedList<>();
private LinkedList<ExternalRequest> externalRequests = new LinkedList<>();
public void addInternalRequest(int floor) {
internalRequests.add(floor);
}
public void addExternalRequest(ExternalRequest request) {
externalRequests.add(request);
}
public LinkedList<Integer> getInternalRequests() {
return new LinkedList<>(internalRequests);
}
public LinkedList<ExternalRequest> getExternalRequests() {
return new LinkedList<>(externalRequests);
}
public void removeInternalRequest(int floor) {
internalRequests.removeIf(f -> f == floor);
}
public void removeExternalRequest(int floor) {
externalRequests.removeIf(req -> req.getFloor() == floor);
}
public boolean hasRequests() {
return !internalRequests.isEmpty() || !externalRequests.isEmpty();
}
}
class Elevator {
private int currentFloor;
private Direction direction = Direction.UP; // 初始方向默认为UP
private State state = State.STOPPED;
private final int maxFloor;
private final int minFloor;
private final RequestQueue requestQueue;
public Elevator(int minFloor, int maxFloor) {
this.minFloor = minFloor;
this.maxFloor = maxFloor;
this.currentFloor = minFloor;
this.requestQueue = new RequestQueue();
}
// Getters and setters
public RequestQueue getRequestQueue() { return requestQueue; }
public int getCurrentFloor() { return currentFloor; }
public void setCurrentFloor(int floor) { currentFloor = floor; }
public Direction getDirection() { return direction; }
public void setDirection(Direction dir) { direction = dir; }
public State getState() { return state; }
public void setState(State s) { state = s; }
public void addExternalRequest(int floor, Direction direction) {
if (floor >= minFloor && floor <= maxFloor) {
requestQueue.addExternalRequest(new ExternalRequest(floor, direction));
}
}
public void addInternalRequest(int floor) {
if (floor >= minFloor && floor <= maxFloor) {
requestQueue.addInternalRequest(floor);
}
}
}
class Controller {
private final Elevator elevator;
public Controller(Elevator elevator) {
this.elevator = elevator;
}
public void processRequests() {
// 输出初始状态
System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
boolean initialDirectionSet = false;
while (elevator.getRequestQueue().hasRequests()) {
determineDirection(initialDirectionSet);
move();
initialDirectionSet = true;
}
}
private void determineDirection(boolean initialDirectionSet) {
if (elevator.getState() == State.STOPPED && !initialDirectionSet) {
RequestQueue queue = elevator.getRequestQueue();
int current = elevator.getCurrentFloor();
if (!queue.getInternalRequests().isEmpty()) {
int firstInternalRequest = queue.getInternalRequests().get(0);
elevator.setDirection(firstInternalRequest > current ? Direction.UP : Direction.DOWN);
} else if (!queue.getExternalRequests().isEmpty()) {
ExternalRequest firstExternalRequest = queue.getExternalRequests().get(0);
elevator.setDirection(firstExternalRequest.getDirection());
}
} else if (elevator.getState() == State.STOPPED) {
RequestQueue queue = elevator.getRequestQueue();
int current = elevator.getCurrentFloor();
boolean hasUp = queue.getInternalRequests().stream().anyMatch(f -> f > current) ||
queue.getExternalRequests().stream().anyMatch(req ->
req.getFloor() > current ||
(req.getFloor() == current && req.getDirection() == Direction.UP));
boolean hasDown = queue.getInternalRequests().stream().anyMatch(f -> f < current) ||
queue.getExternalRequests().stream().anyMatch(req ->
req.getFloor() < current ||
(req.getFloor() == current && req.getDirection() == Direction.DOWN));
switch (elevator.getDirection()) {
case UP:
if (!hasUp && hasDown) elevator.setDirection(Direction.DOWN);
break;
case DOWN:
if (!hasDown && hasUp) elevator.setDirection(Direction.UP);
break;
}
}
}
private void move() {
Direction dir = elevator.getDirection();
if (dir == Direction.UP) {
elevator.setCurrentFloor(elevator.getCurrentFloor() + 1);
} else if (dir == Direction.DOWN) {
elevator.setCurrentFloor(elevator.getCurrentFloor() - 1);
} else {
return;
}
System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + dir);
if (shouldStop()) {
handleStop();
} else {
elevator.setState(State.MOVING);
}
}
private boolean shouldStop() {
int current = elevator.getCurrentFloor();
RequestQueue queue = elevator.getRequestQueue();
boolean internalStop = queue.getInternalRequests().contains(current);
boolean externalStop = queue.getExternalRequests().stream().anyMatch(req ->
req.getFloor() == current && (
req.getDirection() == elevator.getDirection() ||
shouldHandleOppositeDirection(req)
)
);
return internalStop || externalStop;
}
private boolean shouldHandleOppositeDirection(ExternalRequest req) {
Direction currentDir = elevator.getDirection();
if (currentDir == Direction.UP) {
return req.getDirection() == Direction.DOWN &&
!hasRequests(req.getFloor(), Direction.UP);
}
if (currentDir == Direction.DOWN) {
return req.getDirection() == Direction.UP &&
!hasRequests(req.getFloor(), Direction.DOWN);
}
return false;
}
private boolean hasRequests(int floor, Direction dir) {
return elevator.getRequestQueue().getInternalRequests().stream().anyMatch(f ->
dir == Direction.UP ? f > floor : f < floor
) || elevator.getRequestQueue().getExternalRequests().stream().anyMatch(req ->
dir == Direction.UP ? req.getFloor() > floor : req.getFloor() < floor
);
}
private void handleStop() {
int current = elevator.getCurrentFloor();
System.out.println("Open Door # Floor " + current);
elevator.getRequestQueue().removeInternalRequest(current);
elevator.getRequestQueue().removeExternalRequest(current);
System.out.println("Close Door");
elevator.setState(State.STOPPED);
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArrayList<String> inputs = new ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (line.equalsIgnoreCase("end")) break;
inputs.add(line);
}
if (inputs.size() < 2) {
System.out.println("Wrong Format");
return;
}
try {
int min = Integer.parseInt(inputs.get(0));
int max = Integer.parseInt(inputs.get(1));
if (min >= max) {
System.out.println("Wrong Format");
return;
}
Elevator elevator = new Elevator(min, max);
Controller controller = new Controller(elevator);
Pattern externalPattern = Pattern.compile("<\\d+,\\s*(UP|DOWN)>", Pattern.CASE_INSENSITIVE);
Pattern internalPattern = Pattern.compile("<\\d+>");
for (int i = 2; i < inputs.size(); i++) {
String req = inputs.get(i).replaceAll("\\s", "");
try {
if (externalPattern.matcher(req).matches()) {
String[] parts = req.substring(1, req.length()-1).split(",");
int floor = Integer.parseInt(parts[0]);
Direction dir = Direction.valueOf(parts[1].toUpperCase());
elevator.addExternalRequest(floor, dir);
} else if (internalPattern.matcher(req).matches()) {
int floor = Integer.parseInt(req.substring(1, req.length()-1));
elevator.addInternalRequest(floor);
}
} catch (Exception e) {
// 忽略格式错误
}
}
controller.processRequests();
} catch (NumberFormatException e) {
System.out.println("Wrong Format");
}
}
}
以下是我对于我自己代码的类与方法的说明:
Direction 和 State 枚举类:定义电梯的方向(UP,DOWN)和状态(MOVING,STOPPED)
ExternalRequest 类:记录外部请求的楼层和方向。
RequestQueue 类:内部请求和外部请求队列。
Elevator 类:当前楼层、方向、状态、最大和最小楼层限制,以及请求队列。
以下是我用SourceMontor的生成报表内容:

代码行数 275 语句数 170 分支语句占比 17.6% 方法调用语句数 94 含注释的代码行占比 1.5% 类和接口数 7 每类方法数 4.14 每方法平均语句数 4.10 最复杂方法的行号 121 最复杂方法的名称 Controller.determineDirection() 最大复杂度 14 最深代码块的行号 256 最大代码块深度 6 平均代码块深度 2.26 平均复杂度 2.24
主要问题:
Elevator类承接的功能实现太多的功能,不利于代码的修改和维护。
内外部的请求逻辑太过混乱,遇到一些特殊的请求程序不能正确的运行。
改进方案:
将Elevator类的部分功能拆分到新建的类中去,
所以我们的第六次题目集来了。。。。。
第六次电梯:
这是电梯题目的类图关系:

这是我此次代码做出修改的地方:
新增加一个Controller类
class Controller {
private final Elevator elevator;
public Controller(Elevator elevator) {
this.elevator = elevator;
}
public void processRequests() {
// 输出初始状态
System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
boolean initialDirectionSet = false;
while (elevator.getRequestQueue().hasRequests()) {
determineDirection(initialDirectionSet);
move();
initialDirectionSet = true;
}
}
private void determineDirection(boolean initialDirectionSet) {
if (elevator.getState() == State.STOPPED && !initialDirectionSet) {
RequestQueue queue = elevator.getRequestQueue();
int current = elevator.getCurrentFloor();
if (!queue.getInternalRequests().isEmpty()) {
int firstInternalRequest = queue.getInternalRequests().get(0);
elevator.setDirection(firstInternalRequest > current ? Direction.UP : Direction.DOWN);
} else if (!queue.getExternalRequests().isEmpty()) {
ExternalRequest firstExternalRequest = queue.getExternalRequests().get(0);
elevator.setDirection(firstExternalRequest.getDirection());
}
} else if (elevator.getState() == State.STOPPED) {
RequestQueue queue = elevator.getRequestQueue();
int current = elevator.getCurrentFloor();
boolean hasUp = queue.getInternalRequests().stream().anyMatch(f -> f > current) ||
queue.getExternalRequests().stream().anyMatch(req ->
req.getFloor() > current ||
(req.getFloor() == current && req.getDirection() == Direction.UP));
boolean hasDown = queue.getInternalRequests().stream().anyMatch(f -> f < current) ||
queue.getExternalRequests().stream().anyMatch(req ->
req.getFloor() < current ||
(req.getFloor() == current && req.getDirection() == Direction.DOWN));
switch (elevator.getDirection()) {
case UP:
if (!hasUp && hasDown) elevator.setDirection(Direction.DOWN);
break;
case DOWN:
if (!hasDown && hasUp) elevator.setDirection(Direction.UP);
break;
}
}
}
private void move() {
Direction dir = elevator.getDirection();
if (dir == Direction.UP) {
elevator.setCurrentFloor(elevator.getCurrentFloor() + 1);
} else if (dir == Direction.DOWN) {
elevator.setCurrentFloor(elevator.getCurrentFloor() - 1);
} else {
return;
}
System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + dir);
if (shouldStop()) {
handleStop();
} else {
elevator.setState(State.MOVING);
}
}
private boolean shouldStop() {
int current = elevator.getCurrentFloor();
RequestQueue queue = elevator.getRequestQueue();
boolean internalStop = queue.getInternalRequests().contains(current);
boolean externalStop = queue.getExternalRequests().stream().anyMatch(req ->
req.getFloor() == current && (
req.getDirection() == elevator.getDirection() ||
shouldHandleOppositeDirection(req)
)
);
return internalStop || externalStop;
}
private boolean shouldHandleOppositeDirection(ExternalRequest req) {
Direction currentDir = elevator.getDirection();
if (currentDir == Direction.UP) {
return req.getDirection() == Direction.DOWN &&
!hasRequests(req.getFloor(), Direction.UP);
}
if (currentDir == Direction.DOWN) {
return req.getDirection() == Direction.UP &&
!hasRequests(req.getFloor(), Direction.DOWN);
}
return false;
}
private boolean hasRequests(int floor, Direction dir) {
return elevator.getRequestQueue().getInternalRequests().stream().anyMatch(f ->
dir == Direction.UP ? f > floor : f < floor
) || elevator.getRequestQueue().getExternalRequests().stream().anyMatch(req ->
dir == Direction.UP ? req.getFloor() > floor : req.getFloor() < floor
);
}
private void handleStop() {
int current = elevator.getCurrentFloor();
System.out.println("Open Door # Floor " + current);
elevator.getRequestQueue().removeInternalRequest(current);
elevator.getRequestQueue().removeExternalRequest(current);
System.out.println("Close Door");
elevator.setState(State.STOPPED);
}
}
类与方法的说明:
Controller 类:控制一个电梯实例
processRequests():处理所有请求直到队列为空。determineDirection():根据当前状态和请求确定电梯方向。move():电梯根据方向移动,并在必要时停止。shouldStop():判断是否需要在当前楼层停止。shouldHandleOppositeDirection():辅助判断是否处理相反方向的请求。hasRequests():检查指定方向的请求。

passenger类。然后删除了ExternalRequest类class Passenger
{
Integer sourceFloor=null;
Integer destinationFloor=null;
public Passenger(Integer sourceFloor, Integer destinationFloor)
{
this.sourceFloor = sourceFloor;
this.destinationFloor = destinationFloor;
}
public Passenger(Integer destinationFloor)
{
this.destinationFloor = destinationFloor;
}
public Integer getSourceFloor()
{
return sourceFloor;
}
public void setSourceFloor(Integer sourceFloor)
{
this.sourceFloor = sourceFloor;
}
public Integer getDestinationFloor()
{
return destinationFloor;
}
public void setDestinationFloor(Integer destinationFloor)
{
this.destinationFloor = destinationFloor;
}
public Direction getDirection()
{
if(sourceFloor<destinationFloor)
{
return Direction.UP;
}
else if(sourceFloor>destinationFloor)
{
return Direction.DOWN;
}
return Direction.IDLE;
}
}

Main.processInputRequests()Controller.determineDirection()方法的复杂度过高,可能需要重构以降低复杂度,提高可维护性。
浙公网安备 33010602011771号