电梯模拟系统是很多计算机专业的大学生必做的题目,整个系统有着复杂严谨的逻辑。而unity作为一个强大的游戏引擎,除了开发游戏外,也可以作为一个可视化软件,用来模拟电梯的运行再好不过。这篇博客就给大家介绍一个用unity可视化的电梯系统,下面先上效果图。
电梯当前运行状态为上升,黄色小人代表发出向上的请求,白色相反
控制台输出每一t的动作
我们先理顺电梯的运行逻辑。对于本系统而言,模拟时钟从0开始,时间单位为0.1秒。人和电梯的各种动作均要消耗一定的时间单位(简记为t),比如:有人进出时,电梯每隔40t测试一次,若无人进出,则关门;关门和开门各需要20t;每个人进出电梯均需要25t;电梯加速需要15t;上升时,每一层需要51t,减速需要14t;下降时,每一层需要61t,减速需要23t;如果电梯在某层静止时间超过300t,则驶回1层候命。
下面是基本要求:
1)就近原则:电梯的主要调度策略是首先响应沿当前行进方向上最近端的请求直到满足最远端请求。若该方向上无请求时,就改变移动方向;
2)在就近原则无法满足的情况下,首先满足更高层的请求;
3)电梯的最大承载人数为13人,电梯人数达到13人后,在有人出电梯之前,不接受进入电梯的请求;
4)乘客上下电梯时先出后进。进电梯时乘客是按发出乘坐请求的顺序依次进入,每次只能进入一人且每个人花费的时间都为25t;
5)电梯在关门期间(电梯离开之前)所在层提出请求的乘客同样允许进入。
数据结构:
先谈谈用到的数据结构,为存储电梯外的乘客和电梯内的乘客,考虑到链表的删除简洁并高效,本系统使用内外两个链表来进行存储。当系统随机增加乘客时,电梯外的链表在尾部增加一个结点。当有人进入电梯时,电梯外的链表删除该结点,电梯内链表在尾部新增一个结点。在多人进入电梯时,最早发出请求的人在链表的前方,先进行删除,再往后依次删除,采用了队列的逻辑。下面是用c#写的一个链表:
-
public class Node<T>//单链表结点类,采用泛型 { private T data; //数据域,当前结点的数据 private Node<T> next; //引用域,即下一结点 public Node(T item, Node<T> p) { data = item; next = p; } public Node(Node<T> p) { next = p; } public Node() { data = default(T); next = null; } public T Data; public Node<T> Next; } public class MyLinkList<T>//链表类,包含链表定义及基本操作方法 { public bool hasdelete = false; private Node<T> head; //单链表的头结点 //头结点属性 public Node<T> Head { get { return head; } set { head = value; } } //构造器 public MyLinkList() { head = null; } //求单链表的长度 public int Size() { Node<T> p = head; int len = 0; while (p != null) { ++len; p = p.Next; } return len; } //清空单链表 public void Clear() { head = null; } //判断单链表是否为空 public bool IsEmpty() { if (head == null) { return true; } else { return false; } } //在单链表的末尾添加新元素 public void Append(T item) { Node<T> q = new Node<T>(); Node<T> p = new Node<T>();//跟踪指针 // Debug.Log(2); if (head == null) { q.Data = item; q.Next = null; // Debug.Log(1); head = q; Debug.Log(head.Data); return; } p = head; while (p.Next != null) { p = p.Next; } q.Data = item; q.Next = null; p.Next = q; } //在单链表的第i个结点的位置前插入一个值为item的结点 public void Insert(T item, int i) { if (IsEmpty() || i < 0 || i > Size()) { Debug.Log("LinkList is empty or Position is error!"); return; } if (i == 0) { Node<T> q = new Node<T>(); q.Data = item; q.Next = head; head = q; return; } Node<T> p = head; Node<T> r = new Node<T>(); int j = 0; while (p.Next != null && j < i) { r = p; p = p.Next; ++j; } if (j == i) { Node<T> q = new Node<T>(); q.Data = item; q.Next = p; r.Next = q; } } //删除单链表的第i个结点 public T Delete(int i) { hasdelete = true; if (IsEmpty() || i < 0 || i > Size()) { Debug.Log("LinkList is empty or Position is error!"); return default(T); } Node<T> q = new Node<T>(); if (i == 0) { q = head; head = head.Next; hasdelete = true; return q.Data; } Node<T> p = head; int j = 0; while (p.Next != null && j < i) { ++j; q = p; p = p.Next; } if (j == i) { q.Next = p.Next; hasdelete = true; return p.Data; } else { Debug.Log("The " + i + "th node is not exist!"); return default(T); } } //获得单链表的第i个数据元素 public T GetData(int i) { if (IsEmpty() || i < 0) { Debug.Log("LinkList is empty or position is error! "); return default(T); } Node<T> p = new Node<T>(); p = head; int j = 0; while (p.Next != null && j < i) { ++j; p = p.Next; } if (j == i) { return p.Data; } else { Debug.Log("The" + i + "th node is not exist!"); return default(T); } } public void SetData(int pos, T per) {