タートルグラフィックスで学ぶ Python のキホン 第 8 章
教材コード
第 8 章

たくさんのタートル

かめを増やして,名前をつけて,別々に動かします.

第 2 章からここまで,画面にいるかめはずっと 1 匹でした. fd(100) と書けばそのかめが進み,lt(90) と書けばそのかめが回る. 命令する相手が 1 匹しかいないので,相手を指定する必要がなかったのです.

今回はかめを何匹でも増やせるようにします. そうなると「どのかめに命令するのか」を書かなければなりません. そのために,かめを変数に入れて名前をつけ,その名前に向かって命令を出す という書き方を覚えます.これは Python だけの話ではなく, 現在のプログラミングで最もよく使われている考え方 (オブジェクト指向)の入口でもあります.

この章でできるようになること
  • t = Turtle() でかめを何匹でも作れる
  • t.fd(100) のように,相手を指定して命令が出せる
  • これまでの fd(100) が誰への命令だったのかを説明できる
  • かめごとに色・太さ・形・大きさを変えられる
  • 複数のかめを同時に動いているように見せられる
  • distancetowards でかめ同士の関係を調べられる
今回のいちばんの山場 今回のプログラムは「かめを作る」「かめに命令する」の 2 つでできています. 長さも行数も今までと変わりませんが,書き方の形が変わります. 最初の 8.1 節をていねいに読んでください.ここさえ越えれば,あとは今までと同じです.

8.1 かめを増やす

8.1.1 なぜ 1 匹では足りないのか

前の章(第 7 章)までで,iffor, そして繰り返しの入れ子まで覚えました. 1 匹のかめで描ける絵なら,もうたいていのものは描けます. しかし,次のようなことはまだできません.

  • 2 つの絵が同時に育っていくアニメーション(左の円と右の円が一緒に描かれていく)
  • 競走.3 匹が横に並んで,それぞれ違う速さで進む
  • 追いかけっこ.片方がもう片方を追いかける
  • 画面のあちこちにばらばらの状態(位置・向き・色)を同時に持たせること

どれも「状態を持った登場人物が複数いる」という点で共通しています. かめが 1 匹しかいないと,位置も向きも色も 1 組しか持てません. goto で行ったり来たりさせれば真似はできますが,すぐに破綻します. 登場人物が 2 人いるなら,かめも 2 匹用意するのが素直です.

8.1.2 これまでの fd(100) は誰への命令だったのか

from turtle import * と書いて fd(100) と命令したとき, 実は舞台裏で名前のないかめが 1 匹用意されていました. 引数のない fd(100) は,その「名前のないかめ」への命令だったのです. この教材ではこれを既定(きてい)のかめと呼ぶことにします.

既定のかめにも,あとから名前をつけることができます. getturtle() と書くと,既定のかめを受け取れます.

default_turtle.py
from turtle import *

pensize(3)
fd(100)              # 名前のないかめ(既定のかめ)への命令

kame = getturtle()   # そのかめに「kame」という名前をつける

kame.lt(90)          # 今度は名前を指定して命令する
kame.fd(100)

done()
図 8.1 前半と後半で書き方が違うが,動いているのは同じ 1 匹.

前半の fd(100) と後半の kame.fd(100) は, まったく同じかめを動かしています.違うのは書き方だけです. 前半は「(あのかめに)進め」,後半は「kame よ,進め」と言っています.

ヒント getturtle() を使う場面は実はあまりありません. ここでは「今まで命令していた相手は誰だったのか」をはっきりさせるために出しました. 次の節からは,自分で新しいかめを作ります.

8.1.3 t = Turtle() でかめを作る

新しいかめを作るには Turtle() と書きます. そして,できたかめを変数に入れて名前をつけます

かめを 1 匹作って t という名前をつける
t = Turtle()

= の右でかめが 1 匹生まれ= の左の変数 tそのかめを指す名札になります. Turtle大文字の T で始まることに注意してください. かっこも必要です.

命令を出すときは,名前のうしろに .(ドット)を打って命令を書きます.

