猫史档案馆


【Python作品分享】想象与实际【作品秀】

用户:YHY汤圆YHY汤圆查看:0 回复:0 评论:0 创建时间:2022-02-27T19:32:27


【作品展示】

center_image

 

【作品介绍】

 

【作品源代码】

import time, math
import turtle as t

class Human(object):
    def __init__(self, x0, y0, x1=None, y1=None, v0=100, v1=100):
        self.x0 = x0
        self.y0 = y0
        self.tx = x0
        self.ty = y0
        self.x1 = x0 if x1 is None else x1
        self.y1 = y0 if y1 is None else y1
        self.v0 = v0
        self.v1 = v1
        self.tv = v0
        self.in_metro=False
        self.need_get_on=True
        self.should_remove=False
        self.door_index=0

    def move(self,back=False):
        if self.need_get_on:
            if back:
                self.get_on_back()
            else:
                self.get_on()
        else:
            self.get_off()

    def get_on(self):
        if self.ty < -5:
            self.ty+=3
        elif self.ty < 0:
            if self.txself.x1:self.tx-=1
            elif self.ty=self.y1:
            self.in_metro=True
            self.should_remove=True

    def get_on_back(self):
        if self.ty > self.y0:
            self.ty-=1
        else:
            if self.tx > self.x0: self.tx-=1
            elif self.txself.y1:
            self.ty-=1
        else:
            self.in_metro=False
            if self.tv>self.v1:
                self.ty-=1
                self.tv-=2
            if self.tv<=self.v1:
                self.should_remove=True

    def draw(self):
        if self.in_metro:
            return
        x=self.tx
        y=self.ty
        clr=(1-self.tv*0.01,1-self.tv*0.01,1-self.tv*0.01)
        t.pencolor(clr)
        goto_with_penup(x, y)
        t.pensize(1)
        t.begin_fill()
        t.fillcolor(clr)
        t.circle(4)
        t.end_fill()
        ty = 2
        t.sety(y - ty)
        t.goto(x - 6, y - ty - 2)
        t.goto(x, y - ty)
        t.goto(x + 6, y - ty - 2)
        t.goto(x, y - ty)
        ty = 6
        t.sety(y - ty)
        t.goto(x - 2, y - ty - 8)
        t.goto(x, y - ty)
        t.goto(x + 2, y - ty - 8)
        t.goto(x, y - ty)

def fill_rect(w,h,c):
    t.fillcolor(c)
    t.begin_fill()
    for i in range(2):
        t.forward(w)
        t.left(90)
        t.forward(h)
        t.left(90)
    t.end_fill()

def draw_rect(w,h):
    for i in range(2):
        t.forward(w)
        t.left(90)
        t.forward(h)
        t.left(90)

def setx_with_penup(tx):
    t.penup()
    t.setx(tx)
    t.pendown()

def sety_with_penup(ty):
    t.penup()
    t.sety(ty)
    t.pendown()

def goto_with_penup(tx,ty):
    t.penup()
    t.goto(tx,ty)
    t.pendown()

