猿人太一

导航

 

作业题目

题目要求及内容

本次作业要求两个人合作完成,驾驶员和导航员角色自定,鼓励大家在工作期间角色随时互换,这里会布置两个题目,请各组成员根据自己的爱好任选一题。

题目1:

我们在刚开始上课的时候介绍过一个小学四则运算自动生成程序的例子,请实现它,要求:
1.能够自动生成四则运算练习题
2.可以定制题目数量
3.用户可以选择运算符
4.用户设置最大数(如十以内、百以内等)
5.用户选择是否有括号、是否有小数
6.用户选择输出方式(如输出到文件、打印机等)
7.最好能提供图形用户界面(根据自己能力选做,以完成上述功能为主)

题目2

现有一新建办公大厦,共有21层,共有四部电梯,所有电梯基本参数如下表所示,其使用规定如下:
1.楼层号为0~20,其中0号为地下一层
2.有楼层限制的电梯不在相应楼层停靠,如单双层
3.所有电梯采用统一按钮控制
4.请根据上述要求设计并实现一个电梯控制程序,使得用户平均等待时间尽可能小,如果有图形显示就更好了。
5.算法设计方面问题,大家也可以咨询助教,或者参考这篇文章 https://www.jianshu.com/p/eec35bd4e0df
6.另外大家也可以参考邹老师的这篇文章 https://www.cnblogs.com/xinz/archive/2011/03/20/1989662.html

电梯编号 可服务楼层 最大乘客数量 最大载重量
1 全部楼层 10 800kg
2 单层 10 800kg
3 双层 10 800kg
4 全部楼层 20 200kg

分工及代码

题目选择及分工

作业选择

我们选择的是题目二。

角色分工

领航员:刘新宇
驾驶员:林乐伟

作业代码

代码链接

电梯处理函数

import time
# 电梯走一层所需要的时间 /S
SPEED = 2