t という名前のかめへの命令
t.fd(100)
t.lt(90)
t.pencolor("red")

ドットは「」と読むとわかりやすいでしょう. t.fd(100) は「t の fd 命令を,100 で実行する」, もっとくだけて言えば「t よ,100 進め」です.

これまで(第 1〜7 回)今回から
fd(100)t.fd(100)
lt(90)t.lt(90)
pencolor("red")t.pencolor("red")
pu()t.pu()
相手は 1 匹だけ.書かなくても決まる相手を名前で指定する.何匹いてもよい

8.1.4 2 匹のかめを動かす

では実際に 2 匹作ってみましょう.名前は何でもかまいませんが, ここでは亀太郎亀次郎にします.

two_turtles.py
from turtle import *

# かめを 2 匹作る
kame_taro = Turtle()
kame_jiro = Turtle()

# 亀太郎への命令
kame_taro.pensize(4)
kame_taro.pencolor("crimson")
kame_taro.fd(120)

# 亀次郎への命令
kame_jiro.pensize(4)
kame_jiro.pencolor("royalblue")
kame_jiro.lt(90)
kame_jiro.fd(120)

done()
図 8.2 2 匹のかめ.どちらも中央から出発し,別々の方向へ進んだ.

kame_taro への命令と kame_jiro への命令が まったく干渉していないことを確かめてください. 太郎を赤にしても次郎は青のままですし,次郎を左に向けても太郎は右を向いたままです. かめはそれぞれ自分の位置・向き・色・太さを持っています.

生まれたてのかめの状態 新しく作ったかめは,必ず中央 (0, 0)・右向き・黒・ペンを下ろした状態 で生まれます.第 2 章で習った「かめの初期位置」と同じです. 何匹作っても全員そこから始まるので,ばらけさせたいときは pu()goto()pd() で配置します.

8.1.5 よくある間違い

かめを作るときの 6 つのつまずき
書き方何が起きるか
t = turtle()NameError大文字の TTurtle()
t = Turtleかっこが無い.かめが作られず,t.fd(100) でおかしなエラーになる
Turtle() だけ書くかめは生まれるが名札が無いので,二度と命令できない
t fd(100)ドットが無い.SyntaxError
t.fd 100かっこが無い.SyntaxError
かめを作らずに t.fd(100)NameError: name 't' is not defined先に作ってから命令する
虫食い虫食い 8-A 3 匹で Y 字を描く

3 匹のかめを中央から 3 方向へ進ませて,Y 字(三つ又)を描きます. ____ を埋めてください. 3 方向に均等に開くので,角度は 360 ÷ 3 = 120 度ずつです.

fill7_Y.py
from turtle import *

a = Turtle()
b = Turtle()
c = ____()

a.pensize(5)
b.pensize(5)
c.pensize(5)

a.pencolor("crimson")
b.pencolor("seagreen")
c.pencolor("royalblue")

a.lt(90)
a.fd(120)

b.lt(210)
____.fd(120)

c.lt(____)
c.fd(120)

done()

8.2 かめごとに見た目を変える

かめが複数いると,どれがどれだか分からなくなります. 見た目を変えて区別できるようにするのが,複数のかめを扱うコツです.

8.2.1 色と太さ

pencolor(線の色)と pensize(線の太さ)は, 第 2 章で習ったとおりです.前にドットで名前を付けるだけで, そのかめだけに効くようになります.

three_look.py
from turtle import *

a = Turtle()
b = Turtle()
c = Turtle()

a.pencolor("crimson")
a.pensize(1)

b.pencolor("seagreen")
b.pensize(4)
b.lt(120)

c.pencolor("darkorange")
c.pensize(8)
c.lt(240)

# 3 匹とも「正六角形を描く」という同じ動きをする
for i in range(6):
    a.fd(60)
    a.rt(60)
    b.fd(60)
    b.rt(60)
    c.fd(60)
    c.rt(60)