size=60  # 车厢大小
block_num=7  # 车厢数量
human_num_str=[5,2,0,1,3,1,4]  # 每节车厢的人数
# amount_human_num_str=[17,16,20,21,25,21,19]  # 每节车厢的人数
amount_human_num_str=[26,25,24,24,25,24,25]  # 每节车厢的人数
door_pos_arr=[0.3,1,1.7]  # 一节车厢三扇门的位置
door_max_get_on_num=4
def draw_metro(x,size=40,door_open_ratio=0):
    t.clear()
    # t.fillcolor('white')
    # t.begin_fill()
    # goto_with_penup(-1000,200)
    # t.goto(1000,200)
    # t.goto(1000,-500)
    # t.goto(-1000,-500)
    # t.goto(-1000,200)
    # t.end_fill()
    t.pencolor('black')

    t.pensize(1)
    every_width=size*2
    metro_h=size*0.6
    goto_with_penup(x,0)
    t.setx(x-every_width*0.2)
    t.goto(x=x-every_width*0.1,y=metro_h)
    t.setx(x)
    goto_with_penup(x-every_width*0.1,metro_h*0.3)
    draw_rect(metro_h*0.2,metro_h*0.4)
    for a in range(0,block_num):
        sety_with_penup(0)
        setx_with_penup(x + a * every_width)
        draw_rect(size*2,metro_h)

        sety_with_penup(size*0.2)
        window_w=size*0.3
        window_h=size*0.25
        for dx in [(door_pos_arr[0]+door_pos_arr[1])*0.5,(door_pos_arr[1]+door_pos_arr[2])*0.5]:
            setx_with_penup(x + a * every_width + size*dx-window_w*0.5)
            draw_rect(window_w,window_h)

        sety_with_penup(0)
        door_w=size*0.26
        door_open_diff=0
        if door_open_ratio>0:
            r=door_open_ratio*0.01
            door_open_diff=round(door_w*0.5*r)
        for dx in door_pos_arr:
            setx_with_penup(x + a * every_width + size*dx-door_w*0.5-door_open_diff)
            if door_open_diff > 0: fill_rect(door_w*0.5,metro_h*0.8,'white')
            draw_rect(door_w*0.5,metro_h*0.8)
            setx_with_penup(x + a * every_width + size*dx+door_open_diff)
            if door_open_diff > 0: fill_rect(door_w*0.5,metro_h*0.8,'white')
            draw_rect(door_w*0.5,metro_h*0.8)
            if door_open_diff > 0:
                setx_with_penup(x + a * every_width + size*dx-door_open_diff)
                fill_rect(door_open_diff*2,metro_h*0.8,'black')

        sety_with_penup(size*0.25)
        door_window_w=door_w*0.8
        door_window_h=size*0.2
        for dx in door_pos_arr:
            setx_with_penup(x + a * every_width + size * dx - door_window_w * 0.5-door_open_diff)
            draw_rect(door_window_w * 0.5, door_window_h)
            setx_with_penup(x + a * every_width + size * dx+door_open_diff)
            draw_rect(door_window_w * 0.5, door_window_h)

    t.pensize(4)
    for a in range(1,block_num):
        sety_with_penup(0+1)
        setx_with_penup(x + a*every_width+1)
        t.sety(metro_h-1)

