程序员太萌了!利用Python给儿子画一个萌化的蜘蛛侠

Posted python可乐编程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了程序员太萌了!利用Python给儿子画一个萌化的蜘蛛侠相关的知识,希望对你有一定的参考价值。

你是从什么时候开始喜欢上漫威电影的?美国队长,钢铁侠,雷神?

我先入坑的是因为看了蜘蛛侠,小时候看完就幻想着什么时候自己也能成为一个英雄,我觉得第一代蜘蛛侠刻画得是最好的,也是给我印象最深刻的一代蜘蛛侠,从第一部开始慢慢的变强,慢慢的诠释什么叫做能力越大,责任越大,身体素质,精神力量都无比强大。今天我想用Python Turtle库画一个萌版的蜘蛛侠,来怀恋下童年。

很多人学习python,不知道从何学起。
很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
很多已经做案例的人,却不知道如何去学习更加高深的知识。
那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!
QQ群:701698587
欢迎加入,一起讨论 一起学习!

 

最终效果图:

 

 

源码(可直接运行):

from turtle import *
speed(13)  #绘画速度控制
bgcolor("#990000")
pensize(10)
penup()
goto(0,50)
pendown()
circle(-120)
penup()
circle(-120,-60)
pendown()
pensize(5)
right(50)
circle(70,55)
right(85)
circle(75,58)
right(90)
circle(70,55)
right(90)
circle(70,58)

#身子
penup()
pensize(10)
goto(80,15)
pendown()
seth(92)
fd(135)
seth(125)
circle(30,135)
seth(190)
fd(50)
seth(125)
circle(30,135)
seth(275)
fd(90)

#胳膊1
penup()
pensize(10)
goto(92,-150)
seth(240)
pendown()
fd(80)
left(10)
circle(-28,185)



#胳膊2
penup()
goto(0,50)
seth(0)
pensize(10)
circle(-120,-60)
seth(200)
pendown()
fd(72)
left(20)
circle(30,150)
left(20)
fd(20)
right(15)
fd(10)
pensize(5)
fillcolor("#3366cc")
begin_fill()
seth(92)
circle(-120,31)
seth(200)
fd(45)
left(90)
fd(52)
end_fill()
fd(-12)
right(90)
fd(40)
penup()
right(90)
fd(18)
pendown()
right(86)
fd(40)
penup()
goto(-152,-86)
pendown()
left(40)
circle(35,90)

#身体着色
penup()
goto(-80,116)
seth(10)
pensize(5)
pendown()
begin_fill()
fillcolor("#3366cc")
fd(155)
seth(-88)
fd(37)
seth(195)
fd(156)
end_fill()

penup()
goto(-75,38)
seth(15)
pendown()
begin_fill()
fd(158)
seth(-88)
fd(55)
seth(140)
circle(120,78)
end_fill()




#胳膊1着色
penup()
fillcolor("#3366cc")
pensize(5)
goto(75,-170)
pendown()
begin_fill()
seth(240)
fd(30)
right(90)
fd(17)
end_fill()
fd(10)
left(80)
fd(55)
penup()
left(90)
fd(15)
pendown()
left(85)
fd(55)
penup()
goto(43,-225)
left(84)
pendown()
circle(60,51)

speed(0)
#身体竖纹
for i in range(3):
    penup()
    goto(-70+i*15,135)
    seth(-90)
    pendown()
    pensize(5)
    fd(15-2*i)
for i in range(3):
    penup()
    goto(36 + i * 15, 156)
    seth(-90)
    pendown()
    pensize(5)
    fd(15 - 2 * i)

    a = -60
    b = 70
for i in range(4):
    penup()
    goto(a,b)
    a=a+40
    b=b+10
    seth(-90)
    pendown()
    pensize(5)
    fd(26)


def oo (li,jing):
    penup()
    goto(0,50)
    seth(0)
    circle(-120, li)
    pendown()
    right(jing)

pensize(5)
oo(-60,110)
fd(130)
oo(-28,96)
fd(140)
oo(9,89)
fd(144)
oo(42,70)
fd(160)
oo(80,60)
fd(130)