done()
図 8.3 同じ命令でも,向きと見た目が違うので別の絵になる.
pencolor と color の違い color("red") と書くと,線の色と塗りの色の両方が変わります. かめの姿(次の節で出てくる shape)の色も塗りの色で決まるので, かめ自身を色分けしたいときは pencolor ではなく color を使うのが早道です.

8.2.2 かめの形を変える — shape

shape で,かめの姿そのものを変えられます. 使える形は次の 7 種類です.

指定見た目
"classic"細い矢じり(最初の姿)
"arrow"三角の矢印
"square"四角
"triangle"大きめの三角
"circle"丸.ボールに使える
"turtle"かめの形.いちばんかわいい
"blank"姿を出さない(ht() と似ている)

大きさは shapesize(縦, 横) で変えます. shapesize(3, 3) なら縦横とも 3 倍です.

shapes.py
from turtle import *

a = Turtle()
b = Turtle()
c = Turtle()
d = Turtle()
e = Turtle()

a.shape("classic")
b.shape("arrow")
c.shape("square")
d.shape("triangle")
e.shape("turtle")

a.color("crimson")
b.color("darkorange")
c.color("goldenrod")
d.color("seagreen")
e.color("royalblue")

a.pu()
b.pu()
c.pu()
d.pu()
e.pu()

a.goto(-200, 20)
b.goto(-100, 20)
c.goto(0, 20)
d.goto(100, 20)
e.goto(200, 20)

# 全員 2 倍の大きさにする
a.shapesize(2, 2)
b.shapesize(2, 2)
c.shapesize(2, 2)
d.shapesize(2, 2)
e.shapesize(2, 2)

# 文字を書くためだけのかめ
pen = Turtle()
pen.ht()
pen.pu()

pen.goto(-225, -50)
pen.write("classic", font=("Arial", 13, "normal"))
pen.goto(-125, -50)
pen.write("arrow", font=("Arial", 13, "normal"))
pen.goto(-25, -50)
pen.write("square", font=("Arial", 13, "normal"))
pen.goto(75, -50)
pen.write("triangle", font=("Arial", 13, "normal"))
pen.goto(175, -50)
pen.write("turtle", font=("Arial", 13, "normal"))

done()
classicarrowsquaretriangleturtle
図 8.4 5 種類の姿.どれも右(東)を向いている.
役割ごとにかめを用意する 最後に出てきた pen は,文字を書くためだけのかめです. 絵を描くかめと文字を書くかめを分けておくと, 色や位置を行ったり来たりさせずに済みます. 複数のかめが使えるようになると,こういう「役割分担」ができるようになります.

8.2.3 姿を隠す・出す — ht と st

ht()(hide turtle)でかめの姿が消え, st()(show turtle)でまた現れます. 線はそのまま残るので,絵の仕上げによく使います.

姿の出し入れ
a.ht()      # a の姿を隠す(a が描いた線は残る)
a.st()      # a の姿をまた出す

ht()        # 既定のかめを隠す

複数のかめを使うプログラムでは,冒頭に ht() と書いて 使わない既定のかめを消しておくのが定石です. これを書かないと,何もしていないかめが 1 匹,画面の真ん中に立ったままになります.

虫食い虫食い 8-B 3 匹を見た目で区別する

3 匹のかめを横に並べ,形・色・大きさをそれぞれ変えます. ____ を埋めてください. 文字列(形や色の名前)は " で囲むのを忘れないように.

fill7_looks.py
from turtle import *

ht()          # 既定のかめを消しておく

a = Turtle()
b = Turtle()
c = Turtle()

a.shape("turtle")
b.shape(____)          # 丸にする
c.shape("square")

a.color("seagreen")
b.color("crimson")
c.color(____)          # 好きな色にする

a.shapesize(2, 2)
b.shapesize(____, ____)   # b だけ 3 倍
c.shapesize(1, 1)

a.pu()
b.pu()
c.pu()

a.goto(-140, 0)
b.goto(0, 0)
c.goto(140, 0)

done()

8.3 同時に動いているように見せる

ここが今回の一番おもしろいところです. 同じ絵ができあがるのに,動き方がまったく違う 2 つのプログラムを見比べます.

