Turtle 绘制蟒蛇

问题分析

用程序绘制一条蟒蛇

  • 貌似很有趣,可以来试试
  • 先学会蟒蛇绘制,再绘朵玫瑰花送给TA

    基本形状

    image.png

计算机绘图

  • 计算机绘图是什么原理?
  • 一段程序为何能够产生窗体?
  • 为何能在窗体上绘制图形?
  • Python蟒蛇绘制从哪里开始呢?
  • 如何绘制一条线?
  • 如何绘制一个弧形?
  • 如何绘制一个蟒蛇?

输入输出

  • 输入:开始画蟒蛇的指令
  • 处理:创建画布,在画布上画画
  • 输出:在窗体上呈现一条蟒蛇

算法设计

根据上面蟒蛇的图案:

  1. 创建一个画布
  2. 逆时针从左往右画半圆
  3. 顺时针从左往右画半圆
  4. 逆时针从左往右画半圆
  5. 顺时针从左往右画半圆
  6. 逆时针从左往右画半圆
  7. 顺时针从左往右画半圆
  8. 逆时针从左往右画半圆
  9. 顺时针从左往右画半圆
  10. 从左往右画一条横线
  11. 逆时针从下往上画半圆
  12. 从右往左画一条横线
  13. 结束

实例编写

初步实现

  1. import turtle
  2. turtle.setup(1000, 800, 200, 200)
  3. turtle.circle(40, 80)
  4. turtle.circle(-40, 80)
  5. turtle.circle(40, 80)
  6. turtle.circle(-40, 80)
  7. turtle.circle(40, 80)
  8. turtle.circle(-40, 80)
  9. turtle.circle(40, 80)
  10. turtle.circle(-40, 80)
  11. turtle.circle(40, 80/2)
  12. turtle.forward(40)
  13. turtle.circle(16, 180)
  14. turtle.forward(40 * 2/3)
  15. turtle.done()

运行结果:
image.png
很明显,上面的绘制图形跟预想的图形有一定的差别,但外形上大体还是符合要求的。

改进算法

  1. 调整画笔的起始角度,画一条水平的蟒蛇
  2. 加粗画笔,给蟒蛇身上来点儿肉 ```python

    !/usr/bin/env python

    encoding: utf-8

DrawPython1.py

import turtle

turtle.setup(1000, 800, 200, 200) turtle.setheading(-40) turtle.pensize(25) turtle.circle(40, 80) turtle.circle(-40, 80) turtle.circle(40, 80) turtle.circle(-40, 80) turtle.circle(40, 80) turtle.circle(-40, 80) turtle.circle(40, 80) turtle.circle(-40, 80) turtle.circle(40, 80/2) turtle.fd(40) turtle.circle(16, 180) turtle.fd(40 * 2/3) turtle.done()

  1. 运行结果:<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/268154/1608086847516-931ab300-a2e9-4588-8e95-0405777652f9.png#align=left&display=inline&height=822&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1644&originWidth=2000&size=98016&status=done&style=stroke&width=1000)<br />已经非常接近预想中的结果了,但还是有些小问题,比如没有颜色,超出画布的边界了。
  2. <a name="ntnAg"></a>
  3. ### 进一步改进
  4. 1. 调整画笔的起始位置,让蟒蛇居中显示
  5. 1. 给画笔上色,来一条有颜色的蟒蛇
  6. ```python
  7. #!/usr/bin/env python
  8. # encoding: utf-8
  9. #DrawPython1.py
  10. import turtle
  11. turtle.setup(1000, 800, 200, 200)
  12. turtle.penup()
  13. turtle.forward(-250)
  14. turtle.pendown()
  15. turtle.setheading(-40)
  16. turtle.pensize(25)
  17. turtle.pencolor("purple")
  18. turtle.circle(40, 80)
  19. turtle.circle(-40, 80)
  20. turtle.pencolor("red")
  21. turtle.circle(40, 80)
  22. turtle.circle(-40, 80)
  23. turtle.circle(40, 80)
  24. turtle.circle(-40, 80)
  25. turtle.circle(40, 80)
  26. turtle.circle(-40, 80)
  27. turtle.circle(40, 80/2)
  28. turtle.fd(40)
  29. turtle.circle(16, 180)
  30. turtle.fd(40 * 2/3)
  31. turtle.done()

运行结果:
image.png
至此,我们已经可以画出预想中的蟒蛇了,颜色大小都符合需求。在不修改主体逻辑,不影响运行结果的情况,可以进一步的精简代码。代码越少出错的机会也越少。