# 电梯类
class Elevator:
    def __init__(self,eNum,type,pMaxNum,weight):
        """
        :param eNum: 电梯编号
        :param type: 电梯类型 0 全部楼层 1 单层 2 双层
        :param pMaxNum: 最大载客量
        :param weight: 最大载重量
         pNum      : 现载客量
         direction : 电梯运行方向  1 上 0 下
         floor     : 电梯所在楼层
         list      : 记录电梯所有需要停下的楼层
         maxFloor  : 记录运行方向最远的楼层
         status    : 电梯状态 0 等待 1 运行 2 操作
        """
        self.eNum = eNum
        self.type = type
        self.pMaxNum = pMaxNum
        self.weight = weight
        self.pNum = 0
        self.direction = 1
        self.floor = 0
        self.list = []
        self.maxFloor = 0
        self.status = 0
        self.signal = 0
    # 电梯日志函数
    def log(self):
        if self.direction==0:
            print("电梯 " + str(self.eNum) + " 所在楼层 " + str(self.floor) +
                  " 电梯运行方向 " + "↓" )
        else:
            print("电梯 " + str(self.eNum) + " 所在楼层 " + str(self.floor) +
                  " 电梯运行方向 " +  "↑")

    # 电梯上下函数函数
    def operation(self):
        time.sleep(SPEED)
        self.floor += 1 if self.direction else -1
        if self.floor==20:
            if self.direction == 1:
                self.direction = 0
            else:
                self.direction = 1

    # 权值
    def weighT(self,num,direction):
        """
        算法尚不完备
        :param num: 所在楼层
        :param direction: 要去的方向
        :return: 权值 权值小的电梯接任务
        """
        if (num%2==0 and (self.type==0 or self.type==2)) or (num%2==1 and (self.type==0 or self.type==1)):
            if self.pNum<self.pMaxNum:
                if self.direction == direction:
                    if direction==1:
                        if self.floor>num:
                            return 2*self.maxFloor-num-self.floor
                        else:
                            return num-self.floor
                    else:
                        if self.floor<num:
                            return self.floor+num-2*self.maxFloor
                        else:
                            return self.floor-num
                else:
                    if direction==1:
                        if self.floor<num:
                            return self.floor+num-2*self.maxFloor
                        else:
                            if self.maxFloor<num:
                                return self.floor+num-2*self.maxFloor
                            else:
                                return self.floor-num
                    else:
                        if self.floor>num:
                            return 2*self.maxFloor-num-self.floor
                        else:
                            if self.maxFloor>num:
                                return 2*self.maxFloor-num-self.floor
                            else:
                                return num-self.floor

        return 999

    # 接 当乘客在外面按下按键
    def pickUp(self,num,direction):
        """
        :param num: 要接的乘客在几楼
        :return: None
        """
        self.list.append(num)
        self.maxFloor= max(self.maxFloor,num)
        if self.status==0:
            self.status = 1
            self.direction = direction
        print("电梯 " + str(self.eNum) + "接单了")

    # 乘客进入
    def comeIn(self,pNum):
        """
        :param pNum: 上电梯人数
        :return: None
        """
        #pNum = input("有几位乘客要进入电梯?")
        if pNum + self.pNum <= self.pMaxNum:
            self.pNum += pNum
            print("成功进入乘客 " + str(pNum) + " 位,电梯上共有乘客 " + str(self.pNum) + " 位。")
        else:
            self.pNum = self.pMaxNum
            print("进入乘客 " + str(self.pMaxNum-self.pNum) + " 位,因为电梯人数已满有 "
                  + str(pNum-self.pMaxNum+self.pNum) + " 位乘客没有进入电梯")

    # 送 乘客在轿厢内按下按键
    def send(self,num):
        """
        :param num: 去几楼
        :return: None
        """
        #num = input("请输入想要去的楼层")
        if not len(self.list):
            if self.floor>num :
                self.direction=0
            else:
                self.direction=1
        self.list.append(num)
        self.status = 1
        if self.direction==1:
            self.maxFloor = max(self.maxFloor,num)
        else:
            self.maxFloor = min(self.maxFloor,num)

    # 乘客下电梯
    def leave(self,num):
        # num = input("电梯上共有 " + str(self.pNum) + " 有几位乘客要在此楼层下电梯?")
        print(str(num) + " 位乘客在 " + str(self.floor) + " 下了电梯")
        self.pNum -= num
        if len(self.list):
            if self.floor==self.maxFloor:
                self.changeDirection()
        else:
            self.status = 0

    # 电梯改变方向
    def changeDirection(self):
        if self.direction==1:
            self.direction=0
            self.maxFloor = sorted(self.list)[0]
        else:
            self.direction=1
            self.maxFloor = sorted(self.list)[0]
    def run(self):
        while(1):
            while(self.status==1):
                self.operation()
                self.log()
                if(self.floor in self.list):
                    self.list.remove(self.floor)
                    self.status = 2
                    print("等待进行上下电梯选择楼层操作")
                    print(self.list)
                    while(self.signal<1):
                        x=1
                    self.signal = 0
                    # self.leave()
                    # self.comeIn()
                    # self.send()

界面代码

from tkinter import *
from thread import *
import time


def update():
    while (1):
        if e1.status == 2:
            if e1.pNum != 0:
                fm13.pack(fill=BOTH)
                e1.status = 1
            else:
                fm11.pack(fill=BOTH)
                e1.status = 1
        if e2.status == 2:
            if e2.pNum != 0:
                fm23.pack(fill=BOTH)
                e2.status = 1
            else:
                fm21.pack(fill=BOTH)
                e2.status = 1
        if e3.status == 2:
            if e3.pNum != 0:
                fm33.pack(fill=BOTH)
                e3.status = 1
            else:
                fm31.pack(fill=BOTH)
                e3.status = 1
        if e4.status == 2:
            if e4.pNum != 0:
                fm43.pack(fill=BOTH)
                e4.status = 1
            else:
                fm41.pack(fill=BOTH)
                e4.status = 1
        time.sleep(2)
        canvas1.delete(ALL)
        canvas1.create_rectangle(20, -int(e1.floor) * 20 + 500, 120, -(int(e1.floor) * 20 + 20) + 500, fill='black')
        canvas1.create_rectangle(140, -int(e2.floor) * 20 + 500, 240, -(int(e2.floor) * 20 + 20) + 500, fill='black')
        canvas1.create_rectangle(260, -int(e3.floor) * 20 + 500, 360, -(int(e3.floor) * 20 + 20) + 500, fill='black')
        canvas1.create_rectangle(380, -int(e4.floor) * 20 + 500, 480, -(int(e4.floor) * 20 + 20) + 500, fill='black')