8.3.1 順番に動かす

まず,素直に書いた版です.亀太郎が円を描き終わってから,亀次郎が描き始めます. 実行して,動きをよく見てください.

four_sequential.py
from turtle import *

ht()

a = Turtle()
b = Turtle()
c = Turtle()
d = Turtle()

a.pencolor("crimson")
b.pencolor("royalblue")
c.pencolor("seagreen")
d.pencolor("darkorange")

b.lt(90)
c.lt(180)
d.lt(270)

# a が 1 周ぜんぶ描いてから,b が描き始める
for i in range(120):
    a.fd(2)
    a.rt(3)

for i in range(120):
    b.fd(2)
    b.rt(3)

for i in range(120):
    c.fd(2)
    c.rt(3)

for i in range(120):
    d.fd(2)
    d.rt(3)

done()
図 8.5 4 匹が順番に円を描いた結果.

8.3.2 交互に命令を出す

次は,繰り返しの中身を変えた版です. 4 匹ぶんの命令を 1 つの for の中に並べました. できあがる絵はさっきとまったく同じです.実行してください.

four_simultaneous.py
from turtle import *

ht()

a = Turtle()
b = Turtle()
c = Turtle()
d = Turtle()

a.pencolor("crimson")
b.pencolor("royalblue")
c.pencolor("seagreen")
d.pencolor("darkorange")

b.lt(90)
c.lt(180)
d.lt(270)

# 4 匹に少しずつ交互に命令を出す
for i in range(120):
    a.fd(2)
    a.rt(3)
    b.fd(2)
    b.rt(3)
    c.fd(2)
    c.rt(3)
    d.fd(2)
    d.rt(3)

done()
図 8.6 4 匹が同時に円を描いた結果.図 8.5 と同じ絵になる.

4 つの円が一緒に育っていくように見えたはずです. 実際には,コンピュータは「a を少し,b を少し,c を少し,d を少し」と 1 匹ずつ順番に動かしています. ただ,切り替えが細かいので,人間の目には同時に見えるのです.

コラム:コンピュータは同時に 2 つの仕事をできない コンピュータは,本当は2 つの仕事を同時にはできません. みなさんのパソコンやスマホは,動画を見ながらメッセージを打ち, 裏で更新をダウンロードすることができます. しかしその中身は,このタートルの例とまったく同じで, 細かく切り替えながら,いろいろな仕事を少しずつ進めているだけなのです.
  • 1 つの仕事を最後までやってしまうと,他の仕事が待たされる(8.3.1).
  • 少しずつ切り替えると,全部が同時に進んでいるように見える(8.3.2).
  • 切り替えを細かくしすぎると,切り替えそのものに時間を取られて遅くなる.

この考え方をマルチタスクといいます. 第 10 章のアニメーションも,第 12 章のゲームも,同じ原理でできています.

8.3.3 交互に出すときの書き方のコツ

  1. 1 回ぶんの動きを小さくする.fd(100) のように大きく動かすと,交互にしても同時に見えない.fd(2) くらいに刻む.
  2. 繰り返しは 1 つにまとめる.かめの数だけ for を書いたら,それは 8.3.1 の「順番」になる.
  3. 動く距離が違ってもよい.a.fd(2)b.fd(5) にすれば,b のほうが速く見える.競走はこれで作る.
  4. 途中で抜けるかめがいてもよい.if を使えば,あるかめだけ止めることもできる.
虫食い虫食い 8-C 2 匹が向かい合って進む

左端の赤いかめと右端の青いかめが,同時に弧を描きながら進みます. ____ を埋めてください. 青いかめは最初に左(西)を向かせる必要があります.

fill7_face.py
from turtle import *

ht()

a = Turtle()
b = Turtle()

a.pensize(3)
a.pencolor("crimson")
a.pu()
a.goto(-220, -60)
a.pd()

b.pensize(3)
b.pencolor("royalblue")
b.pu()
b.goto(220, -60)
b.pd()
b.lt(____)          # 左(西)を向かせる

