NCHU-OO-前三次大作业总结 - AC

news/2025/11/19 23:26:25/文章来源:https://www.cnblogs.com/xqyy/p/19243806

一、前言

(三次大作业概括)

  • 第一次大作业覆盖了基础算法(身份证校验位计算)、面向对象入门(一元二次方程类设计)、字符串处理(正则表达式验证)等知识点,以及第一次电梯调度作业;
  • 第二次大作业覆盖了复杂类设计(点与线的关系)、状态模式应用(雨刷控制系统)、数据验证(坐标范围检查)等知识点,以及第二次电梯调度作业,对之前电梯调度程序进行迭代性设计,目的是解决电梯类职责过多的问题;
  • 第三次大作业覆盖了业务建模(销售系统设计)、数学算法(蒙特卡洛方法)、佣金计算逻辑、仿真算法实现,以及第三次电梯调度作业,对之前电梯调度程序再次进行迭代性设计,加入乘客类。

总的来说就是从基础语法到面向对象设计,再到算法应用。难度逐步提升,符合学习规律,让我更加灵活的掌握运用SRP。

二、单部电梯调度设计与分析(失败版)

第一次电梯调度

原题

设计一个电梯类,具体包含电梯的最大楼层数、最小楼层数(默认为1层)当前楼层、运行方向、运行状态,以及电梯内部乘客的请求队列和电梯外部楼层乘客的请求队列,其中,电梯外部请求队列需要区分上行和下行。
电梯运行规则如下:电梯默认停留在1层,状态为静止,当有乘客对电梯发起请求时(各楼层电梯外部乘客按下上行或者下行按钮或者电梯内部乘客按下想要到达的楼层数字按钮),电梯开始移动,当电梯向某个方向移动时,优先处理同方向的请求,当同方向的请求均被处理完毕然后再处理相反方向的请求。电梯运行过程中的状态包括停止、移动中、开门、关门等状态。当电梯停止时,如果有新的请求,就根据请求的方向或位置决定移动方向。电梯在运行到某一楼层时,检查当前是否有请求(访问电梯内请求队列和电梯外请求队列),然后据此决定移动方向每次移动一个楼层,检查是否有需要停靠的请求,如果有,则开门,处理该楼层的请求,然后关门继续移动
使用键盘模拟输入乘客的请求,此时要注意处理无效请求情况,例如无效楼层请求,比如超过大楼的最高或最低楼层。还需要考虑电梯的空闲状态,当没有请求时,电梯停留在当前楼层
请编写一个Java程序,设计一个电梯类,包含状态管理、请求队列管理以及调度算法,并使用一些测试用例,模拟不同的请求顺序,观察电梯的行为是否符合预期,比如是否优先处理同方向的请求,是否在移动过程中处理顺路的请求等。为了降低编程难度,不考虑同时有多个乘客请求同时发生的情况,即采用串行处理乘客的请求方式(电梯只按照规则响应请求队列中当前的乘客请求,响应结束后再响应下一个请求),具体运行规则详见输入输出样例。

输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。

  • 电梯内乘客请求格式:<楼层数>
  • 电梯外乘客请求格式:<乘客所在楼层数,乘梯方向>,其中,乘梯方向用UP代表上行,用DOWN代表下行(UP、DOWN必须大写)。
  • 当输入“end”时代表输入结束(end不区分大小写)。

输出格式:
模拟电梯的运行过程,输出方式如下:

  • 运行到某一楼层(不需要停留开门),输出一行文本:
    Current Floor: 楼层数 Direction: 方向
  • 运行到某一楼层(需要停留开门)输出两行文本:
    Open Door # Floor 楼层数
    Close Door

感悟