完善代码

  1. 采用循环的机制绘制蟒蛇的身体
  2. 为什么要采用循环机制呢?
  3. 假如我们需要画一条很长很长的蟒蛇….
  4. 简单重复的事情交给计算机来做
  5. 每一个计算问题都是简单又可以重复的事情
  6. 一个大的计算问题可以拆分为若干个小的计算问题
import turtle

turtle.setup(650, 350, 200, 200)
turtle.penup()
turtle.forward(-250)
turtle.pendown()
turtle.pensize(25)
turtle.pencolor("purple")
turtle.setheading(-40)
for i in range(4):
    turtle.circle(40, 80)
    turtle.circle(-40, 80)
turtle.circle(40, 80/2)
turtle.forward(40)
turtle.circle(16, 180)
turtle.forward(40 * 2/3)
turtle.done()

运行效果

image.png

举一反三

  • 蟒蛇的颜色:黑色、白色、七彩色…
  • 蟒蛇的长度:1节、3节、10节…
  • 蟒蛇的方向:向左走、斜着走…
  • 蟒蛇的数量:7条蟒蛇…

七彩蟒蛇

range() 函数

import turtle

turtle.setup(1080, 350, 200, 200)
turtle.penup()
turtle.forward(-400)
turtle.pendown()
turtle.pensize(25)
turtle.setheading(-40)
colors = ['red', 'yellow', 'orange', 'purple', 'brown', 'navy', 'olive']
for i in range(7):
    print(i)
    color = colors[i]
    turtle.pencolor(color)
    turtle.circle(40, 80)
    turtle.circle(-40, 80)
turtle.circle(40, 80/2)
turtle.forward(40)
turtle.circle(16, 180)
turtle.forward(40 * 2/3)
turtle.done()
import turtle

turtle.setup(1080, 350, 200, 200)
turtle.penup()
turtle.forward(-400)
turtle.pendown()
turtle.pensize(25)
turtle.setheading(-40)
colors = ['red', 'yellow', 'orange', 'purple', 'brown', 'navy', 'olive']
nums = [0, 1, 2, 3, 4, 5, 6, 7]
for i in nums:
    color = colors[i]
    turtle.pencolor(color)
    turtle.circle(40, 80)
    turtle.circle(-40, 80)
turtle.circle(40, 80/2)
turtle.forward(40)
turtle.circle(16, 180)
turtle.forward(40 * 2/3)
turtle.done()

颜色数组

import turtle

turtle.setup(1080, 350, 200, 200)
turtle.penup()
turtle.forward(-400)
turtle.pendown()
turtle.pensize(25)
turtle.setheading(-40)
colors = ['red', 'yellow', 'orange', 'purple', 'brown', 'navy', 'olive']
for color in colors:
    print(color)
    turtle.pencolor(color)
    turtle.circle(40, 80)
    turtle.circle(-40, 80)
turtle.circle(40, 80/2)
turtle.forward(40)
turtle.circle(16, 180)
turtle.forward(40 * 2/3)
turtle.done()

进一步拓展

  • Python蟒蛇绘制问题是各类图像绘制问题的代表
  • 圆形绘制、五角星绘制、国旗绘制、机器猫绘制…
  • 掌握绘制一条线的方法,就可以绘制整个世界

绘图案例

小猪佩奇

image.png

#!/usr/bin/env python
# encoding: utf-8

import turtle as t

def nose(x,y):#鼻子
    t.pu()
    t.goto(x,y)
    t.pd()
    t.seth(-30) # 笔的角度为-30°
    t.begin_fill()
    a = 0.4
    for i in range(120):
        if 0<=i<30 or 60<=i<90:
            a=a+0.08
            t.lt(3) #向左转3度
            t.fd(a) #向前走a的步长
        else:
            a=a-0.08
            t.lt(3)
            t.fd(a)
        pass
    t.end_fill()    # 依据轮廓填充
    t.pu()
    t.seth(90)      # 笔的角度为90度
    t.fd(25)        # 向前移动25
    t.seth(0)       # 转换画笔的角度为0
    t.fd(10)
    t.pd()
    t.pencolor(255,155,192) # 设置画笔颜色
    t.seth(10)
    t.begin_fill()
    t.circle(5)             # 画一个半径为5的圆
    t.color(160,82,45)      # 设置画笔和填充颜色
    t.end_fill()
    t.pu()
    t.seth(0)
    t.fd(20)
    t.pd()
    t.pencolor(255,155,192)
    t.seth(10)
    t.begin_fill()
    t.circle(5)
    t.color(160,82,45)
    t.end_fill()
    pass