for i in range(60):
    a.fd(5)
    a.lt(3)
    ____.fd(5)
    ____.rt(____)   # b は a と反対まわり

done()

8.4 4〜5 匹をまとめて使う

8.4.1 まんじ(卍)を描く

4 匹を中央から東・南・西・北に向けて,同じ命令を同時に出します. 「まっすぐ進む → 左に 90 度曲がる → またまっすぐ進む」だけで卍になります.

swastika.py
from turtle import *

ht()          # 既定のかめを消す

a = Turtle()
b = Turtle()
c = Turtle()
d = Turtle()

a.pensize(4)
b.pensize(4)
c.pensize(4)
d.pensize(4)

a.pencolor("crimson")
b.pencolor("royalblue")
c.pencolor("seagreen")
d.pencolor("darkorange")

# 90 度ずつずらして,四方を向かせる
b.rt(90)
c.rt(180)
d.rt(270)

# まっすぐ進む
for i in range(50):
    a.fd(2)
    b.fd(2)
    c.fd(2)
    d.fd(2)

# その場で左に 90 度まわる
for i in range(90):
    a.lt(1)
    b.lt(1)
    c.lt(1)
    d.lt(1)

# またまっすぐ進む
for i in range(50):
    a.fd(2)
    b.fd(2)
    c.fd(2)
    d.fd(2)

done()
図 8.7 4 匹のかめで描いたまんじ.
なぜ 1 度ずつ 90 回なのか 真ん中の for は,向きを変えるだけなので線を引きません. それでも 1 度ずつ 90 回に分けているのは, lt(90) と一気に書くと 4 匹が「カクッ」と同時に回ってしまい, アニメーションとして面白くないからです. 動きを細かく刻むという発想は,第 10 章でそのまま使います.

8.4.2 タートルリレー

4 匹を四角形の頂点に配置し,1 匹ずつ順番に走らせます. 走り終わったかめは ht() で消えて,次のかめにバトンを渡します. こちらは「同時」ではなく「順番」を意図的に使う例です.

turtle_relay.py
from turtle import *

ht()

a = Turtle()
b = Turtle()
c = Turtle()
d = Turtle()

a.shape("turtle")
b.shape("turtle")
c.shape("turtle")
d.shape("turtle")

a.color("crimson")
b.color("royalblue")
c.color("seagreen")
d.color("darkorange")

a.pensize(4)
b.pensize(4)
c.pensize(4)
d.pensize(4)

# 4 すみに配置して,走る向きを決める
a.pu()
a.goto(-150, 90)
a.seth(0)
a.pd()

b.pu()
b.goto(150, 90)
b.seth(270)
b.pd()

c.pu()
c.goto(150, -90)
c.seth(180)
c.pd()

d.pu()
d.goto(-150, -90)
d.seth(90)
d.pd()

# 第 1 走者
for i in range(60):
    a.fd(5)
a.ht()

# 第 2 走者
for i in range(36):
    b.fd(5)
b.ht()

# 第 3 走者
for i in range(60):
    c.fd(5)
c.ht()

# 第 4 走者(ゴール)
for i in range(36):
    d.fd(5)

done()
図 8.8 4 匹でつないだリレー.最後の 1 匹だけが残る.
seth — 向きを直接決める seth(角度) は「その場でその方角を向く」命令です. ltrt が「今の向きから何度回るか」なのに対し, seth今の向きに関係なく向きが決まります. 0 が東,90 が北,180 が西,270 が南です. 複数のかめをそろえて配置するときに便利です.

8.4.3 変数を 4 つ並べるということ

ここまでのプログラムでは,abcd と変数を 4 つ書き,同じ命令を 4 回ずつ書いてきました. かめが 4 匹なら我慢できますが,10 匹だったらどうでしょうか.100 匹だったら.