def w(num, direction):
    wList = {1: e1.weighT(num, direction), 2: e2.weighT(num, direction),
             3: e3.weighT(num, direction), 4: e4.weighT(num, direction)}
    print(wList)
    eNum = sorted(zip(wList.values(), wList.keys()))[0]
    if eNum[0] != 999:
        if eNum[1] == 1:
            e = e1
        elif eNum[1] == 2:
            e = e2
        elif eNum[1] == 3:
            e = e3
        else:
            e = e4
        e.pickUp(num,direction)
    else:
        print("暂无电梯可用,请稍后重试")


def up():
    num = I1.get()
    print(num)
    direction = 1
    w(int(num), int(direction))


def down():
    num = I1.get()
    direction = 0
    w(int(num), int(direction))


# 电梯1
def e1Leave():
    num = I16.get()
    e1.leave(int(num))
    fm13.forget()
    fm11.pack(fill=BOTH)


def e1ComeIn():
    num = I12.get()
    e1.comeIn(int(num))
    fm11.forget()
    if e1.pNum != 0:
        fm12.pack(fill=BOTH)
    else:
        e1.signal = 1


def e1Send():
    num = I14.get()
    e1.send(int(num))
    e1.signal = 1
    fm12.forget()


# 电梯2
def e2Leave():
    num = I26.get()
    e2.leave(int(num))
    fm23.forget()
    fm21.pack(fill=BOTH)


def e2ComeIn():
    num = I22.get()
    e2.comeIn(int(num))
    fm21.forget()
    if e2.pNum != 0:
        fm22.pack(fill=BOTH)
    else:
        e2.signal = 1

def e2Send():
    num = I24.get()
    e2.send(int(num))
    e2.signal = 1
    fm22.forget()


# 电梯3
def e3Leave():
    num = I36.get()
    e3.leave(int(num))
    fm33.forget()
    fm31.pack(fill=BOTH)


def e3ComeIn():
    num = I32.get()
    e3.comeIn(int(num))
    fm31.forget()
    if e3.pNum != 0:
        fm32.pack(fill=BOTH)
    else:
        e3.signal = 1

def e3Send():
    num = I34.get()
    e3.send(int(num))
    e3.signal = 1
    fm32.forget()


# 电梯4
def e4Leave():
    num = I46.get()
    e4.leave(int(num))
    fm43.forget()
    fm41.pack(fill=BOTH)


def e4ComeIn():
    num = I42.get()
    e4.comeIn(int(num))
    fm41.forget()
    if e4.pNum != 0:
        fm42.pack(fill=BOTH)
    else:
        e4.signal = 1

def e4Send():
    num = I44.get()
    e4.send(int(num))
    e4.signal = 1
    fm42.forget()

win = Tk()
win.geometry("1000x800") #设置窗口大小
win.title("电梯算法")
# Canvas
canvas1 = Canvas(win, bg='blue', height=500, width=500)
canvas1.create_rectangle(20,-int(e1.floor)*20+500,120,-(int(e1.floor)*20+20)+500,fill='black')
canvas1.create_rectangle(140,-int(e2.floor)*20+500,240,-(int(e2.floor)*20+20)+500,fill='black')
canvas1.create_rectangle(260,-int(e3.floor)*20+500,360,-(int(e3.floor)*20+20)+500,fill='black')
canvas1.create_rectangle(380,-int(e4.floor)*20+500,480,-(int(e4.floor)*20+20)+500,fill='black')
canvas1.pack(side="left")