第一次写这道电梯调度题目的时候,写了巨久,最后还是没写出来TAT。
“世上无难事只要肯放弃”(bushi),于是再也没尝试(也是没想到后面两次大作业还有迭代了)包括在第一次作业堪堪结束之前,同学给我分享了一个博客,里面是一位同学关于电梯调度的心得,但是由于本人的懒惰并没有去研究。包括这一次主要依赖AI,用AI的后果就是它一直会删除两个队列中所有的目的楼层的元素,因为不是自己写的所有花了很多时间才发现问题在哪里。
image

  1. 刚开始写的时候只想到了一个队列,不清除为什么需要内部队列和外部队列,再之后看了老师给的look算法,才联想到现实的电梯……内部只需要选择要去哪层,外部在某一楼层选择上或者下。
  2. 因为是采用串行处理乘客的请求方式(电梯只按照规则响应请求队列中当前的乘客请求,响应结束后再响应下一个请求),所以在移除请求的时候只能移除当前请求,而不是把队列中所有的相同楼层的请求全移除,
  3. 类设计也和粗糙,并且就一个测试点,最后提交的代码只能通过题目给的测试案例,自己找了几个测试案例才发现错的有多离谱。以下,一些测试案例:

同楼层多方向请求
输入
1
10
<5,UP>
<5,DOWN>
end
输出(感觉是错的)
Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Open Door # Floor 5
Close Door
Current Floor: 6 Direction: UP
Current Floor: 5 Direction: DOWN
Open Door # Floor 5
Close Door


端点楼层方向冲突
1
10
<1> # 最小楼层
<10> # 最大楼层
<1,DOWN> # 最小楼层下行请求(应忽略方向)
<10,UP> # 最大楼层上行请求(应忽略方向)
end


边界楼层测试(运行超时了)
1 10
<1,UP>
<10,DOWN>
end


  1. 对于方向和下一层楼层的选择想的有点过于简单了,比如只单纯考虑电梯当前运行方向和两个队列的楼层大小关系。

第二次电梯调度作业

第一次迭代
对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客请求类、队列类以及控制类,具体设计可参考如下类图。(我基本都是按老师给的类图来设计的,就不另外再画类图了:))
image
电梯运行规则与前阶段单类设计相同,但要处理如下情况: 电梯运行规则与前阶段单类设计相同,但要处理如下情况:

  • 乘客请求楼层数有误,具体为高于最高楼层数或低于最低楼层数,处理方法:程序自动忽略此类输入,继续执行
  • 乘客请求不合理,具体为输入时出现连续的相同请求,例如<3><3><3>或者<5,DOWN><5,DOWN>,处理方法:程序自动忽略相同的多余输入,继续执行,例如<3><3><3>过滤为<3>

代码质量分析报告

虽然我的代码并没有实现正确的功能,但我还是分析了一下代码质量,就当学习一下如何使用这个软件。

image
image
image

1.项目总体指标

参数 解释
分支语句 (if/switch/循环) 占比28.4%
方法调用语句 112个
注释行占比 7.7%,偏低(建议10%-20%),代码可读性差
类和接口总数 7个
最复杂方法 Controller.determineDirection()
最大圈复杂度 29,较高(建议复杂度≤10)
最大块嵌套深度 6
平均块嵌套深度 2.44,嵌套层次适中
平均圈复杂度 2.55,整体可控

2.Controller.determineDirection()方法的复杂度详情

圈复杂度 语句数 最大嵌套深度 方法调用数 解释
29 40 6 30 该方法逻辑过于复杂,难以理解和维护

3.块深度分布

块深度 语句数
0-2 140
3-5 82
6+ 10

代码逻辑混乱,调试困难,需简化嵌套,拆分为小函数。

感悟

第二次作业老师给了类图,老老实实的按照老师的类图来敲代码,但是对于其中的一些方法比如GetQueueInstance()不知道用途是什么。
image
image
在完善的过程中也学会了去网上找前辈们写的博客,看了其中的一篇(),写的很好啊,但是对其思路的感悟并不深,他总结了八种情况,并且每一种都有四种小情况!!!
https://www.cnblogs.com/Unjx/p/18824685#单部电梯调度程序

  1. 虽然在写代码初期并没有使用代码,但是在我浅浅的领悟下,依然没有通过测试点。和同学讨论无果后,继续寻求AI,中间一度换了好几个AI,但改着改着就把我的DetermineDirection()、getNextFloor()和removeQequest()的实现逻辑给改了,尤其是DetermineDirection()、getNextFloor(),一直说把他改成了路径优化过后的版本巴拉巴拉……慎用AI!!!
  2. 还有就是运行超时,说实话运行超时一直不知道怎么改……
    一些测试案例:

