昨天在网上看到有朋友问如何解决电梯问题,感觉比较有意思,便动手做了一下,有什么不合理的地方还望各位及时指出。
主要思路是:
1.创建对象:Lift(电梯)、Person(乘客)、Floor(楼层)以及RandomNum(产生随机数)。
2.主要介绍Lift类中的start()方法(即电梯运行):其中包含了
randomFloors();// 随机初始化等电梯的人
next(FLOOR_CURRENT);// 爬楼,包括上楼或下楼
printNextStat();// 爬楼状态打印
popSomePerson();// 出电梯
putSomePerson();// 上电梯
printLiftContent();// 打印电梯状态
3.其中的next()爬楼方法是重点:
next()方法把上楼和下楼分成两个方法,两个方法类似,现以上楼的liftUp方法为例说明其流程的伪代码:
上楼(当前楼层号){
if (电梯前一动作为上楼时) {
if (现在已到最高层) { //则开始下行
return 下楼(最高层);
} else {// 未到最高层
if(电梯内有到更高层的){
取出
}
if(等待上行楼层有到更高层的,且等待楼层也比当前楼层高){
取出
}
if (上楼方向没有用户) {
return 下楼(最高层);
}
return 取出的层;
}
} else {// 电梯前一动作为下楼时。
if (到最底层) {//则开始上行
return 上楼(最底层);
}
if (等待下楼的层没有比当前更低的楼层) {
return 上楼(当前层);
}
if (电梯内没有比当前更低的楼层) {
return 上楼(当前层);
} else {
return 下楼(当前层);
}
}
}
以下是相关的源代码,仅供参考。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/**
* 电梯问题
*
* @version 1.0
* @author 点子二木
* @date 2008-12-8
* @right Copyright (C), 点子二木
*/
public class Lift {
static final int INT_FLOOR_HIGHEST = 20;// 最高层
static final int INT_FLOOR_LOWEST = 1;// 最低层
static final int INT_PERSON_WAIT_MAX = 2;// 等电梯的人的最大值
static final int LIST_CAPABILITY_SIZE_MAX = 1000;// 电梯最大负重
static int LIST_CAPABILITY_CURRENT;// 当前电梯的已用大小总和
private static final int INT_RANDOM_FLOOR_COUNT = 2;// 随机的楼层数
private static int FLOOR_CURRENT = 1;// 电梯当前所在层
private static final int INT_STOP_MAX = 5;// 电梯可停的次数最大值
private static int INT_STOP_NUM = 0;// 电梯已停的次数
private static boolean BLN_liftDirection;// 电梯运行的方向,false-向上,true-向下
private static boolean BLN_OPEN;// 本层仍有乘客上下车,false-没有;true-有
private static ArrayList<Person> liftPersonList = new ArrayList<Person>();// 梯中人列表
private static ArrayList<Person> waitPersonList = new ArrayList<Person>();// 等待人列表
public static void main(String[] args) {
initLift();
start();
}
/**
* 初始化电梯
*/
private static void initLift() {
randomFloors();// 随机几层
printLiftContent();// 打印电梯状态
}
/**
* 电梯启动,到下一停,并上下人
*/
private static void start() {
while (true) {
System.out.println("电梯停靠第" + (Lift.INT_STOP_NUM + 1) + "次");
if (liftPersonList.isEmpty() && waitPersonList.isEmpty()) {
randomFloors();// 随机几层
}
next(FLOOR_CURRENT);// 爬楼,包括上楼或下楼
printNextStat();// 爬楼状态打印
popSomePerson();// 出电梯
putSomePerson();// 上电梯
printLiftContent();// 打印电梯状态
}
}
/**
* 随机几层
*/
@SuppressWarnings( { "static-access", "unchecked" })
private static void randomFloors() {
waitPersonList.clear();
for (int index = 0; index < INT_RANDOM_FLOOR_COUNT; index++) {
Floor floor = new Floor();
ArrayList<Person> tempList = floor.waitPersonListOfFloor;
for (Person per : tempList) {
waitPersonList.add(per);
}
}
// / 固定数据测试 start///
// for (int num = 0; num < 2; num++) {
// Person per = new Person(55 + num, 1, 16 + num);
// per.setFrom(16);
// waitPersonList.add(per);
// }
// ArrayList<Person> tempList = (ArrayList<Person>)
// waitPersonList.clone();
// for (Person per : tempList) {
// waitPersonList.add(per);
// }
// / 固定数据测试 end///
sortWaitPersonList();
}
/**
* 遍历打印电梯内列表
*/
private static void printLiftContent() {
sortWaitPersonList();
sortLiftPersonList();
System.out.println("=========当前楼层:" + FLOOR_CURRENT + "=========");
for (int num = 0; num < liftPersonList.size(); num++) {
System.out.println("人物" + (num + 1) + "重量:"
+ liftPersonList.get(num).getAnWeight() + "kg。要去楼层:"
+ liftPersonList.get(num).getTo());
}
System.out.println("当前总重量:" + LIST_CAPABILITY_CURRENT + "kg,最大总重量:"
+ LIST_CAPABILITY_SIZE_MAX + "kg");
System.out.println("=========");
for (int num = 0; num < waitPersonList.size(); num++) {
System.out.println("随机人物" + (num + 1) + "重量:"
+ waitPersonList.get(num).getAnWeight() + "kg。上客楼层:"
+ waitPersonList.get(num).getFrom() + "。要去楼层:"
+ waitPersonList.get(num).getTo());
}
}
/**
* 电梯爬楼到下次停车(*****此方法是关键*****)
*
* @param current
* @return 下次停车的楼层
*/
private static int next(int current) {
int floorNO = 0;
if (!BLN_liftDirection) {
floorNO = liftUp(current);
} else {
floorNO = liftDown(current);
}
if (floorNO < INT_FLOOR_LOWEST) {
System.out.println("@@@@@@@@@@@@@@@@@@@@暂无乘客,电梯停止@@@@@@@@@@"
+ "目前停在" + FLOOR_CURRENT + "层@@@@@@@@@@@@@@@@@@@@");
System.exit(0);
}
if (floorNO == FLOOR_CURRENT) {
System.out.println("&&&&&&&&&&开门!!本层仍有乘客上下车!" + "&&&&&&&&&&");
BLN_OPEN = true;
return FLOOR_CURRENT;
}
FLOOR_CURRENT = floorNO;
BLN_OPEN = false;
return FLOOR_CURRENT;
}
/**
* 电梯上楼
*
* @param current
* @return 上楼停车的楼层
*/
private static int liftUp(int current) {
if (liftPersonList.size() < 1 && waitPersonList.size() < 1) {
return INT_FLOOR_LOWEST - 1;
}
if (!BLN_liftDirection) {// 上楼方向
if (current == INT_FLOOR_HIGHEST) {// 已到顶
BLN_liftDirection = true;
return liftDown(current);
} else {// 未到顶
// 电梯内有到更高层的
int upMin = INT_FLOOR_HIGHEST + 1;// 上楼最小值
for (Person inner : liftPersonList) {// 梯中人取到达楼层
if (inner.getTo() < upMin && inner.getTo() >= current) {
upMin = inner.getTo();
}
}
// 等待上行楼层有到更高层的,且等待楼层也比当前楼层高
for (Person wait : waitPersonList) {// 等待人取等待楼层
if (wait.getFrom() >= current && wait.getFrom() < upMin
&& wait.getTo() > wait.getFrom()) {//
upMin = wait.getFrom();
}
}
if (upMin > INT_FLOOR_HIGHEST) {// 说明上楼方向没有用户
BLN_liftDirection = true;
return liftDown(INT_FLOOR_HIGHEST);
}
return upMin;
}
} else {// 下楼方向
// 到最低层则开始上行
if (INT_FLOOR_LOWEST == current) {
BLN_liftDirection = false;
return liftUp(current);
}
// 等待下行楼层没有比当前更低的楼层
int waitFrom = current;
for (Person wait : waitPersonList) {//
if (wait.getFrom() > wait.getTo() && wait.getFrom() < current) {
waitFrom = wait.getFrom();
}
}
if (waitFrom >= current) {// 说明没有更低的等待
BLN_liftDirection = false;
return liftUp(current);
}
// 电梯内没有比当前更低的楼层
int innerTo = current;
for (Person inner : liftPersonList) {//
if (inner.getTo() < current) {
innerTo = inner.getTo();
}
}
if (innerTo >= current) {// 说明没有更低的坐梯人
BLN_liftDirection = false;
return liftUp(current);
} else {
BLN_liftDirection = true;
return liftDown(current);
}
}
}
/**
* 电梯下楼
*
* @param current
* @return 下楼停车的楼层
*/
private static int liftDown(int current) {
if (liftPersonList.size() < 1 && waitPersonList.size() < 1) {
return INT_FLOOR_LOWEST - 1;
}
if (!BLN_liftDirection) {// 上楼方向
// 到最高层则开始下行
if (INT_FLOOR_HIGHEST == current) {
BLN_liftDirection = true;
return liftDown(current);
}
// 等待上行楼层没有比当前更高的楼层
int waitFrom = current;
for (Person wait : waitPersonList) {//
if (wait.getFrom() < wait.getTo() && wait.getFrom() > current) {
waitFrom = wait.getFrom();
}
}
if (waitFrom <= current) {// 说明没有更高的等待
BLN_liftDirection = true;
return liftDown(current);
}
// 电梯内没有比当前更高的楼层
int innerTo = current;
for (Person inner : liftPersonList) {//
if (inner.getTo() > current) {
innerTo = inner.getTo();
}
}
if (innerTo <= current) {// 说明没有更高的坐梯人
BLN_liftDirection = true;
return liftDown(current);
} else {
BLN_liftDirection = false;
return liftUp(current);
}
} else {// 下楼方向
if (current == INT_FLOOR_LOWEST) {// 已到底
BLN_liftDirection = false;
return liftUp(current);
} else {// 未到底
// 电梯内有到更低层的
int downMax = INT_FLOOR_LOWEST - 1;// 下楼最大的楼层号
for (Person inner : liftPersonList) {// 梯中人取到达楼层
if (inner.getTo() > downMax && inner.getTo() <= current) {
downMax = inner.getTo();
}
}
// 等待下行楼层有到更低层的,且等待楼层也比当前楼层低
for (Person wait : waitPersonList) {// 等待人取等待楼层
if (wait.getFrom() <= current && wait.getFrom() > downMax
&& wait.getTo() < wait.getFrom()) {//
downMax = wait.getFrom();
}
}
if (downMax < INT_FLOOR_LOWEST) {// 说明下楼方向没有用户
BLN_liftDirection = false;
return liftUp(INT_FLOOR_LOWEST);
}
return downMax;
}
}
}
/**
* 爬楼状态打印
*/
private static void printNextStat() {
if (BLN_OPEN) {// 重新开门不用打印
return;
}
Lift.INT_STOP_NUM++;// 停的次数加一
String direct = "";
if (!BLN_liftDirection) {
direct = "上升";
} else {
direct = "下降";
}
System.out.println(">>>>>" + direct + "中>>>>>>>>>>电梯即将到达("
+ FLOOR_CURRENT + ")层:>>>>>>>>>>>>>>>>>>>>");
if (INT_STOP_NUM >= INT_STOP_MAX) {// 不加可能进入死循环
System.exit(0);
}
}
/**
* 本层人上电梯
*
* @return true-上梯成功;false-上梯失败
*/
@SuppressWarnings("unchecked")
private static boolean putSomePerson() {
boolean result = false;
ArrayList<Person> waitclone = (ArrayList<Person>) waitPersonList
.clone();
for (Person per : waitclone) {
if (per.getFrom() == FLOOR_CURRENT) {
putOnePerson(per);
popWaitOnePersonOfThisFloor(per);
result = true;
}
}
return result;
}
/**
* 一个人上电梯
*
* @param person
* @return true-上梯成功;false-上梯失败
*/
private static boolean putOnePerson(Person person) {
boolean result = false;
LIST_CAPABILITY_CURRENT += person.getAnWeight();
if (LIST_CAPABILITY_CURRENT <= LIST_CAPABILITY_SIZE_MAX) {// 该人进入后依旧满足
liftPersonList.add(person);
result = true;
} else {
LIST_CAPABILITY_CURRENT -= person.getAnWeight();
}
return result;
}
/**
* 本层到站人出电梯
*
*/
@SuppressWarnings("unchecked")
private static boolean popSomePerson() {
boolean result = false;
ArrayList<Person> liftclone = (ArrayList<Person>) liftPersonList
.clone();
for (Person person : liftclone) {
if (FLOOR_CURRENT == person.getTo()) {// 如果到达楼层
LIST_CAPABILITY_CURRENT -= person.getAnWeight();
liftPersonList.remove(person);
result = true;
} else {
}
}
return result;
}
/**
* 到站,清除本层等待的一个人
*
* @param person
* @return true-成功删除;false-未删除
*/
private static boolean popWaitOnePersonOfThisFloor(Person person) {
boolean result = false;
if (FLOOR_CURRENT == person.getFrom()) {//
waitPersonList.remove(person);
result = true;
} else {
}
return result;
}
/**
* 电梯中的人排序
*/
@SuppressWarnings("unchecked")
private static void sortLiftPersonList() {
Collections.sort(liftPersonList, new Person());// 按到达层数排序
}
/**
* 等待的人排序
*/
@SuppressWarnings("unchecked")
private static void sortWaitPersonList() {
Collections.sort(waitPersonList, new Person());// 按到达层数排序
}
}
/**
* 乘梯人
*/
@SuppressWarnings("unchecked")
class Person implements Comparator {
private final int INT_WEIGHT_MAX = 200;// 一个人体重最大值
private int anWeight;// 一个人的体重
private int from;// 上梯楼层
private int to;// 下梯楼层
public int compare(Object o1, Object o2) {
Person per1 = (Person) o1;
Person per2 = (Person) o2;
return per1.to - per2.to;
}
Person() {
int wgh = RandomNum.randomInt(1, INT_WEIGHT_MAX);
int fromfloor;
int tofloor;
do {
tofloor = RandomNum.randomInt(Lift.INT_FLOOR_LOWEST,
Lift.INT_FLOOR_HIGHEST);
fromfloor = RandomNum.randomInt(Lift.INT_FLOOR_LOWEST,
Lift.INT_FLOOR_HIGHEST);
} while (tofloor == fromfloor);
anWeight = wgh;
from = fromfloor;
to = tofloor;
}
Person(int anWeight, int from, int to) {
this.anWeight = anWeight;// 一个人的体重
this.from = from;// 上梯楼层
this.to = to;// 下梯楼层
}
public void setTo(int to) {
if (to > Lift.INT_FLOOR_LOWEST && to <= Lift.INT_FLOOR_HIGHEST
&& to != this.from) {
this.to = to;
} else {
this.to = 1;
}
}
public void setFrom(int from) {
if (from > Lift.INT_FLOOR_LOWEST && from <= Lift.INT_FLOOR_HIGHEST
&& from != this.to) {
this.from = from;
} else {
this.from = 1;
}
}
public void setAnWeight(int anWeight) {
if ((anWeight + Lift.LIST_CAPABILITY_CURRENT) < Lift.LIST_CAPABILITY_SIZE_MAX) {
this.anWeight = anWeight;
} else {
this.anWeight = 0;
}
}
// ///=======getter=======//
public int getFrom() {
return from;
}
public int getTo() {
return to;
}
public int getAnWeight() {
return anWeight;
}
}
/**
* 楼层
*/
class Floor {
private int floorNO;// 楼层号
private int waitNum;// 等待的人数
boolean upFlag;// 是否有人上楼的按钮
boolean downFlag;// 是否有人下楼的按钮
ArrayList<Person> waitPersonListOfFloor = new ArrayList<Person>();// 本层等待人列表
Floor(int currentfloor) {
int waitNum = RandomNum.randomInt(1, Lift.INT_PERSON_WAIT_MAX);
this.floorNO = currentfloor;
this.waitNum = waitNum;
for (int num = 0; num < waitNum; num++) {
Person per = new Person();
per.setFrom(currentfloor);
waitPersonListOfFloor.add(per);
if (per.getTo() > floorNO) {
upFlag = true;
}
if (per.getTo() < floorNO) {
downFlag = true;
}
}
}
Floor() {
this.floorNO = RandomNum.randomInt(Lift.INT_FLOOR_LOWEST,
Lift.INT_FLOOR_HIGHEST);
this.waitNum = RandomNum.randomInt(1, Lift.INT_PERSON_WAIT_MAX);
for (int num = 0; num < waitNum; num++) {
Person per = new Person();
per.setFrom(floorNO);
waitPersonListOfFloor.add(per);
if (per.getTo() > floorNO) {
upFlag = true;
}
if (per.getTo() < floorNO) {
downFlag = true;
}
}
}
}
/**
* 产生随机数的方法 :Math.random()*(end-start+1)+start
*/
class RandomNum {
/**
* 产生int型随机数
*
* @param start起始范围
* @param end截止范围
* @return
*/
public static int randomInt(int start, int end) {
int result = (int) (Math.random() * (end - start + 1) + start);
return result;
}
/**
* 产生float型随机数
*
* @param start起始范围
* @param end截止范围
* @return
*/
public static float randomFloat(float start, float end) {
float result = (float) (Math.random() * (end - start + 1) + start);
return result;
}
}