# 总输入 楼层 上下
fm1 = Frame(win)
L1 = Label(fm1,text="请输入所在楼层")
I1 = Entry(fm1)
L2 = Label(fm1,text="请选择方向")
B1 = Button(fm1,text="↑",command=up)
B2 = Button(fm1,text="↓",command=down)
L1.pack(side=TOP,fill=Y)
I1.pack(side=TOP,fill=Y)
L2.pack(side=TOP,fill=Y)
B1.pack()
B2.pack()
fm1.pack(fill=BOTH)

# 电梯1输入进入人数
fm11 = Frame(win)
L11 = Label(fm11,text="电梯1 :请输入进入电梯人数")
I12 = Entry(fm11)
B11 = Button(fm11, text='确认',command=e1ComeIn)
L11.pack(side=TOP,fill=Y)
I12.pack(side=TOP,fill=Y)
B11.pack(side=TOP,fill=Y)


# 电梯1选择楼层
fm12 = Frame(win)
L13 = Label(fm12,text="电梯1 :请选择去哪楼")
I14 = Entry(fm12)
B12 = Button(fm12, text='确认',command=e1Send)
L13.pack(side=TOP,fill=Y)
I14.pack(side=TOP,fill=Y)
B12.pack(side=TOP,fill=Y)


# 电梯1输入离开人数
fm13 = Frame(win)
L15 = Label(fm13,text="电梯1 :请输入离开电梯人数")
I16 = Entry(fm13)
B13 = Button(fm13, text='确认',command=e1Leave)
L15.pack(side=TOP,fill=Y)
I16.pack(side=TOP,fill=Y)
B13.pack(side=TOP,fill=Y)


# 电梯2输入进入人数
fm21 = Frame(win)
L21 = Label(fm21,text="电梯2 :请输入进入电梯人数")
I22 = Entry(fm21)
B21 = Button(fm21, text='确认',command=e2ComeIn)
L21.pack(side=TOP,fill=Y)
I22.pack(side=TOP,fill=Y)
B21.pack(side=TOP,fill=Y)


# 电梯2选择楼层
fm22 = Frame(win)
L23 = Label(fm22,text="电梯2 :请选择去哪楼")
I24 = Entry(fm22)
B22 = Button(fm22, text='确认',command=e2Send)
L23.pack(side=TOP,fill=Y)
I24.pack(side=TOP,fill=Y)
B22.pack(side=TOP,fill=Y)


# 电梯2输入离开人数
fm23 = Frame(win)
L25 = Label(fm23,text="电梯2 :请输入离开电梯人数")
I26 = Entry(fm23)
B23 = Button(fm23, text='确认',command=e2Leave)
L25.pack(side=TOP,fill=Y)
I26.pack(side=TOP,fill=Y)
B23.pack(side=TOP,fill=Y)


# 电梯3输入进入人数
fm31 = Frame(win)
L31 = Label(fm31,text="电梯3 :请输入进入电梯人数")
I32 = Entry(fm31)
B31 = Button(fm31, text='确认',command=e3ComeIn)
L31.pack(side=TOP,fill=Y)
I32.pack(side=TOP,fill=Y)
B31.pack(side=TOP,fill=Y)


# 电梯3选择楼层
fm32 = Frame(win)
L33 = Label(fm32,text="电梯3 :请选择去哪楼")
I34 = Entry(fm32)
B32 = Button(fm32, text='确认',command=e3Send)
L33.pack(side=TOP,fill=Y)
I34.pack(side=TOP,fill=Y)
B32.pack(side=TOP,fill=Y)