重复请求过滤测试
1 10
<3><3><3>
<5,UP><5,UP>
<7>
end


包括看到的大佬的测试案例
输入
1
20
<5>
3,UP>
<7>
<5,UP>
<2>
<6,DOWN>
<16,DOWN>
<4,UP>
<14,UP>
<9>
<3>
<2,UP>
3,DOWN>
end
输出
Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Open Door # Floor 3
Close Door
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Open Door # Floor 5
Close Door
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Open Door # Floor 7
Close Door
Current Floor: 6 Direction: DOWN
Open Door # Floor 6
Close Door
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Current Floor: 3 Direction: DOWN
Current Floor: 2 Direction: DOWN
Open Door # Floor 2
Close Door
Current Floor: 3 Direction: UP
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Current Floor: 8 Direction: UP
Current Floor: 9 Direction: UP
Open Door # Floor 9
Close Door
Current Floor: 8 Direction: DOWN
Current Floor: 7 Direction: DOWN
Current Floor: 6 Direction: DOWN
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Current Floor: 3 Direction: DOWN
Open Door # Floor 3
Close Door
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Current Floor: 8 Direction: UP
Current Floor: 9 Direction: UP
Current Floor: 10 Direction: UP
Current Floor: 11 Direction: UP
Current Floor: 12 Direction: UP
Current Floor: 13 Direction: UP
Current Floor: 14 Direction: UP
Current Floor: 15 Direction: UP
Current Floor: 16 Direction: UP
Open Door # Floor 16
Close Door
Current Floor: 15 Direction: DOWN
Current Floor: 14 Direction: DOWN
Current Floor: 13 Direction: DOWN
Current Floor: 12 Direction: DOWN
Current Floor: 11 Direction: DOWN
Current Floor: 10 Direction: DOWN
Current Floor: 9 Direction: DOWN
Current Floor: 8 Direction: DOWN
Current Floor: 7 Direction: DOWN
Current Floor: 6 Direction: DOWN
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Open Door # Floor 4
Close Door
Current Floor: 5 Direction: UP
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Current Floor: 8 Direction: UP
Current Floor: 9 Direction: UP
Current Floor: 10 Direction: UP
Current Floor: 11 Direction: UP
Current Floor: 12 Direction: UP
Current Floor: 13 Direction: UP
Current Floor: 14 Direction: UP
Open Door # Floor 14
Close Door
Current Floor: 13 Direction: DOWN
Current Floor: 12 Direction: DOWN
Current Floor: 11 Direction: DOWN
Current Floor: 10 Direction: DOWN
Current Floor: 9 Direction: DOWN
Current Floor: 8 Direction: DOWN
Current Floor: 7 Direction: DOWN
Current Floor: 6 Direction: DOWN
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Current Floor: 3 Direction: DOWN
Current Floor: 2 Direction: DOWN
Open Door # Floor 2
Close Door
Current Floor: 3 Direction: UP
Open Door # Floor 3
Close DoorClose Door

第三次电梯调度作业

第二次迭代
对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),取消乘客请求类,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客类、队列类以及控制类,具体设计可参考如下类图。
image
电梯运行规则与前阶段相同,但有如下变动情况:

  • 乘客请求输入变动情况:外部请求由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层>
  • 对于外部请求,当电梯处理该请求之后(该请求出队),要将<请求源楼层,请求目的楼层>中的请求目的楼层加入到请求内部队列(加到队尾)

代码质量分析报告

image
image
image

1.项目总体指标

