一、演示案例脚本列表
以下是本篇文章案例介绍列表,如果你想学习turtle绘图,请看turtle库(海龟绘图)介绍与使用
名称 | 描述 | 相关特性 |
---|---|---|
bytedesign | 复杂的传统海龟绘图模式 | tracer() , delay() , update() |
chaos | 绘制Verhulst 动态模型,演示通过计算机的运算可能会生成令人惊叹的结果 | 世界坐标系 |
clock | 绘制模拟时钟显示本机的当前时间 | 海龟作为表针,ontimer() |
colormixer | 试验 r, g, b 颜色模式 | ondrag() 当鼠标拖动 |
forest | 绘制3棵广度优先树 | 随机化 |
fractalcurves | 绘制Hilbert &Koch 曲线 | 递归 |
lindenmayer | 文化数学 (印度装饰艺术) | L -系统 |
minimal_hanoi | 汉诺塔 | 矩形海龟作为汉诺盘 (shape() ,shapesize() ) |
nim | 玩经典的“尼姆”游戏,开始时有三堆小棒,与电脑对战。 | 海龟作为小棒,事件驱动 (鼠标, 键盘) |
paint | 超极简主义绘画程序 | onclick() 当鼠标点击 |
peace | 初级技巧 | 海龟: 外观与动画 |
penrose | 非周期性地使用风筝和飞镖形状铺满平面 | stamp() 印章 |
planet_and_moon | 模拟引力系统 | 复合开关,Vec2D 类 |
rosette | 一个来自介绍海龟绘图的维基百科文章的图案 | clone() ,undo() |
round_dance | 两两相对并不断旋转舞蹈的海龟 | 复合形状,clone() ,shapesize() ,tilt() ,get_shapepoly() ,update |
sorting_animate | 动态演示不同的排序方法 | 简单对齐, 随机化 |
tree | 一棵 (图形化的) 广度优先树 (使用生成器) | clone() 克隆 |
two_canvases | 简单设计 | 两块画布上的海龟 |
yinyang | 另一个初级示例 | circle() 画圆 |
二、演示脚本案例代码
2.1 bytedesign
from time import perf_counter as clock
from turtle import Turtle, mainloop
class Designer(Turtle):
def design(self, homePos, scale):
self.up()
for i in range(5):
self.forward(64.65 * scale)
self.down()
self.wheel(self.position(), scale)
self.up()
self.backward(64.65 * scale)
self.right(72)
self.up()
self.goto(homePos)
self.right(36)
self.forward(24.5 * scale)
self.right(198)
self.down()
self.centerpiece(46 * scale, 143.4, scale)
self.getscreen().tracer(True)
def wheel(self, initpos, scale):
self.right(54)
for i in range(4):
self.pentpiece(initpos, scale)
self.down()
self.left(36)
for i in range(5):
self.tripiece(initpos, scale)
self.left(36)
for i in range(5):
self.down()
self.right(72)
self.forward(28 * scale)
self.up()
self.backward(28 * scale)
self.left(54)
self.getscreen().update()
def tripiece(self, initpos, scale):
oldh = self.heading()
self.down()
self.backward(2.5 * scale)
self.tripolyr(31.5 * scale, scale)
self.up()
self.goto(initpos)
self.setheading(oldh)
self.down()
self.backward(2.5 * scale)
self.tripolyl(31.5 * scale, scale)
self.up()
self.goto(initpos)
self.setheading(oldh)
self.left(72)
self.getscreen().update()
def pentpiece(self, initpos, scale):
oldh = self.heading()
self.up()
self.forward(29 * scale)
self.down()
for i in range(5):
self.forward(18 * scale)
self.right(72)
self.pentr(18 * scale, 75, scale)
self.up()
self.goto(initpos)
self.setheading(oldh)
self.forward(29 * scale)
self.down()
for i in range(5):
self.forward(18 * scale)
self.right(72)
self.pentl(18 * scale, 75, scale)
self.up()
self.goto(initpos)
self.setheading(oldh)
self.left(72)
self.getscreen().update()
def pentl(self, side, ang, scale):
if side < (2 * scale): return
self.forward(side)
self.left(ang)
self.pentl(side - (.38 * scale), ang, scale)
def pentr(self, side, ang, scale):
if side < (2 * scale): return
self.forward(side)
self.right(ang)
self.pentr(side - (.38 * scale), ang, scale)
def tripolyr(self, side, scale):
if side < (4 * scale): return
self.forward(side)
self.right(111)
self.forward(side / 1.78)
self.right(111)
self.forward(side / 1.3)
self.right(146)
self.tripolyr(side * .75, scale)
def tripolyl(self, side, scale):
if side < (4 * scale): return
self.forward(side)
self.left(111)
self.forward(side / 1.78)
self.left(111)
self.forward(side / 1.3)
self.left(146)
self.tripolyl(side * .75, scale)
def centerpiece(self, s, a, scale):
self.forward(s)
self.left(a)
if s < (7.5 * scale):
return
self.centerpiece(s - (1.2 * scale), a, scale)
def main():
t = Designer()
t.speed(0)
t.hideturtle()
t.getscreen().delay(0)
t.getscreen().tracer(0)
at = clock()
t.design(t.position(), 2)
et = clock()
return "runtime: %.2f sec." % (et - at)
if __name__ == '__main__':
msg = main()
print(msg)
mainloop()
2.2 chaos
from turtle import *
N = 80
def f(x):
return 3.9 * x * (1 - x)
def g(x):
return 3.9 * (x - x ** 2)
def h(x):
return 3.9 * x - 3.9 * x * x
def jumpto(x, y):
penup();
goto(x, y)
def line(x1, y1, x2, y2):
jumpto(x1, y1)
pendown()
goto(x2, y2)
def coosys():
line(-1, 0, N + 1, 0)
line(0, -0.1, 0, 1.1)
def plot(fun, start, color):
pencolor(color)
x = start
jumpto(0, x)
pendown()
dot(5)
for i in range(N):
x = fun(x)
goto(i + 1, x)
dot(5)
def main():
reset()
setworldcoordinates(-1.0, -0.1, N + 1, 1.1)
speed(0)
hideturtle()
coosys()
plot(f, 0.35, "blue")
plot(g, 0.35, "green")
plot(h, 0.35, "red")
# Now zoom in:
for s in range(100):
setworldcoordinates(0.5 * s, -0.1, N + 1, 1.1)
return "Done!"
if __name__ == "__main__":
main()
mainloop()
2.3 clock
from datetime import datetime
from turtle import *
def jump(distanz, winkel=0):
penup()
right(winkel)
forward(distanz)
left(winkel)
pendown()
def hand(laenge, spitze):
fd(laenge * 1.15)
rt(90)
fd(spitze / 2.0)
lt(120)
fd(spitze)
lt(120)
fd(spitze)
lt(120)
fd(spitze / 2.0)
def make_hand_shape(name, laenge, spitze):
reset()
jump(-laenge * 0.15)
begin_poly()
hand(laenge, spitze)
end_poly()
hand_form = get_poly()
register_shape(name, hand_form)
def clockface(radius):
reset()
pensize(7)
for i in range(60):
jump(radius)
if i % 5 == 0:
fd(25)
jump(-radius - 25)
else:
dot(3)
jump(-radius)
rt(6)
def setup():
global second_hand, minute_hand, hour_hand, writer
mode("logo")
make_hand_shape("second_hand", 125, 25)
make_hand_shape("minute_hand", 130, 25)
make_hand_shape("hour_hand", 90, 25)
clockface(160)
second_hand = Turtle()
second_hand.shape("second_hand")
second_hand.color("gray20", "gray80")
minute_hand = Turtle()
minute_hand.shape("minute_hand")
minute_hand.color("blue1", "red1")
hour_hand = Turtle()
hour_hand.shape("hour_hand")
hour_hand.color("blue3", "red3")
for hand in second_hand, minute_hand, hour_hand:
hand.resizemode("user")
hand.shapesize(1, 1, 3)
hand.speed(0)
ht()
writer = Turtle()
# writer.mode("logo")
writer.ht()
writer.pu()
writer.bk(85)
def wochentag(t):
wochentag = ["星期一", "星期二", "星期三",
"星期四", "星期五", "星期六", "星期日"]
return wochentag[t.weekday()]
def datum(z):
monat = ["一月", "二月", "三月", "四月", "五月", "六月",
"七月", "八月", "九月", "十月", "十一月", "十二月"]
j = z.year
m = monat[z.month - 1]
t = z.day
return "%d年 %s %d日" % (j, m, t)
def tick():
t = datetime.today()
sekunde = t.second + t.microsecond * 0.000001
minute = t.minute + sekunde / 60.0
stunde = t.hour + minute / 60.0
try:
tracer(False)
writer.clear()
writer.home()
writer.forward(65)
writer.write(wochentag(t),
align="center", font=("Courier", 14, "bold"))
writer.back(150)
writer.write(datum(t),
align="center", font=("Courier", 14, "bold"))
writer.forward(85)
second_hand.setheading(6 * sekunde)
minute_hand.setheading(6 * minute)
hour_hand.setheading(30 * stunde)
tracer(True)
ontimer(tick, 100)
except Terminator:
pass
def main():
tracer(False)
setup()
tracer(True)
tick()
return "EVENTLOOP"
if __name__ == "__main__":
mode("logo")
msg = main()
print(msg)
mainloop()
2.4 colormixer
运行后使用鼠标拖拉海龟可改变窗口背景颜色。
from turtle import Screen, Turtle, mainloop
class ColorTurtle(Turtle):
def __init__(self, x, y):
Turtle.__init__(self)
self.shape("turtle")
self.resizemode("user")
self.shapesize(3, 3, 5)
self.pensize(10)
self._color = [0, 0, 0]
self.x = x
self._color[x] = y
self.color(self._color)
self.speed(0)
self.left(90)
self.pu()
self.goto(x, 0)
self.pd()
self.sety(1)
self.pu()
self.sety(y)
self.pencolor("gray25")
self.ondrag(self.shift)
def shift(self, x, y):
self.sety(max(0, min(y, 1)))
self._color[self.x] = self.ycor()
self.fillcolor(self._color)
setbgcolor()
def setbgcolor():
screen.bgcolor(red.ycor(), green.ycor(), blue.ycor())
def main():
global screen, red, green, blue
screen = Screen()
screen.delay(0)
screen.setworldcoordinates(-1, -0.3, 3, 1.3)
red = ColorTurtle(0, .5)
green = ColorTurtle(1, .5)
blue = ColorTurtle(2, .5)
setbgcolor()
writer = Turtle()
writer.ht()
writer.pu()
writer.goto(1, 1.15)
writer.write("拖拉海龟!", align="center", font=("Arial", 30, ("bold", "italic")))
return "EVENTLOOP"
if __name__ == "__main__":
msg = main()
print(msg)
mainloop()
2.5 forest
from random import randrange
from time import perf_counter as clock
from turtle import Turtle, colormode, tracer, mainloop
def symRandom(n):
return randrange(-n, n + 1)
def randomize(branchlist, angledist, sizedist):
return [(angle + symRandom(angledist),
sizefactor * 1.01 ** symRandom(sizedist))
for angle, sizefactor in branchlist]
def randomfd(t, distance, parts, angledist):
for i in range(parts):
t.left(symRandom(angledist))
t.forward((1.0 * distance) / parts)
def tree(tlist, size, level, widthfactor, branchlists, angledist=10, sizedist=5):
if level > 0:
lst = []
brs = []
for t, branchlist in list(zip(tlist, branchlists)):
t.pensize(size * widthfactor)
t.pencolor(255 - (180 - 11 * level + symRandom(15)),
180 - 11 * level + symRandom(15),
0)
t.pendown()
randomfd(t, size, level, angledist)
yield 1
for angle, sizefactor in branchlist:
t.left(angle)
lst.append(t.clone())
brs.append(randomize(branchlist, angledist, sizedist))
t.right(angle)
for x in tree(lst, size * sizefactor, level - 1, widthfactor, brs,
angledist, sizedist):
yield None
def start(t, x, y):
colormode(255)
t.reset()
t.speed(0)
t.hideturtle()
t.left(90)
t.penup()
t.setpos(x, y)
t.pendown()
def doit1(level, pen):
pen.hideturtle()
start(pen, 20, -208)
t = tree([pen], 80, level, 0.1, [[(45, 0.69), (0, 0.65), (-45, 0.71)]])
return t
def doit2(level, pen):
pen.hideturtle()
start(pen, -135, -130)
t = tree([pen], 120, level, 0.1, [[(45, 0.69), (-45, 0.71)]])
return t
def doit3(level, pen):
pen.hideturtle()
start(pen, 190, -90)
t = tree([pen], 100, level, 0.1, [[(45, 0.7), (0, 0.72), (-45, 0.65)]])
return t
# 这里有 3 个树生成器:
def main():
p = Turtle()
p.ht()
tracer(75, 0)
u = doit1(6, Turtle(undobuffersize=1))
s = doit2(7, Turtle(undobuffersize=1))
t = doit3(5, Turtle(undobuffersize=1))
a = clock()
while True:
done = 0
for b in u, s, t:
try:
b.__next__()
except:
done += 1
if done == 3:
break
tracer(1, 10)
b = clock()
return "runtime: %.2f sec." % (b - a)
if __name__ == '__main__':
main()
mainloop()
2.6 fractalcurves
from time import sleep, perf_counter as clock
from turtle import *
class CurvesTurtle(Pen):
def hilbert(self, size, level, parity):
if level == 0:
return
# 旋转并绘制与大曲线奇偶校验相反的第一条子曲线
self.left(parity * 90)
self.hilbert(size, level - 1, -parity)
# 绘制与大曲线相同的第二条子曲线的接口
self.forward(size)
self.right(parity * 90)
self.hilbert(size, level - 1, parity)
# 第三条子曲线
self.forward(size)
self.hilbert(size, level - 1, parity)
# 第四条子曲线
self.right(parity * 90)
self.forward(size)
self.hilbert(size, level - 1, -parity)
# 需要最后一圈才能使最终从大正方形面向外
self.left(parity * 90)
def fractalgon(self, n, rad, lev, dir):
import math
# 如果 dir = 1 向外转
# 如果 dir = -1 向内转
edge = 2 * rad * math.sin(math.pi / n)
self.pu()
self.fd(rad)
self.pd()
self.rt(180 - (90 * (n - 2) / n))
for i in range(n):
self.fractal(edge, lev, dir)
self.rt(360 / n)
self.lt(180 - (90 * (n - 2) / n))
self.pu()
self.bk(rad)
self.pd()
def fractal(self, dist, depth, dir):
if depth < 1:
self.fd(dist)
return
self.fractal(dist / 3, depth - 1, dir)
self.lt(60 * dir)
self.fractal(dist / 3, depth - 1, dir)
self.rt(120 * dir)
self.fractal(dist / 3, depth - 1, dir)
self.lt(60 * dir)
self.fractal(dist / 3, depth - 1, dir)
def main():
ft = CurvesTurtle()
ft.reset()
ft.speed(0)
ft.ht()
ft.getscreen().tracer(1, 0)
ft.pu()
size = 6
ft.setpos(-33 * size, -32 * size)
ft.pd()
ta = clock()
ft.fillcolor("red")
ft.begin_fill()
ft.fd(size)
ft.hilbert(size, 6, 1)
# 框架
ft.fd(size)
for i in range(3):
ft.lt(90)
ft.fd(size * (64 + i % 2))
ft.pu()
for i in range(2):
ft.fd(size)
ft.rt(90)
ft.pd()
for i in range(4):
ft.fd(size * (66 + i % 2))
ft.rt(90)
ft.end_fill()
tb = clock()
res = "Hilbert: %.2fsec. " % (tb - ta)
sleep(1)
ft.reset()
ft.speed(0)
ft.ht()
ft.getscreen().tracer(1, 0)
ta = clock()
ft.color("black", "blue")
ft.begin_fill()
ft.fractalgon(3, 250, 4, 1)
ft.end_fill()
ft.begin_fill()
ft.color("red")
ft.fractalgon(3, 200, 4, -1)
ft.end_fill()
tb = clock()
res += "Koch: %.2fsec." % (tb - ta)
return res
if __name__ == '__main__':
msg = main()
print(msg)
mainloop()
2.7 lindenmayer
from turtle import *
def replace(seq, replacementRules, n):
for i in range(n):
newseq = ""
for element in seq:
newseq = newseq + replacementRules.get(element, element)
seq = newseq
return seq
def draw(commands, rules):
for b in commands:
try:
rules[b]()
except TypeError:
try:
draw(rules[b], rules)
except:
pass
def main():
def r():
right(45)
def l():
left(45)
def f():
forward(7.5)
snake_rules = {"-": r, "+": l, "f": f, "b": "f+f+f--f--f+f+f"}
snake_replacementRules = {"b": "b+f+b--f--b+f+b"}
snake_start = "b--f--b--f"
drawing = replace(snake_start, snake_replacementRules, 3)
reset()
speed(3)
tracer(1, 0)
ht()
up()
backward(195)
down()
draw(drawing, snake_rules)
from time import sleep
sleep(3)
def A():
color("red")
circle(10, 90)
def B():
from math import sqrt
color("black")
l = 5 / sqrt(2)
forward(l)
circle(l, 270)
forward(l)
def F():
color("green")
forward(10)
krishna_rules = {"a": A, "b": B, "f": F}
krishna_replacementRules = {"a": "afbfa", "b": "afbfbfbfa"}
krishna_start = "fbfbfbfb"
reset()
speed(0)
tracer(3, 0)
ht()
left(45)
drawing = replace(krishna_start, krishna_replacementRules, 3)
draw(drawing, krishna_rules)
tracer(1)
return "Done!"
if __name__ == '__main__':
msg = main()
print(msg)
mainloop()
2.8 minimal_hanoi
from turtle import *
class Disc(Turtle):
def __init__(self, n):
Turtle.__init__(self, shape="square", visible=False)
self.pu()
self.shapesize(1.5, n * 1.5, 2) # 正方形-->矩形
self.fillcolor(n / 6., 0, 1 - n / 6.)
self.st()
class Tower(list):
# 河内塔,内置类型列表的子类
def __init__(self, x):
# 创建一个空塔。x 是 PEG 的 x 位置
self.x = x
def push(self, d):
d.setx(self.x)
d.sety(-150 + 34 * len(self))
self.append(d)
def pop(self):
d = list.pop(self)
d.sety(150)
return d
def hanoi(n, from_, with_, to_):
if n > 0:
hanoi(n - 1, from_, to_, with_)
to_.push(from_.pop())
hanoi(n - 1, with_, from_, to_)
def play():
onkey(None, "space")
clear()
try:
hanoi(6, t1, t2, t3)
write("结束!",
align="center", font=("Courier", 16, "bold"))
except Terminator:
pass
def main():
global t1, t2, t3
ht();
penup();
goto(0, -225) # 作家
t1 = Tower(-250)
t2 = Tower(0)
t3 = Tower(250)
# 制作 6 个圆盘塔
for i in range(6, 0, -1):
t1.push(Disc(i))
# 准备用户界面
write("按空格键开始游戏",
align="center", font=("Courier", 16, "bold"))
onkey(play, "space")
listen()
return "EVENTLOOP"
if __name__ == "__main__":
msg = main()
print(msg)
mainloop()
2.9 nim
import random
import time
import turtle
SCREENWIDTH = 640
SCREENHEIGHT = 480
MINSTICKS = 7
MAXSTICKS = 31
HUNIT = SCREENHEIGHT // 12
WUNIT = SCREENWIDTH // ((MAXSTICKS // 5) * 11 + (MAXSTICKS % 5) * 2)
SCOLOR = (63, 63, 31)
HCOLOR = (255, 204, 204)
COLOR = (204, 204, 255)
def randomrow():
return random.randint(MINSTICKS, MAXSTICKS)
def computerzug(state):
xored = state[0] ^ state[1] ^ state[2]
if xored == 0:
return randommove(state)
for z in range(3):
s = state[z] ^ xored
if s <= state[z]:
move = (z, s)
return move
def randommove(state):
m = max(state)
while True:
z = random.randint(0, 2)
if state[z] > (m > 1):
break
rand = random.randint(m > 1, state[z] - 1)
return z, rand
class NimModel(object):
def __init__(self, game):
self.game = game
def setup(self):
if self.game.state not in [Nim.CREATED, Nim.OVER]:
return
self.sticks = [randomrow(), randomrow(), randomrow()]
self.player = 0
self.winner = None
self.game.view.setup()
self.game.state = Nim.RUNNING
def move(self, row, col):
maxspalte = self.sticks[row]
self.sticks[row] = col
self.game.view.notify_move(row, col, maxspalte, self.player)
if self.game_over():
self.game.state = Nim.OVER
self.winner = self.player
self.game.view.notify_over()
elif self.player == 0:
self.player = 1
row, col = computerzug(self.sticks)
self.move(row, col)
self.player = 0
def game_over(self):
return self.sticks == [0, 0, 0]
def notify_move(self, row, col):
if self.sticks[row] <= col:
return
self.move(row, col)
class Stick(turtle.Turtle):
def __init__(self, row, col, game):
turtle.Turtle.__init__(self, visible=False)
self.row = row
self.col = col
self.game = game
x, y = self.coords(row, col)
self.shape("square")
self.shapesize(HUNIT / 10.0, WUNIT / 20.0)
self.speed(0)
self.pu()
self.goto(x, y)
self.color("white")
self.showturtle()
def coords(self, row, col):
packet, remainder = divmod(col, 5)
x = (3 + 11 * packet + 2 * remainder) * WUNIT
y = (2 + 3 * row) * HUNIT
return x - SCREENWIDTH // 2 + WUNIT // 2, SCREENHEIGHT // 2 - y - HUNIT // 2
def makemove(self, x, y):
if self.game.state != Nim.RUNNING:
return
self.game.controller.notify_move(self.row, self.col)
class NimView(object):
def __init__(self, game):
self.game = game
self.screen = game.screen
self.model = game.model
self.screen.colormode(255)
self.screen.tracer(False)
self.screen.bgcolor((240, 240, 255))
self.writer = turtle.Turtle(visible=False)
self.writer.pu()
self.writer.speed(0)
self.sticks = {}
for row in range(3):
for col in range(MAXSTICKS):
self.sticks[(row, col)] = Stick(row, col, game)
self.display("... 请稍等片刻 ...")
self.screen.tracer(True)
def display(self, msg1, msg2=None):
self.screen.tracer(False)
self.writer.clear()
if msg2 is not None:
self.writer.goto(0, - SCREENHEIGHT // 2 + 48)
self.writer.pencolor("red")
self.writer.write(msg2, align="center", font=("Courier", 18, "bold"))
self.writer.goto(0, - SCREENHEIGHT // 2 + 20)
self.writer.pencolor("black")
self.writer.write(msg1, align="center", font=("Courier", 14, "bold"))
self.screen.tracer(True)
def setup(self):
self.screen.tracer(False)
for row in range(3):
for col in range(self.model.sticks[row]):
self.sticks[(row, col)].color(SCOLOR)
for row in range(3):
for col in range(self.model.sticks[row], MAXSTICKS):
self.sticks[(row, col)].color("white")
self.display("轮到你了!点击最左边的摇杆删除。")
self.screen.tracer(True)
def notify_move(self, row, col, maxspalte, player):
if player == 0:
farbe = HCOLOR
for s in range(col, maxspalte):
self.sticks[(row, s)].color(farbe)
else:
self.display(" ... 思考 ... ")
time.sleep(0.5)
self.display(" ... 思考 ... aaah ...")
farbe = COLOR
for s in range(maxspalte - 1, col - 1, -1):
time.sleep(0.2)
self.sticks[(row, s)].color(farbe)
self.display("轮到你了!点击最左边的摇杆删除。")
def notify_over(self):
if self.game.model.winner == 0:
msg2 = "恭喜。你是赢家!!!"
else:
msg2 = "对不起,电脑是赢家。"
self.display("要再次游戏,请按空格键。要离开,请按 ESC 键。", msg2)
def clear(self):
if self.game.state == Nim.OVER:
self.screen.clear()
class NimController(object):
def __init__(self, game):
self.game = game
self.sticks = game.view.sticks
self.BUSY = False
for stick in self.sticks.values():
stick.onclick(stick.makemove)
self.game.screen.onkey(self.game.model.setup, "space")
self.game.screen.onkey(self.game.view.clear, "Escape")
self.game.view.display("按空格键开始游戏")
self.game.screen.listen()
def notify_move(self, row, col):
if self.BUSY:
return
self.BUSY = True
self.game.model.notify_move(row, col)
self.BUSY = False
class Nim(object):
CREATED = 0
RUNNING = 1
OVER = 2
def __init__(self, screen):
self.state = Nim.CREATED
self.screen = screen
self.model = NimModel(self)
self.view = NimView(self)
self.controller = NimController(self)
def main():
mainscreen = turtle.Screen()
mainscreen.mode("standard")
mainscreen.setup(SCREENWIDTH, SCREENHEIGHT)
nim = Nim(mainscreen)
return "EVENTLOOP"
if __name__ == "__main__":
main()
turtle.mainloop()
2.10 paint
from turtle import *
def switchupdown(x=0, y=0):
if pen()["pendown"]:
end_fill()
up()
else:
down()
begin_fill()
def changecolor(x=0, y=0):
global colors
colors = colors[1:] + colors[:1]
color(colors[0])
def main():
global colors
shape("circle")
resizemode("user")
shapesize(.5)
width(3)
colors = ["red", "green", "blue", "yellow"]
color(colors[0])
switchupdown()
onscreenclick(goto, 1)
onscreenclick(changecolor, 2)
onscreenclick(switchupdown, 3)
return "EVENTLOOP"
if __name__ == "__main__":
msg = main()
print(msg)
mainloop()
2.11 peace
from turtle import *
def main():
peacecolors = ("red3", "orange", "yellow",
"seagreen4", "orchid4",
"royalblue1", "dodgerblue4")
reset()
Screen()
up()
goto(-320, -195)
width(70)
for pcolor in peacecolors:
color(pcolor)
down()
forward(640)
up()
backward(640)
left(90)
forward(66)
right(90)
width(25)
color("white")
goto(0, -170)
down()
circle(170)
left(90)
forward(340)
up()
left(180)
forward(170)
right(45)
down()
forward(170)
up()
backward(170)
left(90)
down()
forward(170)
up()
goto(0, 300)
return "Done!"
if __name__ == "__main__":
main()
mainloop()
2.12 penrose
from math import cos, pi
from time import perf_counter as clock, sleep
from turtle import *
f = (5 ** 0.5 - 1) / 2.0 # (sqrt(5)-1)/2 -- 黄金比例
d = 2 * cos(3 * pi / 10)
def kite(l):
fl = f * l
lt(36)
fd(l)
rt(108)
fd(fl)
rt(36)
fd(fl)
rt(108)
fd(l)
rt(144)
def dart(l):
fl = f * l
lt(36)
fd(l)
rt(144)
fd(fl)
lt(36)
fd(fl)
rt(144)
fd(l)
rt(144)
def inflatekite(l, n):
if n == 0:
px, py = pos()
h, x, y = int(heading()), round(px, 3), round(py, 3)
tiledict[(h, x, y)] = True
return
fl = f * l
lt(36)
inflatedart(fl, n - 1)
fd(l)
rt(144)
inflatekite(fl, n - 1)
lt(18)
fd(l * d)
rt(162)
inflatekite(fl, n - 1)
lt(36)
fd(l)
rt(180)
inflatedart(fl, n - 1)
lt(36)
def inflatedart(l, n):
if n == 0:
px, py = pos()
h, x, y = int(heading()), round(px, 3), round(py, 3)
tiledict[(h, x, y)] = False
return
fl = f * l
inflatekite(fl, n - 1)
lt(36)
fd(l)
rt(180)
inflatedart(fl, n - 1)
lt(54)
fd(l * d)
rt(126)
inflatedart(fl, n - 1)
fd(l)
rt(144)
def draw(l, n, th=2):
clear()
l = l * f ** n
shapesize(l / 100.0, l / 100.0, th)
for k in tiledict:
h, x, y = k
setpos(x, y)
setheading(h)
if tiledict[k]:
shape("kite")
color("black", (0, 0.75, 0))
else:
shape("dart")
color("black", (0.75, 0, 0))
stamp()
def sun(l, n):
for i in range(5):
inflatekite(l, n)
lt(72)
def star(l, n):
for i in range(5):
inflatedart(l, n)
lt(72)
def makeshapes():
tracer(0)
begin_poly()
kite(100)
end_poly()
register_shape("kite", get_poly())
begin_poly()
dart(100)
end_poly()
register_shape("dart", get_poly())
tracer(1)
def start():
reset()
ht()
pu()
makeshapes()
resizemode("user")
def test(l=200, n=4, fun=sun, startpos=(0, 0), th=2):
global tiledict
goto(startpos)
setheading(0)
tiledict = {}
tracer(0)
fun(l, n)
draw(l, n, th)
tracer(1)
nk = len([x for x in tiledict if tiledict[x]])
nd = len([x for x in tiledict if not tiledict[x]])
print("%d kites and %d darts = %d pieces." % (nk, nd, nk + nd))
def demo(fun=sun):
start()
for i in range(8):
a = clock()
test(300, i, fun)
b = clock()
t = b - a
if t < 2:
sleep(2 - t)
def main():
mode("logo")
bgcolor(0.3, 0.3, 0)
demo(sun)
sleep(2)
demo(star)
pencolor("black")
goto(0, -200)
pencolor(0.7, 0.7, 1)
write("请稍等...",
align="center", font=('Arial Black', 36, 'bold'))
test(600, 8, startpos=(70, 117))
return "Done"
if __name__ == "__main__":
msg = main()
mainloop()
2.13 planet_and_moon
from turtle import Shape, Turtle, mainloop, Vec2D as Vec
G = 8
class GravSys(object):
def __init__(self):
self.planets = []
self.t = 0
self.dt = 0.01
def init(self):
for p in self.planets:
p.init()
def start(self):
for i in range(10000):
self.t += self.dt
for p in self.planets:
p.step()
class Star(Turtle):
def __init__(self, m, x, v, gravSys, shape):
Turtle.__init__(self, shape=shape)
self.penup()
self.m = m
self.setpos(x)
self.v = v
gravSys.planets.append(self)
self.gravSys = gravSys
self.resizemode("user")
self.pendown()
def init(self):
dt = self.gravSys.dt
self.a = self.acc()
self.v = self.v + 0.5 * dt * self.a
def acc(self):
a = Vec(0, 0)
for planet in self.gravSys.planets:
if planet != self:
v = planet.pos() - self.pos()
a += (G * planet.m / abs(v) ** 3) * v
return a
def step(self):
dt = self.gravSys.dt
self.setpos(self.pos() + dt * self.v)
if self.gravSys.planets.index(self) != 0:
self.setheading(self.towards(self.gravSys.planets[0]))
self.a = self.acc()
self.v = self.v + dt * self.a
# 为行星创建复合黄色/蓝色形状
def main():
s = Turtle()
s.reset()
s.getscreen().tracer(0, 0)
s.ht()
s.pu()
s.fd(6)
s.lt(90)
s.begin_poly()
s.circle(6, 180)
s.end_poly()
m1 = s.get_poly()
s.begin_poly()
s.circle(6, 180)
s.end_poly()
m2 = s.get_poly()
planetshape = Shape("compound")
planetshape.addcomponent(m1, "orange")
planetshape.addcomponent(m2, "blue")
s.getscreen().register_shape("planet", planetshape)
s.getscreen().tracer(1, 0)
# 设置重力系统
gs = GravSys()
sun = Star(1000000, Vec(0, 0), Vec(0, -2.5), gs, "circle")
sun.color("yellow")
sun.shapesize(1.8)
sun.pu()
earth = Star(12500, Vec(210, 0), Vec(0, 195), gs, "planet")
earth.pencolor("green")
earth.shapesize(0.8)
moon = Star(1, Vec(220, 0), Vec(0, 295), gs, "planet")
moon.pencolor("blue")
moon.shapesize(0.5)
gs.init()
gs.start()
return "Done!"
if __name__ == '__main__':
main()
mainloop()
2.14 rosette
from time import perf_counter as clock, sleep
from turtle import Screen, Turtle, mainloop
def mn_eck(p, ne, sz):
turtlelist = [p]
# 创建 NE-1 附加海龟
for i in range(1, ne):
q = p.clone()
q.rt(360.0 / ne)
turtlelist.append(q)
p = q
for i in range(ne):
c = abs(ne / 2.0 - i) / (ne * .7)
# 让那些ne海龟迈出一步
# 并行:
for t in turtlelist:
t.rt(360. / ne)
t.pencolor(1 - c, 0, c)
t.fd(sz)
def main():
s = Screen()
s.bgcolor("black")
p = Turtle()
p.speed(0)
p.hideturtle()
p.pencolor("red")
p.pensize(3)
s.tracer(36, 0)
at = clock()
mn_eck(p, 36, 19)
et = clock()
z1 = et - at
sleep(1)
at = clock()
while any(t.undobufferentries() for t in s.turtles()):
for t in s.turtles():
t.undo()
et = clock()
return "runtime: %.3f sec" % (z1 + et - at)
if __name__ == '__main__':
msg = main()
print(msg)
mainloop()
2.15 round_dance
执行后按任意键停止动画。
from turtle import *
def stop():
global running
running = False
def main():
global running
clearscreen()
bgcolor("gray10")
tracer(False)
shape("triangle")
f = 0.793402
phi = 9.064678
s = 5
c = 1
# 创建复合形状
sh = Shape("compound")
for i in range(10):
shapesize(s)
p = get_shapepoly()
s *= f
c *= f
tilt(-phi)
sh.addcomponent(p, (c, 0.25, 1 - c), "black")
register_shape("multitri", sh)
# 创建舞者
shapesize(1)
shape("multitri")
pu()
setpos(0, -200)
dancers = []
for i in range(180):
fd(7)
tilt(-4)
lt(2)
update()
if i % 12 == 0:
dancers.append(clone())
home()
# 舞动
running = True
onkeypress(stop)
listen()
cs = 1
while running:
ta = -4
for dancer in dancers:
dancer.fd(7)
dancer.lt(2)
dancer.tilt(ta)
ta = -4 if ta > 0 else 2
if cs < 180:
right(4)
shapesize(cs)
cs *= 1.005
update()
return "DONE!"
if __name__ == '__main__':
print(main())
mainloop()
2.16 sorting_animate
import random
from turtle import *
class Block(Turtle):
def __init__(self, size):
self.size = size
Turtle.__init__(self, shape="square", visible=False)
self.pu()
self.shapesize(size * 1.5, 1.5, 2) # 正方形-->矩形
self.fillcolor("black")
self.st()
def glow(self):
self.fillcolor("red")
def unglow(self):
self.fillcolor("black")
def __repr__(self):
return "Block size: {0}".format(self.size)
class Shelf(list):
def __init__(self, y):
"create a shelf. y is y-position of first block"
self.y = y
self.x = -150
def push(self, d):
width, _, _ = d.shapesize()
# 通过底部边缘对齐块
y_offset = width / 2 * 20
d.sety(self.y + y_offset)
d.setx(self.x + 34 * len(self))
self.append(d)
def _close_gap_from_i(self, i):
for b in self[i:]:
xpos, _ = b.pos()
b.setx(xpos - 34)
def _open_gap_from_i(self, i):
for b in self[i:]:
xpos, _ = b.pos()
b.setx(xpos + 34)
def pop(self, key):
b = list.pop(self, key)
b.glow()
b.sety(200)
self._close_gap_from_i(key)
return b
def insert(self, key, b):
self._open_gap_from_i(key)
list.insert(self, key, b)
b.setx(self.x + 34 * key)
width, _, _ = b.shapesize()
# 通过底部边缘对齐块
y_offset = width / 2 * 20
b.sety(self.y + y_offset)
b.unglow()
def isort(shelf):
length = len(shelf)
for i in range(1, length):
hole = i
while hole > 0 and shelf[i].size < shelf[hole - 1].size:
hole = hole - 1
shelf.insert(hole, shelf.pop(i))
return
def ssort(shelf):
length = len(shelf)
for j in range(0, length - 1):
imin = j
for i in range(j + 1, length):
if shelf[i].size < shelf[imin].size:
imin = i
if imin != j:
shelf.insert(j, shelf.pop(imin))
def partition(shelf, left, right, pivot_index):
pivot = shelf[pivot_index]
shelf.insert(right, shelf.pop(pivot_index))
store_index = left
for i in range(left, right): # 范围不包括末尾的值
if shelf[i].size < pivot.size:
shelf.insert(store_index, shelf.pop(i))
store_index = store_index + 1
shelf.insert(store_index, shelf.pop(right)) # 将枢轴移动到正确位置
return store_index
def qsort(shelf, left, right):
if left < right:
pivot_index = left
pivot_new_index = partition(shelf, left, right, pivot_index)
qsort(shelf, left, pivot_new_index - 1)
qsort(shelf, pivot_new_index + 1, right)
def randomize():
disable_keys()
clear()
target = list(range(10))
random.shuffle(target)
for i, t in enumerate(target):
for j in range(i, len(s)):
if s[j].size == t + 1:
s.insert(i, s.pop(j))
show_text(instructions1)
show_text(instructions2, line=1)
enable_keys()
def show_text(text, line=0):
line = 20 * line
goto(0, -250 - line)
write(text, align="center", font=("Courier", 16, "bold"))
def start_ssort():
disable_keys()
clear()
show_text("选择排序")
ssort(s)
clear()
show_text(instructions1)
show_text(instructions2, line=1)
enable_keys()
def start_isort():
disable_keys()
clear()
show_text("插入排序")
isort(s)
clear()
show_text(instructions1)
show_text(instructions2, line=1)
enable_keys()
def start_qsort():
disable_keys()
clear()
show_text("快速排序")
qsort(s, 0, len(s) - 1)
clear()
show_text(instructions1)
show_text(instructions2, line=1)
enable_keys()
def init_shelf():
global s
s = Shelf(-200)
vals = (4, 2, 8, 9, 1, 5, 10, 3, 7, 6)
for i in vals:
s.push(Block(i))
def disable_keys():
onkey(None, "s")
onkey(None, "i")
onkey(None, "q")
onkey(None, "r")
def enable_keys():
onkey(start_isort, "i")
onkey(start_ssort, "s")
onkey(start_qsort, "q")
onkey(randomize, "r")
onkey(bye, "space")
def main():
getscreen().clearscreen()
ht()
penup()
init_shelf()
show_text(instructions1)
show_text(instructions2, line=1)
enable_keys()
listen()
return "EVENTLOOP"
instructions1 = "按 i 进行插入排序,按 S 进行选择排序,按 Q 进行快速排序"
instructions2 = "空格键退出,R 随机化"
if __name__ == "__main__":
msg = main()
mainloop()
2.17 tree
from time import perf_counter as clock
from turtle import Turtle, mainloop
def tree(plist, l, a, f):
# plist 是笔列表 l 是分支的长度 a 是 2 个分支之间夹角的一半 f 是分支从一层缩短到另一层的系数
if l > 3:
lst = []
for p in plist:
p.forward(l)
q = p.clone()
p.left(a)
q.right(a)
lst.append(p)
lst.append(q)
for x in tree(lst, l * f, a, f):
yield None
def maketree():
p = Turtle()
p.setundobuffer(None)
p.hideturtle()
p.speed(0)
p.getscreen().tracer(30, 0)
p.left(90)
p.penup()
p.forward(-210)
p.pendown()
t = tree([p], 200, 65, 0.6375)
for x in t:
pass
def main():
a = clock()
maketree()
b = clock()
return "done: %.2f sec." % (b - a)
if __name__ == "__main__":
msg = main()
print(msg)
mainloop()
2.18 two_canvases
from turtle import TurtleScreen, RawTurtle, TK
def main():
root = TK.Tk()
cv1 = TK.Canvas(root, width=300, height=200, bg="#ddffff")
cv2 = TK.Canvas(root, width=300, height=200, bg="#ffeeee")
cv1.pack()
cv2.pack()
s1 = TurtleScreen(cv1)
s1.bgcolor(0.85, 0.85, 1)
s2 = TurtleScreen(cv2)
s2.bgcolor(1, 0.85, 0.85)
p = RawTurtle(s1)
q = RawTurtle(s2)
p.color("red", (1, 0.85, 0.85))
p.width(3)
q.color("blue", (0.85, 0.85, 1))
q.width(3)
for t in p, q:
t.shape("turtle")
t.lt(36)
q.lt(180)
for t in p, q:
t.begin_fill()
for i in range(5):
for t in p, q:
t.fd(50)
t.lt(72)
for t in p, q:
t.end_fill()
t.lt(54)
t.pu()
t.bk(50)
return "EVENTLOOP"
if __name__ == '__main__':
main()
TK.mainloop()
2.19 yinyang
from turtle import *
def yin(radius, color1, color2):
width(3)
color("black", color1)
begin_fill()
circle(radius / 2., 180)
circle(radius, 180)
left(180)
circle(-radius / 2., 180)
end_fill()
left(90)
up()
forward(radius * 0.35)
right(90)
down()
color(color1, color2)
begin_fill()
circle(radius * 0.15)
end_fill()
left(90)
up()
backward(radius * 0.35)
down()
left(90)
def main():
reset()
yin(200, "black", "white")
yin(200, "white", "black")
ht()
return "Done!"
if __name__ == '__main__':
main()
mainloop()