吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3130|回复: 6
收起左侧

[Python 原创] [新人娱乐向]电梯模拟器

[复制链接]
暗语寒飞 发表于 2020-10-20 10:38

学习 python 后一直没有什么想要写的东西, 工作上开发使用的是 php 语言, 一时间也改变不了.

然后在某个网站(网址忘记了)看到了一个 web 版的电梯模拟器, 玩了半天, 他的电梯运行逻辑各种情况下都有问题, 这就萌生了我自己写一个 python 版的想法.

当时不会 GUI, 只能把展示内容写在文件里, 这样, 我打开展示文件(只读), 然后执行程序, 文件中的内容会一秒刷新一次 (偷懒版动画, 哈哈)

现在学了 GUI, 发呆发了大半天也没写出来, 就先放弃了

先展示一下效果:

image3.gif

图中红色的是 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[str(layer)][orientation] = True
            return True
        else:
            return False

    def over_task(self, layer, orientation):
        '''接到乘客
        将指定楼层的上状态或下状态设置关
        '''
        if orientation == 'up' or orientation == 'down':
            self.data[str(layer)][orientation] = 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[passenger_obj.orientation].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[self.move_orientation].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 = [0, 40, 50, 60, 70, 80, 100]
        weight_level_random = [1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 5]
        random.shuffle(weight_level_random)
        return random.randint(weight_level[weight_level_random[0]], weight_level[weight_level_random[0] + 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[str(i)]['down'] is True else '   ')
        file_content += '%s' % (' ↑ ' if mansion_obj.data[str(i)]['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)

免费评分

参与人数 3吾爱币 +14 热心值 +3 收起 理由
alexskyboy + 3 + 1 热心回复!
笙若 + 1 + 1 谢谢@Thanks!
苏紫方璇 + 10 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

sunbester 发表于 2020-10-20 10:42
不错,学习了
sludger 发表于 2020-10-20 11:06
lucifer52 发表于 2020-10-20 20:45
 楼主| 暗语寒飞 发表于 2020-10-21 10:55
sludger 发表于 2020-10-20 11:06
赞一个,想学python,但是0基础不知道咋个开始

我是看***的 7月7大佬的python基础视频入的门, 你可以找找, 网络上有资源免费下载的, 吾爱应该就有   https://coding.imooc.com/class/chapter/136.html#Anchor
alexskyboy 发表于 2020-10-22 14:12
感谢分享,正好学习~~~~~~~~·
骑士计划 发表于 2020-10-25 17:52
感觉很有趣的样子,楼主辛苦啦
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 23:41

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表