参数 解释
分支语句 (if/switch/循环) 占比20.5%
方法调用语句 104个
注释行占比 4.7%,偏低(建议10%-20%)
类和接口总数 7个
最复杂方法 Controller.determineDirection()
最大圈复杂度 22,较高(建议复杂度≤10)
最大块嵌套深度 5
平均块嵌套深度 1.93
平均圈复杂度 2.21

2.Controller.determineDirection()方法的复杂度详情

圈复杂度 语句数 最大嵌套深度 方法调用数 解释
22 41 4 39 圈复杂度越高越难维护

3.块深度分布

块深度 语句数
0-2 167
3-5 53
6+ 0

表示大部分代码(约76%)嵌套不深(0-2层),但仍有53句在3-5层嵌套,可读性和维护性较差

4.总结

  1. Controller.determineDirection()方法过于复杂,建议拆分成多个小方法。
  2. 注释严重不足,建议补充关键算法和复杂逻辑的注释(好吧确实也不太爱写注释OvO)。
  3. 部分方法嵌套过深,最大嵌套深度为5,建议通过提取方法或简化条件逻辑来降低嵌套。
  4. 整体复杂度可控,平均复杂度2.21和平均嵌套深度1.93还算复杂。

感悟

本次题目主要改进为新增Passenger类,将外部请求<楼层数,方向>改为<源楼层,目的楼层>,并且执行完外部请求后将其目的楼层加入内部请求队列队尾。
有了前两次失败的经验之后,本次稍微顺利一点,而且测试点也更多,但很可惜的是依旧不能通过所有测试点……感觉自己陷入了一个错误的循环里出不来。
image
image

  1. 花在这一次大作业上的时间其实很少,因为前面两次都失败,类在一次次迭代,我相信难度也是在增加的,一开始就有恐惧心理在。导致在临近截止时间的最后一个晚上才开始写,然后在离截止时间还有五分钟的时候通过了三个测试点!!!
  2. 我觉得本次大作业对我最大的收获就是学会了如何使用IDEA调试功能,打断点调试太方便了,可以很好的知道请求响应的过程,可惜醒悟的太晚了O.O。

三、总结

  1. 还是不能太轻易放弃,虽然第三次通过3/4的测试点,可能是因为老师给的测试点更多了还是侥幸过了那么几个,但是最终还是有成果的。
  2. 下次再做大作业还是得多和同学们讨论,这三次下来有点陷入思维局限了,看问题的角度太少,分析问题太浅薄,最终呈现就不太好……
  3. 通过这三次的大作业,从小题开始可以很好的解决问题到三次电梯调度以及迭代基本失败,也算是学习到了很多,比如通过正则表达式的捕获分组来判断输入的是内部请求还是外部请求;比如单一职责原则,将某些相关的功能封装成一个类,通过类与类的关系来实现最终的功能;比如打断点调试代码……这都是以前写代码没有注意或者不熟练使用的!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/970473.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Postman关于AES的加解密