penup()
goto(-80,-40)
right(160)
pendown()
right(50)
circle(70,45)
right(75)
circle(70,38)
right(50)
circle(70,45)
right(90)
circle(70,48)

penup()
goto(-53,-70)
pendown()
left(40)
circle(70,30)
right(50)
circle(70,20)
right(50)
circle(70,38)
right(70)
circle(70,24)

penup()
goto(-19,-105)
left(72)
pendown()
fd(22)
right(60)
fd(22)

oo(-140,80)
circle(-90,120)

penup()
oo(140,100)
circle(90,13)
pendown()
right(-50)
circle(70,45)
right(75)
circle(70,38)
right(50)
circle(70,36)

penup()
goto(22,-185)
right(70)
pendown()
fd(72)

penup()
goto(-40,-182)
right(38)
pendown()
fd(70)




speed(10)

#左眼
penup()
pensize(7)
goto(-15,-110)
seth(0)
pendown()
pensize(10)
begin_fill()
left(130)
fd(110)
right(250)
circle(90,60)
circle(40,120)
fillcolor("#F5FFFA")
end_fill()
#右眼
penup()
goto(5,-110)
pendown()
begin_fill()
right(30)
fd(110)
right(-250)
circle(-90,60)
circle(-40,120)
end_fill()
done()

 

期待你们的三连(点赞,收藏,评论),你们的支持是我持续输出的动力,感谢。

利用python画出动态高优先权优先调度

技术图片

之前写过一个文章。

利用python画出SJF调度图

动态高度优先权优先调度

动态优先权调度算法,以就绪队列中各个进程的优先权作为进程调度的依据。各个进程的优先权在创建进程时所赋予,随着进程的推进或其等待时间的增加而改变。进程的优先权利用某一范围内的整数来表示。有的系统数值越小优先权越高,如Unix系统,有的系统则反之。采用该算法时,每次总是在就绪队列中选择一个优先权最高的进程进行调度,并将处理机分配给该进程。动态优先权调度算法又分为抢占式和非抢占式两种。

调度结果:

技术图片img

调度数据

A 0 5 3
1 3 5
2 1 3
3 1 4
4 2 2
技术图片img

算法流程图

技术图片img

类初始化

本来想要在SJF调度的基础上修改的,也就是继承,可是发现了问题,只能重新修改类了。

self.data = []存储进程
self.name = ‘‘ 进程名字
self.service_time = 0 服务时间
self.arrival_time = 0 到达时间
self.state = ‘‘ 初始状态
self.number = 0 进程数量
self.timeout = 0 超时限定
self.start = 0 开始时间
self.end = 0 结束时间
self.n 动态优先权的变化大小

获取数据:

获取数据可以从文件(如.txt)中读入,亦可以从console读入。这里要求一个地方,就是数据的格式,名字,到达时间,服务时间。中间用空格分开。如下面表格:

namearrival_timeservice_time优先权
A 0 5 3
B 1 3 5
C 2 1 3
D 3 1 4
E 4 4 4
def get_data_file(self):
        with open(‘data2.txt‘"r", encoding="utf-8"as file:
            for line in file.read().splitlines():
                name, arrival_time, service_time, priority = line.split()
                # insert the process
                self.insert_data(name, arrival_time, service_time, priority)
        file.close()
        # initial queue
        # sort first arrival_time and second service_time
        self.data.sort(key=lambda x: (x[‘arrival_time‘], x[‘priority‘]))
        # update and recode id
        for i in range(self.number):
            self.data[i][‘index‘] = i

    def get_data_input(self):
        print(‘How many processes do you want input?‘)
        processes_number = int(input(‘Please enter an integer of type int:‘))
        print(‘name and arrival_time and service_time and priority of process‘)
        print(‘such as:A 0 5 3‘)
        for _ in range(processes_number):
            name, arrival_time, service_time, priority = input(
                ‘Please enter ‘).split()
            self.insert_data(name, arrival_time, service_time, priority)
        # initial queue
        # sort first arrival_time and second service_time
        self.data.sort(key=lambda x: (x[‘arrival_time‘], x[‘priority‘]))
        # update and recode id
        for i in range(self.number):
            self.data[i][‘index‘] = i

进行调度

调度的过程就是队列,每次取已经到达的进程优先权高的,如果优先权相同,则调度时间片早到达队列的。

这个地方有一个小提示:使用队列,并不一定用到队列。队列可以是逻辑结构。这个算法的基本思想就是,在已经到达的进程中,执行优先权高的进程,执行一个时间片,优先权减少n,如果同优先权的情况下,排在队列之前的优先。针对这个问题的队列我们可以设计三种方法:优先队列,排序维护,插队。优先队列没什么好说的,C++里面的内容,只要定义得对,结构体重载写正确,那就很容易实现。另外一个就是当没有优先队列的时候,我们可以用排序来维护或者达到这个效果,是这个队首元素是我们想要的。另外一种方法就是直接插入元素。

技术图片img 技术图片img 技术图片img

入队的过程可以简化成这样的方式,这样操作即可以保证了队列的有序,又可以保证,同优先级的先后问题。这样的方法比排序快,而且容易理解。

这个插入的方法呢,python列表直接就有,参数为index和value,直接遍历进行插入进程就可以。

def to_get_index(self, data, process):
        for i in range(len(data)):
            if process[‘priority‘] > data[i][‘priority‘]:
                return i
        return len(data)

    def get_next_data(self, index,  data):
        # get processes from the beginning to the end of the current process
        result = [x for x in self.data if x[‘arrival_time‘] <=
                  self.end and x[‘state‘] == ‘w‘ and x not in data]
        if result or data:
            # maintain the queue
            for process in result:
                data.insert(self.to_get_index(data, process), process)
            return data
        # no processes entered at current time
        for process in self.data:
            if process[‘state‘] == ‘w‘:
                self.start = self.end = process[‘arrival_time‘]
                return [process]
        return []

    def implement(self):
        ‘‘‘start algorithm‘‘‘
        # get first process
        data = [self.data[0]]
        # update the time of start
        self.start = self.end = data[0][‘arrival_time‘]
        while data:
            # update information
            self.update_information(
                data[0][‘index‘], self.end, self.end + 1, data)
            # get next process or processes
            data = self.get_next_data(data.pop(0)[‘index‘], data)
        self.data.sort(key=lambda x: x[‘id‘])

数据更新

数据更新就是更新原始的数据,包括计算状态,开始时间,结束时间,周转时间,平均周转时间等等。

def update_information(self, index, start, end, data):
        self.data[index][‘state‘] = ‘R‘
        print(‘-‘*40)
        # print("running order is:", *[i[‘name‘] for i in data], sep=‘->‘)
        print("from {:} to {:}".format(start, end))
        print("the running order is :")
        self.show_data_running(start, end, data)
        self.data[index][‘start‘].append(start)
        self.data[index][‘end‘].append(end)
        # had finished
        self.data[index][‘state‘] = ‘w‘
        if len(self.data[index][‘end‘]) == self.data[index][‘service_time‘]:
            self.data[index][‘state‘] = ‘f‘
            self.data[index][‘turnaround_time‘] = end - 
                self.data[index][‘arrival_time‘]
            self.data[index][‘authorized_turnover_time‘] = self.data[index][‘turnaround_time‘] / 
                self.data[index][‘service_time‘]
        else:
            self.data[index][‘priority‘] -= self.n
        self.start = start
        self.end = end
        # self.show_data()
        print("the finish status is :")
        self.show_data_running(start, end, data)

绘制图形

利用python的第三方库,根据数据进行绘图,然后展示出好看的图片。

这里引用上次博客的图形。

def init_image(self):
        # size = 1000 * 500
        plt.figure(‘SJF‘, figsize=(105))
        self.drow_image()
        # setting xticks for 0 to self.end + 2
        plt.xticks([i for i in range(self.end + 3)])
        # setting title
        plt.title(‘the time of process about this‘)

        plt.xlabel(‘‘)
        plt.ylabel(‘processes‘)
        # setting yticks.such as A == 0
        plt.yticks(self.get_y_ticks()[0], self.get_y_ticks()[1])

这里引用上次的博客的图形。

技术图片img

这里引用上次的博客的图形。

技术图片img

这里引用上次的博客的图形。

技术图片img 技术图片img
def set_ax(self):
        ax = plt.gca()  # 获取到当前坐标轴信息
        ax.spines[‘right‘].set_color(‘none‘)
        ax.spines[‘bottom‘].set_color(‘none‘)
        ax.xaxis.set_ticks_position(‘top‘)   # 将X坐标轴移到上面
        ax.invert_yaxis()  # 反转Y坐标轴
        ax.grid(True, linestyle=‘-.‘)  # 网格
def show_image(self):
        self.init_image()
        self.set_ax()
        plt.savefig(‘result.png‘, dpi=300)
        plt.show()

通过之前可以看出,都没有变化,那么我们绘图可以直接调用之前的数据吗?

当然不行,否则绘制的直线会错乱:

如下图:

技术图片img 技术图片img

我们想要得到的结果就是所有的A标签一个颜色,所有的B标签一个颜色,所以我们需要自己设定颜色。

def drow_image(self):
        colormap = plt.cm.gist_ncar  # nipy_spectral, Set1,Paired
        colors = [‘r‘‘g‘‘b‘‘c‘‘m‘‘y‘‘k‘] + 
            [colormap(random.random()) for i in range(len(self.data) + 1)]
        for i in range(len(self.data)):
            # the time line of process from start to end
            process = self.data[i]
            plt.plot([process[‘start‘][0], process[‘end‘][0]],
                     [process[‘id‘], process[‘id‘]],
                     label=process[‘name‘],
                     color=colors[i],
                     lw=2)
            for x1, x2 in zip(process[‘start‘][1:], process[‘end‘][1:]):
                plt.plot([x1, x2],
                         [process[‘id‘], process[‘id‘]],
                         color=colors[i],
                         lw=2)
            # annotation of the key point
            plt.plot([process[‘end‘][-1], process[‘end‘][-1]],
                     [-1, process[‘id‘]],
                     ‘k--‘,
                     lw=1)
        # legend
        plt.legend(loc=‘best‘)

运行结果如图:

技术图片img

这样达到了我们的基本要求。

后记

按照开始的设想,实验二应该直接就是继承实验1,然后修改方法就行了,可是实际的操作过程中遇到了很多问题,比如改某个方法,其它的方法页需要更改,不够既然用类写了,最大的好处就是清晰直观。其实这两个实验把我带进了误区,满脑子都是排序,队列,维护一类的词语,从而忘记了最最简单的方法,直接一个循环,然后依次遍历取最优解就行,时间复杂度和空间复杂度都是最低的。还有可惜的就是,没有优化自己的代码,写的太难看了,运用到的方法也不太好。关于代码没有注释的问题,其实是有注释的,实验报告中为了减少篇幅,所以删去了,代码的详细情况和解释,包括一些独特的用法,都记录在了我的博客中。

最最重要的一件事情,就是,至今还没有实现动态的绘制直线,我知道有这个方法,却不是太懂,看了很多资料,也没有一个最合理的解释。这一个地方就有机会在实现。

代码的风格:参照的是PEP8。

最后,这两个调度的实验结束了,最开始自己想要用python动态绘制调度图的想法也落实了一半,但是会不会实现就不好说了,估计也没有这个时候写实验的冲劲了。但是有一点,python挺好玩的,也挺喜欢这种实践与理论结合的方式,下一次的实验,用plt显然是不可以的了,实现的方式和是否可视化展示,还没想好,反正路在脚下,走就完事。

完整代码

# -*- coding: utf-8 -*-
# @Author: wfy
# @Date:   2020-04-10 15:31:44
# @Last Modified by:   wfy
# @Last Modified time: 2020-04-19 10:06:13
import random
import matplotlib.pyplot as plt


class Solution():
    """to achieve SJF"""

    def __init__(self):
        super(Solution, self).__init__()
        # save processes
        self.data = []
        self.name = ‘‘
        self.service_time = 0
        self.arrival_time = 0
        self.priority = 0
        self.state = ‘‘
        self.number = 0
        self.timeout = 0
        self.start = 0
        self.end = 0
        self.n = 1

    def insert_data(self, name, arrival_time, service_time, priority):
        self.data.append({
            ‘id‘: self.number,
            ‘name‘: name,
            ‘arrival_time‘: int(arrival_time),
            ‘service_time‘: int(service_time),
            ‘priority‘: int(priority),
            ‘state‘‘w‘,
            ‘turnaround_time‘0,
            ‘authorized_turnover_time‘0,
            ‘start‘: [],
            ‘end‘: [],
        })
        self.timeout = max(self.timeout, int(arrival_time))
        self.number += 1

    def get_data_file(self):
        with open(‘data2.txt‘"r", encoding="utf-8"as file:
            for line in file.read().splitlines():
                name, arrival_time, service_time, priority = line.split()
                # insert the process
                self.insert_data(name, arrival_time, service_time, priority)
        file.close()
        # initial queue
        # sort first arrival_time and second service_time
        self.data.sort(key=lambda x: (x[‘arrival_time‘], x[‘priority‘]))
        # update and recode id
        for i in range(self.number):
            self.data[i][‘index‘] = i

    def get_data_input(self):
        print(‘How many processes do you want input?‘)
        processes_number = int(input(‘Please enter an integer of type int:‘))
        print(‘name and arrival_time and service_time and priority of process‘)
        print(‘such as:A 0 5 3‘)
        for _ in range(processes_number):
            name, arrival_time, service_time, priority = input(
                ‘Please enter ‘).split()
            self.insert_data(name, arrival_time, service_time, priority)
        # initial queue
        # sort first arrival_time and second service_time
        self.data.sort(key=lambda x: (x[‘arrival_time‘], x[‘priority‘]))
        # update and recode id
        for i in range(self.number):
            self.data[i][‘index‘] = i

    def show_data_running(self, start, end, data):
        print("name state priority")
        for process in data:
            print("{:<7} {:6} {}".format(
                process[‘name‘], process[‘state‘], process[‘priority‘]))

    def show_data(self):
        print("{:<6}{:<10}{:<10}{:<10}{:<6}{:<8}{:<7}{:<6}".format(
            ‘name‘‘arr_time‘‘ser_time‘‘priority‘‘周转时间‘‘带权周转时间‘‘start‘‘end‘))
        for process in sorted(self.data, key=lambda x: x[‘id‘]):
            print("{:<6}{:<10}{:<10}{:<10}{:<10}{:<14.2f}{}{}".format(
                process[‘name‘],
                process[‘arrival_time‘],
                process[‘service_time‘],
                process[‘priority‘],
                process[‘turnaround_time‘],
                process[‘authorized_turnover_time‘],
                process[‘start‘],
                process[‘end‘]))

    def update_information(self, index, start, end, data):
        self.data[index][‘state‘] = ‘R‘
        print(‘-‘*40)
        # print("running order is:", *[i[‘name‘] for i in data], sep=‘->‘)
        print("from {:} to {:}".format(start, end))
        print("the running order is :")
        self.show_data_running(start, end, data)
        self.data[index][‘start‘].append(start)
        self.data[index][‘end‘].append(end)
        # had finished
        self.data[index][‘state‘] = ‘w‘
        if len(self.data[index][‘end‘]) == self.data[index][‘service_time‘]:
            self.data[index][‘state‘] = ‘f‘
            self.data[index][‘turnaround_time‘] = end - 
                self.data[index][‘arrival_time‘]
            self.data[index][‘authorized_turnover_time‘] = self.data[index][‘turnaround_time‘] / 
                self.data[index][‘service_time‘]
        else:
            self.data[index][‘priority‘] -= self.n
        self.start = start
        self.end = end
        # self.show_data()
        print("the finish status is :")
        self.show_data_running(start, end, data)

    def to_get_index(self, data, process):
        for i in range(len(data)):
            if process[‘priority‘] > data[i][‘priority‘]:
                return i
        return len(data)

    def get_next_data(self, index,  data):
        # get processes from the beginning to the end of the current process
        result = [x for x in self.data if x[‘arrival_time‘] <=
                  self.end and x[‘state‘] == ‘w‘ and x not in data]
        if result or data:
            # maintain the queue
            for process in result:
                data.insert(self.to_get_index(data, process), process)
            return data
        # no processes entered at current time
        for process in self.data:
            if process[‘state‘] == ‘w‘:
                self.start = self.end = process[‘arrival_time‘]
                return [process]
        return []

    def implement(self):
        ‘‘‘start algorithm‘‘‘
        # get first process
        data = [self.data[0]]
        # update the time of start
        self.start = self.end = data[0][‘arrival_time‘]
        while data:
            # update information
            self.update_information(
                data[0][‘index‘], self.end, self.end + 1, data)
            # get next process or processes
            data = self.get_next_data(data.pop(0)[‘index‘], data)
        self.data.sort(key=lambda x: x[‘id‘])

    def get_y_ticks(self):
        return [x[‘id‘for x in self.data] + [self.data[-1][‘id‘] + 1], [x[‘name‘for x in self.data] + [‘‘]

    def init_image(self):
        # size = 1000 * 500
        plt.figure(‘SJF‘, figsize=(105))
        self.drow_image()
        # setting xticks for 0 to self.end + 2
        plt.xticks([i for i in range(self.end + 3)])
        # setting title
        plt.title(‘the time of process about this‘)

        plt.xlabel(‘‘)
        plt.ylabel(‘processes‘)
        # setting yticks.such as A == 0
        plt.yticks(self.get_y_ticks()[0], self.get_y_ticks()[1])

    def drow_image(self):
        colormap = plt.cm.gist_ncar  # nipy_spectral, Set1,Paired
        colors = [‘r‘‘g‘‘b‘‘c‘‘m‘‘y‘‘k‘] + 
            [colormap(random.random()) for i in range(len(self.data) + 1)]
        for i in range(len(self.data)):
            # the time line of process from start to end
            process = self.data[i]
            plt.plot([process[‘start‘][0], process[‘end‘][0]],
                     [process[‘id‘], process[‘id‘]],
                     label=process[‘name‘],
                     color=colors[i],
                     lw=2)
            for x1, x2 in zip(process[‘start‘][1:], process[‘end‘][1:]):
                plt.plot([x1, x2],
                         [process[‘id‘], process[‘id‘]],
                         color=colors[i],
                         lw=2)
            # annotation of the key point
            plt.plot([process[‘end‘][-1], process[‘end‘][-1]],
                     [-1, process[‘id‘]],
                     ‘k--‘,
                     lw=1)
        # legend
        plt.legend(loc=‘best‘)

    def set_ax(self):
        ax = plt.gca()  # 获取到当前坐标轴信息
        ax.spines[‘right‘].set_color(‘none‘)
        ax.spines[‘bottom‘].set_color(‘none‘)
        ax.xaxis.set_ticks_position(‘top‘)   # 将X坐标轴移到上面
        ax.invert_yaxis()  # 反转Y坐标轴
        ax.grid(True, linestyle=‘-.‘)  # 网格

    def show_image(self):
        self.init_image()
        self.set_ax()
        plt.savefig(‘result.png‘, dpi=300)
        plt.show()

    def main(self):
        self.get_data_file()
        self.show_data()
        self.implement()
        self.show_data()
        self.show_image()


if __name__ == ‘__main__‘:
    try:
        Solution().main()
    except Exception as e:
        print(‘发生异常‘, e)
    else:
        print("end")
    finally:
        print("finally")

以上是关于程序员太萌了!利用Python给儿子画一个萌化的蜘蛛侠的主要内容,如果未能解决你的问题,请参考以下文章

利用python画出动态高优先权优先调度

python用turtle画圆弧

Ruby | 小青蛙席卷盆友圈,今天你蛙儿子回家了吗?

Python 画好看的云词图

33岁转行python,如果不是5岁儿子给我的鼓励,可能幸福也不会来敲门了

用python绘制字符画