[新人娱乐向]电梯模拟器
学习 python 后一直没有什么想要写的东西, 工作上开发使用的是 php 语言, 一时间也改变不了.然后在某个网站(网址忘记了)看到了一个 web 版的电梯模拟器, 玩了半天, 他的电梯运行逻辑各种情况下都有问题, 这就萌生了我自己写一个 python 版的想法.
当时不会 GUI, 只能把展示内容写在文件里, 这样, 我打开展示文件(只读), 然后执行程序, 文件中的内容会一秒刷新一次 (偷懒版动画, 哈哈)
现在学了 GUI, 发呆发了大半天也没写出来, 就先放弃了
先展示一下效果:
图中红色的是 vscode 的一个插件, 检测无效空格的. 名字叫 `Trailing Spaces`
#### 项目地址 (https://github.com/anyuhanfei/Elevator_simulation)
用 vscode 打开展示文件, 然后不要进行任何操作, 否则 vscode 会获取写权限, 这样程序就没办法更新文件了.
#### 还有什么好玩的能写出来的吗?
接下来是代码, 大概思路就是, 把大楼, 电梯, 乘客分别封装成类, 包含属性和所有可能的动作. 执行文件中循环执行电梯运行逻辑, 并且电梯运行一次, 展示文件更新一次.
### 大楼
```
class mansion():
maximum_layer = None# 最高层数
minimum_layer = 1# 最低层数
data = {}# 每层电梯情况
def __init__(self, maximum_layer, minimum_layer=None):
self.maximum_layer = maximum_layer
self.minimum_layer = minimum_layer if minimum_layer is not None else self.minimum_layer
self._init_data()
def _init_data(self):
'''初始化电梯具体数据'''
for i in range(self.minimum_layer, self.maximum_layer + 1):
if i != 0:
self.data.update({'%s' % (i): {'up': False, 'down': False}})
def add_task(self, layer, orientation):
'''乘客按电梯
将指定楼层的上状态或下状态设置开
'''
if orientation == 'up' or orientation == 'down':
self.data = True
return True
else:
return False
def over_task(self, layer, orientation):
'''接到乘客
将指定楼层的上状态或下状态设置关
'''
if orientation == 'up' or orientation == 'down':
self.data = False
return True
else:
return False
```
### 电梯
```
class elevator():
maximum_load = 460# kg最大载重
current_layer = 1# 当前所在层数,初始化为1(电梯无0层)
passenger_number = 0# 乘客数量,初始化为0
passenger_total_weight = 0# 乘客总重量,初始化为0
move_task = {'up': set(), 'down': set()}# 移动任务,乘客需要到达的层数
move_orientation = 'up'# 移动方向
def __init__(self, maximum_load=None):
self.maximum_load = self.maximum_load if maximum_load is None else maximum_load
def check_mansion_data(self, mansion_obj):
'''检测大楼状态
若有新增的移动任务,则添加
'''
for key, value in mansion_obj.data.items():
if value['up'] is True:
self.move_task['up'].add(int(key))
if value['down'] is True:
self.move_task['down'].add(int(key))
def move_self(self, minimum_layer, maximum_layer):
'''移动自己
每一时间单位执行一次,移动一层
'''
if self.update_orientation() is False:
return
# 到达顶层没有停留,改变方向后向下了一格(找不到bug,无奈之举)
if maximum_layer == self.current_layer and self.move_orientation == 'up':
return
if minimum_layer == self.current_layer and self.move_orientation == 'down':
return
self.current_layer = self.current_layer + 1 if self.move_orientation == 'up' else self.current_layer - 1
if self.current_layer == 0:
self.current_layer = self.current_layer + 1 if self.move_orientation == 'up' else self.current_layer - 1
def add_move_task(self, passenger_obj):
'''乘客进入电梯完成后,添加移动任务'''
self.move_task.add(passenger_obj.want_layer)
def check_overload(self, passenger_obj):
'''超载检测'''
if self.passenger_total_weight + passenger_obj.weight > self.maximum_load:
return False
else:
self.passenger_number += 1
self.passenger_total_weight += passenger_obj.weight
return True
def check_open_door(self, minimum_layer, maximum_layer):
'''检测是否开门(即停止)'''
try:
self.move_task.remove(self.current_layer)
# self.update_orientation()
return True
except BaseException:
# 不应该开门
return False
def remove_passenger(self, passenger_obj):
'''乘客到达'''
self.passenger_number -= 1
self.passenger_total_weight -= passenger_obj.weight
def update_orientation(self):
'''更新方向'''
temp = False
if self.move_orientation == 'up':# 检测向上任务中有没有大于我所在层数的
for i in (self.move_task['down'] | self.move_task['up']):
if int(i) > self.current_layer:
temp = True
break
elif self.move_orientation == 'down':# 检测向下任务中有没有小于我所在层数的
for i in (self.move_task['down'] | self.move_task['up']):
if int(i) < self.current_layer:
temp = True
break
if temp is False:
self.move_orientation = 'down' if self.move_orientation == 'up' else 'up'
return temp
```
### 乘客
```
import random
class passenger():
weight = None# 体重,40~100之间
current_layer = None# 当前所在层数
want_layer = None# 想要到达层数
orientation = None# 方向
status = False# 当前乘坐状态,False为等待中,True为乘坐中
def __init__(self, max_layer, min_layer, weight=None, current_layer=None, want_layer=None):
self.weight = self._random_weight() if weight is None else weight
self.current_layer = self._random_current_layer(min_layer, max_layer) if current_layer is None else current_layer
self.want_layer = self._random_want_layer(min_layer, max_layer) if want_layer is None else want_layer
self.orientation = 'up' if self.current_layer < self.want_layer else 'down'
def start_task(self):
'''开始任务
在大楼上按电梯按钮,这里只需要返回大楼对象要操作的楼层和上下方向即可
'''
return self.current_layer, 'up' if self.current_layer < self.want_layer else 'down'
def in_elevator(self):
'''进入电梯'''
self.status = True
def elevator_overload(self):
'''电梯超载
重新开始任务
'''
self.status = False
return self.start_task()
def whether_to_over(self, elevator_obj):
'''是否达到目的层数'''
if elevator_obj.current_layer == self.want_layer:
return True
else:
return False
def _random_weight(self):
'''随机生成体重
40~50公斤几率:20%
50~60公斤几率:35%
60~70公斤几率:30%
70~80公斤几率:10%
80~100公斤几率:5%
'''
weight_level =
weight_level_random =
random.shuffle(weight_level_random)
return random.randint(weight_level], weight_level + 1])
def _random_current_layer(self, min_layer, max_layer):
'''随机生成所在楼层
1楼及其下楼层居多
'''
for i in range(min_layer, max_layer + 1):
if i == 0:
continue
if i <= 1:
if random.randint(0, 1) == 1:
return i
return random.randint(2, max_layer)
def _random_want_layer(self, min_layer, max_layer):
'''随机生成要去楼层(不与所在楼层相同)
根据所在楼层随机要求楼层,
1层和负层:若有负层,高层居多,负层少
高层:1层和负层居多,其他层少
'''
want_layer = 0
if self.current_layer <= 1:
want_layer = random.randint(min_layer, max_layer)
else:
if random.randint(0, 1) == 1:
want_layer = random.randint(2, max_layer)
else:
want_layer = random.randint(min_layer, 1)
if want_layer == 0 or want_layer == self.current_layer:
want_layer = self._random_want_layer(min_layer, max_layer)
return want_layer
```
### 参数
```
'''运行方式'''
RUN_MODE = 'auto'# manual or auto
'''运行间隔时间(自动模式生效)'''
UNIT_TIME = 2
'''楼层'''
MAXIMUM_LAYER = 7
MINIMUM_LAYER = 1
'''乘客生成概率'''
PGP = 2# 最低为1,数值越大,概率越低
'''电梯最大载重'''
MAXIMUM_LOAD = 200# None为默认载重
```
### 执行文件
```
import time
import random
import __init__
from element import mansion
from element import elevator
from element import passenger
# 大楼初始化
mansion_obj = mansion.mansion(__init__.MAXIMUM_LAYER, __init__.MINIMUM_LAYER)
# 电梯初始化
elevator_obj = elevator.elevator(__init__.MAXIMUM_LOAD)
# 乘客初始化
passenger_objs = dict()
# 开始运营
while(True):
if __init__.RUN_MODE == 'manual':
if input('请输入下一步指令:(N结束)') == 'N':
break
else:
time.sleep(__init__.UNIT_TIME)
elevator_obj.move_self(__init__.MINIMUM_LAYER, __init__.MAXIMUM_LAYER)
# 随机生成乘客
if random.randint(1, __init__.PGP) == 1:
passenger_obj = passenger.passenger(__init__.MAXIMUM_LAYER, __init__.MINIMUM_LAYER)
passenger_objs.update({str(time.time()): passenger_obj})
# 按按钮
layer, orientation = passenger_obj.start_task()
mansion_obj.add_task(layer, orientation)
# 电梯检索
elevator_obj.check_mansion_data(mansion_obj)
# 电梯移动,检测开门
pop_passenger_keys = []
if elevator_obj.check_open_door(__init__.MINIMUM_LAYER, __init__.MAXIMUM_LAYER) is True:
for key, i in passenger_objs.items():
if i.status is False:# 未上电梯
if i.current_layer == elevator_obj.current_layer:# 电梯到达当前所在楼层
if i.orientation == elevator_obj.move_orientation:# 方向相同
i.in_elevator()# 乘客上电梯
if elevator_obj.check_overload(i) is True:# 超载检测
elevator_obj.add_move_task(i)# 添加移动任务
mansion_obj.over_task(i.current_layer, i.orientation)# 大楼电梯按钮关闭
else:
layer, orientation = i.elevator_overload()# 超载,重新按电梯
mansion_obj.add_task(layer, orientation)
else:# 已上电梯
if i.whether_to_over(elevator_obj) is True:# 到达目的地
# 乘客下电梯
elevator_obj.remove_passenger(i)
pop_passenger_keys.append(key)
for key in pop_passenger_keys:
passenger_objs.pop(key)
elevator_obj.check_mansion_data(mansion_obj)# 电梯检索
# 动态打印
file_content = ''
for i in range(__init__.MAXIMUM_LAYER, __init__.MINIMUM_LAYER - 1, -1):
if i == 0:
continue
if i == elevator_obj.current_layer:
file_content += ' 电梯 '
else:
file_content += ' '
file_content += '%s' % (i)
file_content += '%s' % (' ↓ ' if mansion_obj.data['down'] is True else ' ')
file_content += '%s' % (' ↑ ' if mansion_obj.data['up'] is True else ' ')
file_content += ' '
for key, value in passenger_objs.items():
if value.status is False and value.current_layer == i:
file_content += ' 人(%s) ' % (value.want_layer)
file_content += '\n'
# 电梯参数
file_content += '\n'
file_content += '电梯任务: %s\n电梯方向:%s\n' % (elevator_obj.move_task, elevator_obj.move_orientation)
file_content += '所在层:%s\n当前载重:%s\n' % (elevator_obj.current_layer, elevator_obj.passenger_total_weight)
file_content += '电梯乘客: '
for key, value in passenger_objs.items():
if value.status is True:
file_content += ' 人(%s) ' % (value.want_layer)
file_content += '\n'
# 乘客参数
file_content += '\n所有乘客:\n'
for key, value in passenger_objs.items():
file_content += '所在层:%s达到层:%s方向:%s' % (value.current_layer, value.want_layer, value.orientation)
file_content += '乘坐状态:%s体重:%s\n' % (value.status, value.weight)
# 保存到文件
with open('show.log', 'w+', encoding="utf-8") as f:
f.write(file_content)
``` 不错,学习了 赞一个,想学python,但是0基础不知道咋个开始 挺不错的,对学习理解很有帮助。 sludger 发表于 2020-10-20 11:06
赞一个,想学python,但是0基础不知道咋个开始
我是看***的 7月7大佬的python基础视频入的门, 你可以找找, 网络上有资源免费下载的, 吾爱应该就有 https://coding.imooc.com/class/chapter/136.html#Anchor 感谢分享,正好学习~~~~~~~~· 感觉很有趣的样子,楼主辛苦啦:lol
页:
[1]