Postman 绝对是软件测试工程师做接口联调、测试的必备工具。虽然实际工作中,团队可能会用到 JMeter、Apifox、Apipost、Burp Suite 等不同工具,但 Postman 凭借通用性强的优势,成为连接开发、测试、CTC(持续测试 /…

汉诺塔问题详解

《具体数学》第一章习题 12 bonus: 有柱子 A,B,C, 有 \(m_i\) 个半径为 \(i\) 的碟子,规定时刻大碟子不能在小的碟子上方,初始碟子都在柱 A,每次操作将一个柱子最上面碟子挪到另一个柱子最上面,末态柱子按原顺序(…

发布与订阅者模式-复盘

背景传统点对点调用让服务之间像蜘蛛网一样缠绕:一次改动,全网抖动。 发布-订阅(Pub/Sub)通过Broker把“谁发”与“谁收”彻底解耦,将调用关系转化为“主题-订阅”声明式关系,成为现代微服务、实时推送、事件驱动…

20232307 2025-2026-1 《网络与系统攻防技术》实验七实验报告

20232307 2025-2026-1 《网络与系统攻防技术》实验七实验报告 1.实验内容及要求 本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法。具体实践有 (1)简单应用SET工具建立冒名网站 (2)e…

《R语言医学数据分析实战》学习记录--第一章 R语言介绍

第一章 R语言介绍 内容记录 R和python很类似,可以通过对比python与R的区别进行学习,尤其对R中独有或有区别的部分,做特殊记录和学习。 有几个功能为R中特别处理:工作目录管理:通过getwd()获得当前工作目录,通过s…

251119明天就要去适应比赛场地了

我们学习室真绝了,上午没人来,晚上九点之后就关门了。 当然了,我九点之后又去了 读英文的东西真痛苦,啥时候才能无痛直接阅读啊啊啊啊。还是要加油吧, 今晚去随便打了打,保持一下手感,有的老大叔真不讲究,一来…

【数据结构】哈希表的理论与实现 - 教程

【数据结构】哈希表的理论与实现 - 教程2025-11-19 23:11 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block …

在阿里云上部署Redis

首先确定一个下载目录:cd /user #进入usr文件夹 mkdir redis #创建redis文件包下载redis安装包:wget http://download.redis.io.release.redis-6.0.1.tar.gz #获取redis安装包解压安装包tar -xzvf redis-6.0.1.tar.gz …

pip安装第三方包

https://pypi.tuna.tsinghua.edu.cn/simple

李克特量表(Likert scale)

李克特量表(Likert scale)是社会科学和市场研究中最常用的一种量表形式,用于衡量态度、意见或感知等心理变量。 核心特点对称与平衡: 量表通常是对称且平衡的,即积极和消极的选项数量相等,中间有一个中性点。 等…

java---maven

java及maven: 前提是已经安装了java:下载maven:https://maven.apache.org/然后下载:https://maven.apache.org/download.cgi找到下载:下载安装,然后放到一个没有中文路径的文件夹里面,然后配置环境变量: 搜索【…

新来的外包,在大群分享了它的限流算法的实现

1. 令牌桶按用户维度限流 前文golang/x/time/rate演示了基于整体请求速率的令牌桶限流; 那基于用户id、ip、apikey请求速率的限流(更贴近生产的需求), 阁下又该如何应对? 那这个问题就从全局速率变成了按照用户维度…

用 Rust 与 Tesseract 进行英文数字验证码识别

Rust 是一门注重性能与安全的系统编程语言,越来越多用于图像处理和自动化领域。本文将介绍如何使用 Rust 调用 Tesseract 引擎,实现简单的英文数字验证码识别。 更多内容访问ttocr.com或联系1436423940 一、开发准备…

详细介绍:开源AI大模型、AI智能名片与S2B2C商城系统:个体IP打造与价值赋能的新范式

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

ThreadLocal 源码解析

TreadLocal ThreadLocal解决的是线程内部变量的问题,并不是为了解决并发与共享变量的问题。 堆中有两个引用指向ThreadLocal,一个是ThreadLocal本身(强引用),一个ThreadLocalMap中Entry的key(弱引用)。 ThreadL…

黑马程序员SpringCloud微服务开发与实战- Docker项目部署-03

黑马程序员SpringCloud微服务开发与实战- Docker项目部署-03Posted on 2025-11-19 22:59 心默默言 阅读(0) 评论(0) 收藏 举报1

C# 和 Tesseract 实现英文数字验证码识别

验证码识别是一项常见的图像处理任务,尤其在自动化测试和数据采集场景中非常实用。本文将介绍如何在 C# 环境下,结合 Tesseract OCR 完成英文数字验证码的自动识别。 一、开发环境准备安装 Visual Studio 更多内容访…

linux ftp自动

您提到的“Linux FTP自动”可能有多种含义,以下是几种常见情况的解释和对应的Linux命令或脚本示例:1. 自动 FTP 上传文件(使用 ftp 命令) 如果您想在 Linux 系统中自动上传文件到 FTP 服务器,可以使用 ftp 命令结…