かめが増えると手に負えなくなる
a.fd(2)
b.fd(2)
c.fd(2)
d.fd(2)
# …あと 96 行
100 匹のかめはどうするのか 第 16 章で習うリストを使うと, 「かめ 100 匹」をひとまとめにして for で回せるようになります. 今は面倒に感じておくことが大事です. 第 2 章で同じ図形を 3 回書いたのと同じ状況にいます. 今回は多くても 5 匹までにしておきましょう.

8.5 かめ同士の関係を調べる

かめが複数いると,「あのかめはどこにいるのか」を 知りたくなります.そのための命令が 2 つあります.

8.5.1 距離を測る — distance

a.distance(b) と書くと, a から b までの距離が数として返ってきます. かめに命令するのではなく,かめにたずねて答えをもらう使い方です. 第 3 章の input()int() と同じ仲間で, 返ってきた数を変数に入れたり,計算に使ったりできます. こういう「答えを返す命令」を自分で作る方法は,第 14 章で習います.

distance.py
from turtle import *

ht()

a = Turtle()
b = Turtle()

a.shape("turtle")
a.color("seagreen")
b.shape("circle")
b.color("crimson")

a.pu()
a.goto(-120, -60)
b.pu()
b.goto(90, 70)

# 距離を測って表示する
print("a から b までの距離は", round(a.distance(b)))

# 2 匹を線で結んでみる
a.pencolor("gray")
a.pensize(2)
a.pd()
a.goto(b.xcor(), b.ycor())
a.pu()

done()
図 8.9 2 匹を結んだ線.長さがコンソールに出る.

b.xcor()b.ycor() は, b の x 座標・y 座標を返します. 相手の座標を取ってきて,そこへ goto したわけです. 座標を数で書かずに「相手のいるところ」と書けるのが, かめを変数で持っていることの利点です.

ヒント a.distance(b) は,a.distance(100, 50) のように 座標を直接渡すこともできます. どちらの書き方でも,返ってくるのは「そこまでの距離」です.

8.5.2 相手の方を向く — towards

a.towards(b) は,a から見た b の方角を返します. これを seth に渡せば,a は b の方を向きます.

追いかける動きの 2 行
a.seth(a.towards(b))    # a が b の方を向く
a.fd(5)                 # b に向かって 5 進む

この 2 行を繰り返すだけで,追いかけっこになります.

chase.py
from turtle import *

ht()

nezumi = Turtle()      # 逃げるほう
kame = Turtle()        # 追うほう

nezumi.shape("circle")
nezumi.color("crimson")
nezumi.pensize(2)
nezumi.pu()
nezumi.goto(160, 100)
nezumi.pd()

kame.shape("turtle")
kame.color("seagreen")
kame.shapesize(1.5, 1.5)
kame.pensize(2)
kame.pu()
kame.goto(-200, -120)
kame.pd()

for i in range(80):
    # ねずみは円を描いて逃げる
    nezumi.lt(4)
    nezumi.fd(6)

    # かめはねずみの方を向いて追いかける
    kame.seth(kame.towards(nezumi))
    kame.fd(7)

print("最後の距離は", round(kame.distance(nezumi)))

done()
図 8.10 かめ(緑)がねずみ(赤)を追いかけた軌跡.

かめのほうが 1 歩だけ大きい(7 と 6)ので,じわじわ追いつきます. kame.fd(7)kame.fd(5) に変えると, 今度は追いつけません.数を変えて確かめてください.

当たり判定の原型 towards が返すのは角度distance が返すのは長さです. どちらも答えを返してくる命令なので, print で表示したり,if の条件に使ったりできます. if kame.distance(nezumi) < 20: と書けば, 「つかまえた」の判定になります.第 12 章のゲームで使います.
虫食い虫食い 8-D 鬼ごっこ

青い子どもが逃げ,赤い鬼が追いかけます. ____ を埋めてください. 「相手の方を向く」ための命令と,「距離を測る」ための命令を思い出しましょう.

fill7_oni.py
from turtle import *

ht()

ko = Turtle()      # 逃げる子ども
oni = Turtle()     # 追う鬼

ko.shape("circle")
ko.color("royalblue")
ko.pensize(2)
ko.pu()
ko.goto(180, 120)
ko.pd()