# 电梯3输入离开人数
fm33 = Frame(win)
L35 = Label(fm33,text="电梯3 :请输入离开电梯人数")
I36 = Entry(fm33)
B33 = Button(fm33, text='确认',command=e3Leave)
L35.pack(side=TOP,fill=Y)
I36.pack(side=TOP,fill=Y)
B33.pack(side=TOP,fill=Y)


# 电梯4输入进入人数
fm41 = Frame(win)
L41 = Label(fm41,text="电梯4 :请输入进入电梯人数")
I42 = Entry(fm41)
B41 = Button(fm41, text='确认',command=e4ComeIn)
L41.pack(side=TOP,fill=Y)
I42.pack(side=TOP,fill=Y)
B41.pack(side=TOP,fill=Y)


# 电梯4选择楼层
fm42 = Frame(win)
L43 = Label(fm42,text="电梯4 :请选择去哪楼")
I44 = Entry(fm42)
B42 = Button(fm42, text='确认',command=e4Send)
L43.pack(side=TOP,fill=Y)
I44.pack(side=TOP,fill=Y)
B42.pack(side=TOP,fill=Y)


# 电梯4输入进入人数
fm43 = Frame(win)
L45 = Label(fm43,text="电梯4 :请输入离开电梯人数")
I46 = Entry(fm43)
B43 = Button(fm43, text='确认',command=e4Leave)
L45.pack(side=TOP,fill=Y)
I46.pack(side=TOP,fill=Y)
B43.pack(side=TOP,fill=Y)

t=threading.Thread(target=update)
t.start()
win.mainloop()


线程代码

from elevator import *

import threading

e1 = Elevator(1,0,10,800)
e2 = Elevator(2,1,10,800)
e3 = Elevator(3,2,10,800)
e4 = Elevator(4,0,20,2000)

# 创建线程
t1  = threading.Thread(target=e1.run)
t2  = threading.Thread(target=e2.run)
t3  = threading.Thread(target=e3.run)
t4  = threading.Thread(target=e4.run)
t1.start()
t2.start()
t3.start()
t4.start()

测试

单元测试

测试代码

import unittest
from elevator import *
e1 = Elevator(1, 0, 10, 800)
class Testelevator(unittest.TestCase):
    #每个测试方法以test开头

    def test_weighT(self):
        self.assertEqual(2, e1.weighT(2, 1))
    def test_pickUp(self):
        self.assertEqual(1, e1.pickUp(2, 1))
if __name__ == '__main__':
    #verbosity  输出详细程度 0 1 2
    unittest.main(verbosity=2)

测试结果

由于函数大多为操作函数,所以,只测了两个函数
测试图片

总结

个人总结

在本次的结对过程中,我扮演的是领航员的角色。他的编程能力很强,所以在这个过程当中我完全是以一个学习者的角色在旁边辅助。他让我学会了很多变成的小技巧,和一些优化代码的方法。在整个过程当中,我学习了很多。学习了python的简单编程,学习了对错误的处理,学习了代码优化的一些技巧。总之,很感谢队友对我的帮助。
在这个结对编程的过程中,我也深刻地认识到了结对编程的必要性。在课上,老师在讲课的时候,我会觉得,两个人敢一个人就可以完成的事,感觉浪费时间还浪费人力。影响整个过程的进度。但是,在结对的过程当中,我会发现这样的效率不是1+1=2,而是1+1>2。在这个过程当中,彼此的编程思路发生碰撞,会有更高的方法实现同样的事情,使代码结构更牢固,执行效率高。并不会出现浪费的情况。因为,在一个人编程时,思路会有局限性,而且,当一个人认准一个思路他总是会相对这个思路修改,并不会考虑其他。但是,当两个人一起看一个问题时,每个人的思路汇集会有更好的方法解决。但是,对于一些简单的功能实现,会出现浪费时间。我个人觉得,结对编程更适合一些功能复杂,并且要求执行效率高的这样的程序编写。

posted on 2019-05-03 19:58  猿人太一  阅读(192)  评论(0编辑  收藏  举报