def make_human_pos(x,n,door_index,two_line=True):
    arr=[]
    if two_line:
        for i in range(0,n,2):
            human = Human(x-8,-20-20*(i//2),x1=x-4,y1=20)
            human.door_index=door_index
            arr.append(human)
        for i in range(1,n,2):
            human = Human(x+8,-20-20*(i//2),x1=x+4,y1=20)
            human.door_index=door_index
            arr.append(human)
    else:
        for i in range(0,n):
            human = Human(x,-20-20*i,x1=x,y1=20)
            human.door_index=door_index
            arr.append(human)
    return arr

def make_in_metro_human_pos(x, n,door_index):
    arr=[]
    for i in range(0, n):
        human = Human(x, 20 * i, x1=x, y1=-10, v1=0)
        human.door_index=door_index
        human.in_metro=True
        human.need_get_on=False
        arr.append(human)
    return arr

def any_get_off_human_in_door(human_arr, door_index):
    for human in human_arr:
        if human.door_index==door_index:
            if not human.need_get_on and human.in_metro:
                return True
    return False

def check_no_got_on(all_human, door_got_on_num_dic):
    for human in all_human:
        if human.need_get_on and door_got_on_num_dic[human.door_index]>0:
            return False
    return True

def draw_all(all_human):
    door_got_on_num_dic={}
    for i in range(block_num):
        door_got_on_num_dic[i*3]=door_max_get_on_num
        door_got_on_num_dic[i*3+1]=door_max_get_on_num
        door_got_on_num_dic[i*3+2]=door_max_get_on_num

    t.screensize()
    t.setup(width=1.0, height=1.0)

    train_speed = 30
    startx = 800
    endx = -500

    tempx = startx
    while tempx > endx:
        if tempx - endx < 500 and train_speed > 1:
            if len(all_human)<20:
                train_speed *= 0.9 if train_speed < 10 else 0.95
            else:
                train_speed *= 0.95 if train_speed > 10 else 0.98

        tempx -= train_speed
        if tempx < endx:
            tempx = endx
        t.tracer(False)
        draw_metro(int(tempx), size=size)
        for human in all_human: human.draw()
        t.hideturtle()
        t.tracer(True)
        time.sleep(0)

    for i in range(0, 100, 4):
        t.tracer(False)
        draw_metro(-500, size=size, door_open_ratio=i)
        for human in all_human: human.draw()
        t.hideturtle()
        t.tracer(True)
        time.sleep(0)

    while True:
        t.tracer(False)
        draw_metro(int(tempx), size=size, door_open_ratio=100)
        for human in all_human: human.draw()
        t.hideturtle()
        t.tracer(True)
        time.sleep(0)

        for i in range(len(all_human) - 1, -1, -1):
            human = all_human[i]
            if human.need_get_on:
                if door_got_on_num_dic[human.door_index]>0:
                    if not any_get_off_human_in_door(all_human, human.door_index):
                        human.get_on()
                        if human.in_metro:
                            door_got_on_num_dic[human.door_index]-=1
            else:
                human.get_off()

            if all_human[i].should_remove:
                del all_human[i]

        if len(all_human) == 0:
            break
        if check_no_got_on(all_human, door_got_on_num_dic):
            for human in all_human:
                if human.need_get_on:
                    human.y0+=20*(door_max_get_on_num//2)

            break

    for i in range(100, -4, -4):
        t.tracer(False)
        draw_metro(-500, size=size, door_open_ratio=i)
        for human in all_human:
            human.move(back=True)
            human.draw()
        t.hideturtle()
        t.tracer(True)
        time.sleep(0)
        for x in range(len(all_human) - 1, -1, -1):
            if all_human[x].should_remove:
                del all_human[x]

    endx = -2000
    while tempx > endx:
        train_speed = train_speed * 1.02
        tempx -= train_speed
        if tempx < endx:
            tempx = endx
        t.tracer(False)
        draw_metro(int(tempx), size=size)
        for human in all_human:
            human.move(back=True)
            human.draw()
        t.hideturtle()
        t.tracer(True)
        time.sleep(0)
        for x in range(len(all_human) - 1, -1, -1):
            if all_human[x].should_remove:
                del all_human[x]

def run(add_in_metro=None, amount_human=False):
    endx = -500
    num_str = amount_human_num_str if amount_human else human_num_str
    all_human = []
    for i in range(block_num):
        n = 0 if i >= len(num_str) else int(num_str[i])

        n1 = n // 3
        n3 = int(math.ceil(n / 3))
        n2 = n - n1 - n3
        all_human += make_human_pos(endx + i * size * 2 + door_pos_arr[0] * size, n1, i * 3)
        all_human += make_human_pos(endx + i * size * 2 + door_pos_arr[1] * size, n2, i * 3 + 1)
        all_human += make_human_pos(endx + i * size * 2 + door_pos_arr[2] * size, n3, i * 3 + 2)

        if add_in_metro:
            n = 0 if i >= len(add_in_metro) else int(add_in_metro[i])
            n1 = n // 3
            n3 = int(math.ceil(n / 3))
            n2 = n - n1 - n3
            all_human += make_in_metro_human_pos(endx + i * size * 2 + door_pos_arr[0] * size, n1, i * 3)
            all_human += make_in_metro_human_pos(endx + i * size * 2 + door_pos_arr[1] * size, n2, i * 3 + 1)
            all_human += make_in_metro_human_pos(endx + i * size * 2 + door_pos_arr[2] * size, n3, i * 3 + 2)

    while len(all_human)>0:
        draw_all(all_human)

def draw_str(s):
    t.screensize()
    t.setup(width=1.0, height=1.0)
    t.penup()
    t.goto(-300,0)
    t.pendown()
    t.write(s, font=("Arial", 32,"bold"))
    t.hideturtle()

if __name__ == '__main__':
    draw_str('你希望上班坐地铁是这样的')
    time.sleep(2)
    run()
    draw_str('再或者上班坐地铁是这样的')
    time.sleep(2)
    run(add_in_metro=[1,3,1,4,5,2,0])
    draw_str('实际上上班坐地铁是这样的')
    time.sleep(2)
    run(amount_human=True,add_in_metro=[1,3,1,4,5,2,0])
    draw_str('这段程序送给在外打拼的你')
    time.sleep(2)
    t.mainloop()

 

【提示】

部分含有Python第三方库相关内容的作品,在海龟编辑器网页端无法运行哦!如遇到这种情况,可以打开下面的链接,下载海龟编辑器客户端:

https://python.codemao.cn


回复

上一页1 页 / 共 0下一页