oni.shape("turtle")
oni.color("crimson")
oni.pensize(2)

for i in range(60):
    ko.lt(5)
    ko.fd(8)
    oni.seth(oni.____(ko))    # ko の方を向く
    oni.fd(____)              # ko より少しだけ速く

print("最後の距離は", round(oni.____(ko)))

done()

8.6 足跡を残す — stamp

t.stamp() と書くと,そのときのかめの姿が その場にハンコのように押されて残ります. 線ではなく姿そのものが残るのがポイントです.

stamp.py
from turtle import *

ht()

t = Turtle()
t.shape("turtle")
t.color("seagreen")
t.shapesize(1.6, 1.6)
t.pu()                 # 線は引かない
t.goto(-220, -80)

for i in range(9):
    t.stamp()          # 今の姿をその場に残す
    t.fd(52)
    t.lt(7)

done()
図 8.11 9 個の足跡.線は 1 本も引いていない.

pu() してあるので線は引かれません. それでも進んだ跡がわかるのは,stamp() が姿を残しているからです.

命令意味
t.stamp()今の姿をその場に残す
t.clearstamps()そのかめが残した足跡をすべて消す
ヒント stamp は第 10 章・第 12 章でとても役に立ちます. たとえば「弾を撃つ」「星をばらまく」「通った道に印をつける」といった処理を, かめを何匹も作らずに書けます.

8.7 この章で出てきた命令

命令意味
t = Turtle()かめを 1 匹作り,t という名前をつける
t.fd(長さ)t に「進め」と命令する.bk lt rt も同じ形
t.pu() / t.pd()t のペンを上げる・下ろす
t.pencolor(色)t の線の色
t.color(色)t の線の色と姿の色の両方
t.pensize(太さ)t の線の太さ
t.shape(名前)t の姿.classic arrow square triangle circle turtle blank
t.shapesize(縦, 横)t の姿の大きさ(倍率)
t.ht() / t.st()t の姿を隠す・出す
t.goto(x, y)t をその座標へ動かす
t.seth(角度)t をその方角に向ける.0 が東,90 が北
t.xcor() / t.ycor()t の x 座標・y 座標を返す
t.heading()t が今向いている角度を返す
t.distance(u)t から u までの距離を返す
t.towards(u)t から見た u の方角を返す
t.stamp()t の姿をその場に残す
t.clearstamps()t が残した足跡を消す
getturtle()既定のかめ(名前のないかめ)を受け取る

演習

以下の演習には,出発点となるプログラムが入っています. 「▶ この演習を開く」で右側に読み込み,それを発展させて作品にしてください. できあがったら「⤓ 保存」でファイルに保存して,手元に残しておきましょう.

ヒント どの演習でも,先頭に ht() を書いて 既定のかめを消しておくことを忘れずに. 作ったかめが何匹いるのか,自分でも分からなくなったら, かめごとに色を変えてみてください.
演習演習 8-1 まんじをアレンジする

4 匹のかめを同時に動かしてまんじ(卍)を描くプログラムを与えます. これをもとに,独自にアレンジを加えたプログラムを作ってください.

  • かめの数を 4 匹から 6 匹・8 匹に増やしてみる(向きは 360 ÷ 匹数 度ずつ)
  • 曲がる回数を増やして,渦巻きのようにしてみる
  • 太さや色を途中で変えてみる
  • 曲がる向き(ltrt)を入れ替えてみる
出発点のまんじ
演習演習 8-2 タートルリレーをアレンジする

4 匹のかめが四角形のコースをリレーするプログラムを与えます. これをもとに,独自にアレンジを加えたプログラムを作ってください.

  • コースを三角形・五角形・星形にしてみる
  • 走者を 5 人・6 人に増やしてみる
  • 走り終わった人を ht() で消すのをやめて,並ばせてみる
  • バトンを渡す瞬間に stamp() で印を残してみる
  • 走る速さ(fd の数)を走者ごとに変えてみる
出発点のリレー
演習演習 8-3 タートルレースをアレンジする

