电梯调度
现有一新建办公大厦,共有21层,共有四部电梯,所有电梯基本参数如下表所示:
电梯编号 | 可服务楼层 | 最大乘客数量 |
最大载重量 |
1 | 全部楼层 | 10 | 800 kg |
2 | 单层 | 10 | 800 kg |
3 | 双层 | 20 | 1600 kg |
4 | 全部楼层 | 20 | 2000 kg |
其使用规定如下:
1、楼层号为0~20,其中0号为地下一层;
2、有楼层限制的电梯不在响应楼层停靠,如单双层;
3、所有电梯采用统一按钮控制
请根据上述要求设计并实现一个电梯控制程序,如果有图形显示就更好了。
伙伴介绍与评价:
本次结对编程项目(电梯调度)我的伙伴是王敬一,这是他的博客链接http://www.cnblogs.com/m108280546/
经过两人的协商,最终决定分工为:我审查,他编程。以下为我们工作中的一些片段:
我的基础有些薄弱,这次的结对编程中,基本上是我的伙伴带着我做的,java语言之前没有接触过,因此在编程过程中其实是一直在学习的过程,所谓审查,其实并没有起到什么作用,因此,编程思路全部跟随我的伙伴来。我的编程伙伴工作态度很认真,有耐心,编程细致认真,代码易读明了。
需求分析与简单构思:
(据王敬一)
所谓电梯调度,我认为就是在有限的条件下,尽最大努力减少乘客的等待时间,同时让更多乘客能坐到电梯。不过如果细想的话,要考虑的事情还是非常的多的。
1.四部电梯,且这四部电梯的信息各不相同(载客数,载重能力)。更为特殊一点的是2、3号这种有楼层限制的电梯,提到楼层限制,我就想到了我们学校图书馆的电梯(1-6楼不停),应该还是单双层更难一些。这里初步构想用以编号不同(1-4)来区别这些信息,感觉这应该没什么争议。
2.调度问题:一共21层楼,0代表地下一层。首先,要考虑一下初始状态,没什么问题的话感觉要么是一开始4部电梯都停在最底层(即地下一层)要么是一开始都停在大堂(即1楼,毕竟1楼人经常是最多的)。后来我又结合这4部电梯的特殊性,想到一个最优的初始位置即:1号电梯最初停在1楼(最普通的电梯),2号电梯最初停在7楼(单层电梯),3号电梯最初停在14楼(双层电梯),4号电梯停在0楼(地下一楼,承载能力最强,适合运送货物,这里我猜大重量的货物应该在地下室。。。) 虽然我感觉这种安排1 、7、14、0的安排不仅发挥的各自电梯的优势而且能够保证一开始的调度时间最短。但是后来想想,现实中好像没有这么安排的。然后重要的便是电梯调度算法,关于在这个电梯调度算法,我想了很久,而且在变成过程中也不断在改变自己的想法,因为我觉得实在是在复杂了,有些问题更是完全矛盾的,难以取舍的。比如1号电梯在3楼处于空闲状态,2号电梯正载着人从底层向上最终要去7楼,当2号电梯刚到上升到3楼的时候,5楼有人按了↑的按钮。那么此时是让空闲的1号电梯去呢?还是顺路且刚好仅为单层停靠的2号电梯去呢?等等此种让人纠结的问题数不胜数。最后我在无限的纠结中只能放弃,或许真的是我想太多了。应该从简单些入手。设触发外部按键的楼层为请求楼层,触发内部楼层按键为目的楼层,电梯目前所处楼层为当前楼层。这里我觉得一个最基本的算法便是要让(请求楼层-当前楼层)最小的去响应外部按键,同样优先让(目的楼层-当前楼层)最小的去响应内部按键(不同的人有不同的目的楼层)。
3.界面问题:这个真的好难啊,我以前从来没做过任何界面,电梯是动的,如果用让图形“动起来”是最大的问题。最后我实在是不理解“所有电梯均采用统一按钮控制”这句话是什么意思,一个按钮怎么控制4个电梯的内部请求,21个楼层的外部请求。
实现过程:
一开始进行的还是比较顺利的,各种class先弄出来。但是后来解决不了的问题来了...下面附上一小段最初的失败作品的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
class
ElevatorInfo
{
int
Elevator_Num;
int
Elevator_Service;
int
Elevator_MaxPassenger;
int
Elevator_MaxWeight;
public
ElevatorInfo(
int
a,
int
b,
int
c,
int
d)
{
this
.Elevator_Num=a;
this
.Elevator_Service=b;
//可服务楼层:0代表全部,1代表单层,2代表双层。
this
.Elevator_MaxPassenger=c;
this
.Elevator_MaxWeight=d;
}
}
class
ElevatorStatus
{
int
Num;
int
CurrentPassengers;
int
CurrentWeight;
int
CurrentFloor;
int
Status;
//电梯运行状态:0代表停止,1代表向上,-1代表向下
int
Arrive;
//电梯是否到达目标楼层:1代表到达,0代表未到达
public
ElevatorStatus(
int
n)
{
switch
(n)
{
case
1
:
this
.CurrentFloor=
1
;
break
;
case
2
:
this
.CurrentFloor=
7
;
break
;
case
3
:
this
.CurrentFloor=
14
;
break
;
case
4
:
this
.CurrentFloor=
0
;
break
;
}
this
.Num=n;
this
.CurrentPassengers=
0
;
this
.CurrentWeight=
0
;
this
.Status=
0
;
this
.Arrive=
0
;
}
}
class
RequestInfo
{
int
RequestFloor;
int
UpOrDown;
int
Passengers;
int
Weight;
}
|
或许是由于我刚开始学Java,水平实在是太菜了,跟着http://www.cnblogs.com/vamei/archive/2013/03/31/2991531.html这个网站上的教程胡乱写,越写越像C语言,后来研究好久,不用多线程根本不能让4个电梯同时运作,然而我并不会,去网上百度一下,也没怎么弄明白,而且界面部分也不熟练。实在是写不出来,最终这个“初稿”也就加起来200行左右,没有什么明显Java的样子,只能实现控制台里的输入一些乘客、重量、外部请求楼层什么的然后输出一个调用的电梯信息。后来经过我坚持不懈的各种百度,查书。“借鉴”了各种电梯程序中多线程和界面的部分。经过两三天的增删改查终于算是完成了。但是问题还是很大的,多线程还是弄不明白,没有实现电梯单双层问题,电梯之间也没有乘客数量和载重能力的区分(这里我感觉可能需要每个线程都不一样,好麻烦,只好妥协了)不过我觉得已经无所谓了,这次项目真的让我学到很多。所以重点在总结里。
总结和体会:
一、Java的优点:
1、跨平台
2、开源框架丰富,开发周期短
3、易入门
二、之前没有接触java并且不接触java是因为在2015年是甲骨文公司宣布不再支援java网页外挂,并且谷歌也要在下一代Android上放弃使用java转而使用 OpenJDK,因此认为没有学习的必要,但是进过学习后发现java易于上手,学习门槛底,实在是适合我这种基础较差的同学。
三、然后以下是王敬一的总结,我实在是还没有那个水平:
1.Java十分明显的面向对象的特点。
2.程序稍微庞大一些后,其中需要需要定义的变量名很多,要仔细设计一下他们的名称,否则经常容易混淆。最好都翻译成英文。
3.在做界面时,各种常见的如Frame、Panel、Button、TextFiled等等。
4.创建一个新的窗口后,要记住加上setVisible(true)来让其显示。相反可用setVisible(false)让其隐藏。
5.setBounds与setLayout,前者既然定位又定义大小setBounds(int x,int y,int width,int height),后者定义布局方式,常用setLayout(null)和setLayout(new FlowLayout())
6.事件监听机制以及常见的鼠标事件、键盘事件。下面附上一段程序中的代码,其中包含了窗口框架,文本框,按钮,鼠标事件实现弹窗。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
class
PassengerAndWeightAction
implements
ActionListener
{
//输入人数和重量
private
JFrame f1;
private
JFrame f2;
private
TextField tf1;
private
TextField tf2;
private
TextField tf3;
private
Button but;
public
void
actionPerformed(ActionEvent e)
{
f1 =
new
JFrame(
"请输入乘客数和重量"
);
f2 =
new
JFrame(
"错误"
);
f1.setLayout(
new
FlowLayout());
f1.setBounds(
450
,
350
,
400
,
100
);
f1.setVisible(
true
);
f1.set
f2.setBounds(
450
,
350
,
260
,
70
);
tf1 =
new
TextField(
10
);
tf2 =
new
TextField(
10
);
tf3 =
new
TextField(
16
);
tf3.setText(
" 人数或重量超过限制,请返回重新输入!"
);
but =
new
Button(
"确认"
);
f1.add(but);
f1.add(tf1);
f1.add(tf2);
f2.add(tf3);
but.addMouseListener(
new
MouseAdapter() {
public
void
mouseClicked(MouseEvent e){
int
p = Integer.parseInt(tf1.getText());
int
w = Integer.parseInt(tf2.getText());
if
(p>
20
||w>
2000
)
{
f2.setVisible(
true
);
}
else
{
f1.dispose();
}
}
});
}
}
|
7.在elipse中记得运用Ctrl+Shift+O来一键import,如各种java.awt以及javax.swing
8.在一些鼠标与键盘事件中由于传递的参数为String类型,如果想想要获取文本框中的int类型信息,可采用Integer.parseInt(TextField.getText())语句,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
but.addMouseListener(
new
MouseAdapter() {
public
void
mouseClicked(MouseEvent e){
int
p = Integer.parseInt(tf1.getText());
int
w = Integer.parseInt(tf2.getText());
if
(p>
20
||w>
2000
)
{
f2.setVisible(
true
);
}
else
{
f1.dispose();
}
}
});
|
9.Java中封装和接口,public,private区别。 implements用法。
10. Java中的继承extends,以及接口的继承。虽然不支持多重继承,但可以用接口来实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
class
UpAction
implements
ActionListener
{
private
int
floor;
public
UpAction(
int
i)
{
floor = i;
}
public
void
actionPerformed(ActionEvent e)
{
bUp[floor].setForeground(Color.RED);
bUp[floor].setEnabled(
false
);
foundThread.addTask(floor,
true
);
}
}
class
DownAction
implements
ActionListener
{
private
int
floor;
public
DownAction(
int
i)
{
floor = i;
}
public
void
actionPerformed(ActionEvent e)
{
bDown[floor].setForeground(Color.RED);
bDown[floor].setEnabled(
false
);
foundThread.addTask(floor,
false
);
}
}
|
11.最常见的:构造器与方法重载、组合、类数据与类方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class
Elevator
extends
Thread
{
//电梯运行主类
private
int
id;
private
int
floor = FLOOR;
private
JPanel myPanel =
new
JPanel();
private
JButton displaystate =
new
JButton(
"-"
);
private
JButton[] buttons;
public
int
currentfloor =
0
;
public
int
currentstate = PAUSE;
private
JButton displayfloor =
new
JButton(
"0"
);
private
ArrayList destinations;
public
Elevator(
int
x)
public
void
addFloor(
int
i)
public
void
wantToFloor(
int
i) <br>
public
void
setState()
}
|
12.如果定义的变量名混淆了,需要更改,在eclipse中可以选中需要更改的变量名按Alt+Shift+R来更改程序中的所有的该变量名。
13.最常犯的错误便是中文输入法乱入问题,要留意 ;和 ; ()和 ()、“” 和 "" 等等符号。切记编程一定要细心。
本次结对编程收获颇丰,首先要感谢一下我的结对伙伴带着我编程学习,我觉得在整个过程中,我们的程序的一步一步的改善,直到最终成型,离不开彼此之间的交流讨论,同时也让双方都学到了很多新的知识。我们在本次结对编程项目中的合作十分愉快。虽然最后的成品没有完全实现所有要求,但是这次项目重要的是让一个初学Java的我巩固了很多基础知识的同时也学到了很多新的知识,相信这次项目对我的Java学习有着极大的帮助。更重要的是让我更进一步了解了结对编程,实实在在的体验了一次结对编程,学会了如何更好的与他人合作来完成一个项目。