def head(x,y):  #头
    t.color((255,155,192),"pink")
    t.pu()
    t.goto(x,y)
    t.seth(0)
    t.pd()
    t.begin_fill()
    t.seth(180)
    t.circle(300,-30)   # 顺时针画一个半径为300,圆心角为30°的园
    t.circle(100,-60)
    t.circle(80,-100)
    t.circle(150,-20)
    t.circle(60,-95)
    t.seth(161)
    t.circle(-300,15)
    t.pu()
    t.goto(-100,100)
    t.pd()
    t.seth(-30)
    a=0.4
    for i in range(60):
        if 0<=i<30 or 60<=i<90:
            a=a+0.08
            t.lt(3) #向左转3度
            t.fd(a) #向前走a的步长
        else:
            a=a-0.08
            t.lt(3)
            t.fd(a)
            t.end_fill()
        pass
    pass

def ears(x,y): #耳朵
    t.color((255,155,192),"pink")
    t.pu()
    t.goto(x,y)
    t.pd()
    t.begin_fill()
    t.seth(100)
    t.circle(-50,50)
    t.circle(-10,120)
    t.circle(-50,54)
    t.end_fill()
    t.pu()
    t.seth(90)
    t.fd(-12)
    t.seth(0)
    t.fd(30)
    t.pd()
    t.begin_fill()
    t.seth(100)
    t.circle(-50,50)
    t.circle(-10,120)
    t.circle(-50,56)
    t.end_fill()
    pass

def eyes(x,y):  #眼睛
    t.color((255,155,192),"white")
    t.pu()
    t.seth(90)
    t.fd(-20)
    t.seth(0)
    t.fd(-95)
    t.pd()
    t.begin_fill()
    t.circle(15)
    t.end_fill()
    t.color("black")
    t.pu()
    t.seth(90)
    t.fd(12)
    t.seth(0)
    t.fd(-3)
    t.pd()
    t.begin_fill()
    t.circle(3)
    t.end_fill()
    t.color((255,155,192),"white")
    t.pu()
    t.seth(90)
    t.fd(-25)
    t.seth(0)
    t.fd(40)
    t.pd()
    t.begin_fill()
    t.circle(15)
    t.end_fill()
    t.color("black")
    t.pu()
    t.seth(90)
    t.fd(12)
    t.seth(0)
    t.fd(-3)
    t.pd()
    t.begin_fill()
    t.circle(3)
    t.end_fill()
    pass

def cheek(x,y): #腮
    t.color((255,155,192))
    t.pu()
    t.goto(x,y)
    t.pd()
    t.seth(0)
    t.begin_fill()
    t.circle(30)
    t.end_fill()
    pass

def mouth(x,y): #嘴
    t.color(239,69,19)
    t.pu()
    t.goto(x,y)
    t. pd()
    t.seth(-80)
    t.circle(30,40)
    t.circle(40,80)
    pass

def body(x,y):  #身体
    t.color("red",(255,99,71))
    t.pu()
    t.goto(x,y)
    t.pd()
    t.begin_fill()
    t.seth(-130)
    t.circle(100,10)
    t.circle(300,30)
    t.seth(0)
    t.fd(230)
    t.seth(90)
    t.circle(300,30)
    t.circle(100,3)
    t.color((255,155,192),(255,100,100))
    t.seth(-135)
    t.circle(-80,63)
    t.circle(-150,24)
    t.end_fill()
    pass

def hands(x,y): #手
    t.color((255,155,192))
    t.pu()
    t.goto(x,y)
    t.pd()
    t.seth(-160)
    t.circle(300,15)
    t.pu()
    t.seth(90)
    t.fd(15)
    t.seth(0)
    t.fd(0)
    t.pd()
    t.seth(-10)
    t.circle(-20,90)
    t.pu()
    t.seth(90)
    t.fd(30)
    t.seth(0)
    t.fd(237)
    t.pd()
    t.seth(-20)
    t.circle(-300,15)
    t.pu()
    t.seth(90)
    t.fd(20)
    t.seth(0)
    t.fd(0)
    t.pd()
    t.seth(-170)
    t.circle(20,90)
    pass