3 匹のかめが左から右へ競走するプログラムを与えます. 進む距離を乱数で決めるので,実行するたびに結果が変わります. これをもとに,独自にアレンジを加えたプログラムを作ってください.

  • 走者を 4 匹・5 匹に増やす
  • コースに線を引く,ゴールの線を引く
  • xcor() を比べて,優勝者を print で発表する
  • 速い走者と遅い走者を作る(randint の上限を変える)
  • 途中で転ぶ走者を作る(if で一定回数だけ進ませない)
ヒント from random import randint と書いておくと, randint(0, 6)0 以上 6 以下のでたらめな整数 が手に入ります.毎回違う数になるので,レースらしくなります.
演習演習 8-4 たくさんのタートルで 1 枚の絵を描く

今まで描いた絵を,何匹かのかめで分担して描いてみます. 第 2 章で描いた「家」を,屋根係・かべ係・ドア係の 3 匹で描くプログラムを与えます. これをもとに,独自にアレンジを加えたプログラムを作ってください.

  • 係を増やす(窓係・煙突係・木係・太陽係)
  • 係ごとに色と太さを変えて,誰が何を描いたか分かるようにする
  • 3 匹を同時に動かして,家が一度に組み上がるようにしてみる(8.3 節)
  • 家を 2 軒・3 軒に増やす
出発点の家(3 匹で分担して描いた)
演習演習 8-5 星と五角形を同時に描く

2 匹のかめが,同時にそれぞれ星と五角形を描くプログラムを与えます. どちらも「進む」と「曲がる」を細かく刻み,交互に命令を出しています. 星は 1 か所で 144 度,五角形は 72 度曲がるので, 同じ回数だけ刻んで,1 回に曲がる角度を変えています. これをもとに,独自にアレンジを加えたプログラムを作ってください.

  • 3 匹目を足して,正六角形や正八角形も同時に描かせる
  • 大きさを変える(fd の数)
  • 描き終わったあと,2 匹を中央に集合させる
  • 描きながら色が変わるようにする
出発点:星(左)と五角形(右)
自由演習 8-6 かめたちの物語

ここまでの命令だけを使って,複数のかめが登場する作品を作ってください. 絵でも,競走でも,追いかけっこでも,かめたちのダンスでもかまいません.

  • かめを 3 匹以上使うこと
  • かめごとに色または形を変えて,区別できるようにすること
  • 8.3 節の「交互に命令を出す」をどこかで必ず使うこと
  • 先頭にコメントで,題名・氏名・日付を書くこと
  • 仕上げに既定のかめを ht() で消すこと
ヒント ネタに困ったら,次のどれかから始めてみてください. 「花火(中央から何匹も外へ飛び出す)」 「太陽と地球と月(追いかけながら回る)」 「合唱(横一列のかめが順番に上下する)」 「迷路(何匹かが別々の道を進む)」.

まとめ

  • t = Turtle() でかめを作り,t.fd(100) のようにドットで相手を指定して命令する.
  • これまでの fd(100) は,名前のないかめ(既定のかめ)への命令だった.
  • かめはそれぞれ自分の位置・向き・色・太さ・姿を持っている.shapecolor で区別をつける.
  • 順番に動かすと順番に見え,交互に少しずつ動かすと同時に見える.コンピュータは本当は同時に 2 つの仕事をしていない.
  • t.distance(u) で距離,t.towards(u) で方角がわかる.seth(towards(…)) で追いかけっこになる.
  • t.stamp() で姿をその場に残せる.
  • かめが増えると変数も増える.まとめて扱う方法は第 16 章(リスト)で習う.

次の回では,いったん絵から離れます. タートルを使わず,入力・計算・表示だけで作る CUI プログラムを書いてみます. 絵がない代わりに,仕様を読んでそのとおりに作る力がためされます.

そのあとの第 10 章で,このかめたちを本当に動かしますontimer という命令を使って, 「少し動かして,少し待って,また少し動かす」を繰り返させると, 絵がアニメーションになります.