def foot(x,y):  #脚
    t.pensize(10)
    t.color((240,128,128))
    t.pu()
    t.goto(x,y)
    t.pd()
    t.seth(-90)
    t.fd(40)
    t.seth(-180)
    t.color("black")
    t.pensize(15)
    t.fd(20)
    t.pensize(10)
    t.color((240,128,128))
    t.pu()
    t.seth(90)
    t.fd(40)
    t.seth(0)
    t.fd(90)
    t.pd()
    t.seth(-90)
    t.fd(40)
    t.seth(-180)
    t.color("black")
    t.pensize(15)
    t.fd(20)
    pass

def tail(x,y):  #尾巴
    t.pensize(4)
    t.color((255,155,192))
    t.pu()
    t.goto(x,y)
    t.pd()
    t.seth(0)
    t.circle(70,20)
    t.circle(10,330)
    t.circle(70,30)

def setting():  #参数设置
    t.pensize(4)        # 设置画笔的大小
    t.hideturtle()
    t.colormode(255)    # 设置GBK颜色范围为0-255
    t.color((255,155,192),"pink")   # 设置画笔颜色和填充颜色(pink)
    t.setup(840,500)    # 设置主窗口的大小为840*500
    t.speed(100)        # 设置画笔速度
    pass

if __name__ == '__main__':
    setting()       #画布、画笔设置
    nose(-100,100)  #鼻子
    head(-69,167)   #头
    ears(0,160)     #耳朵
    eyes(0,140)     #眼睛
    cheek(80,10)    #腮
    mouth(-20,30)   #嘴
    body(-32,-8)    #身体
    hands(-56,-45)  #手
    foot(2,-177)    #脚
    tail(148,-155)  #尾巴
    t.done()        #结束

太阳花

image.png

import turtle as t
import time
t.color("red", "yellow")
t.speed(10)
t.begin_fill()
for _ in range(50):
    t.forward(200)
    t.left(170)
t.end_fill()
t.hideturtle()
t.done()

树1

image.png

from turtle import *
from random import *
from math import *

def tree(n, l):
    pd()
    t = cos(radians(heading() + 45)) / 18 + 0.25
    pencolor(t, t, t)
    pensize(n / 4)
    forward(l)
    if n > 0:
        b = random() * 15 + 10
        c = random() * 15 + 10
        d = l *(random() * 0.35 + 0.6)
        right(b)
        tree(n - 1, d)
        left(b + c)
        tree(n - 1, d)
        right(c)
    else:
        right(90)
        n = cos(radians(heading() - 45)) / 4 + 0.5
        pencolor(n, n, n)
        circle(2)
        left(90)
    pu()
    backward(l)
    pass

def drawTree():
    bgcolor(0.5, 0.5, 0.5)
    ht()
    speed(10)
    tracer(1000, 0)
    left(90)
    pu()
    backward(300)
    tree(13, 100)
    done()
    pass

if __name__ == "__main__":
    drawTree()

树2

image.png

import random
from turtle import *
from time import sleep

t = Turtle()
w = Screen()

def tree(branchLen, t):
    if branchLen > 3:
        if 8 <= branchLen <= 12:
            if random.randint(0, 2) == 0:
                t.color('snow')
            else:
                t.color('lightcoral')
            t.pensize(branchLen / 3)
        elif branchLen < 8:
            if random.randint(0, 1) == 0:
                t.color('snow')
            else:
                t.color('lightcoral')
            t.pensize(branchLen / 2)
        else:
            t.color('sienna')
            t.pensize(branchLen / 10)

        t.forward(branchLen)
        a = 1.5 * random.random()
        t.right(20*a)
        b = 1.5 * random.random()
        tree(branchLen-10*b, t)
        t.left(40*a)
        tree(branchLen-10*b, t)
        t.right(20*a)
        t.up()
        t.backward(branchLen)
        t.down()
    pass

def petal(m, t):  # 树下花瓣
    for i in range(m):
        a = 200 - 400 * random.random()
        b = 10 - 20 * random.random()
        t.up()
        t.forward(b)
        t.left(90)
        t.forward(a)
        t.down()
        t.color("lightcoral")
        t.circle(1)
        t.up()
        t.backward(a)
        t.right(90)
        t.backward(b)
    pass

def main():
    hideturtle()
    getscreen().tracer(15, 0)
    screensize(bg='wheat')
    t.left(90)
    t.up()
    t.backward(150)
    t.down()
    t.color('sienna')
    tree(60, t)
    petal(100, t)
    done()
    pass

if __name__ == "__main__":
    main()

时钟

所有的课程结束后,学员可以自己独立编写出下面的闹钟。
image.png