2018年6月15日金曜日

【Python】家を描くプログラムを関数化 インデント&コメントアウトすれば即完成【タートルグラフィックス】

前回の記事のなかで、亀の家を描くプログラムを作りました。 今回、そのプログラムを関数にしました。

前回のプログラムの一部をコピーして、関数のコードとして貼り付け、インデントし、不要な記述をコメントアウトしたら、すぐに関数が完成しました。

関数を作れば、処理が簡潔で手短になります。プログラムの可読性が高ったかもしれません。

亀の家をたくさん描くプログラム

一軒の家を描くだけではつまらないので、 たくさんの亀の家を作るプログラム を作ってみました。

前回のプログラムを少し改変しました。

亀の家を大量に作るプログラムのソースコードはこちら です。

import turtle # turtleモジュールをインポート

#------ 現在地から見て(x,y)がある方向にカーソルの向きを設定する関数------------
def turnTo(ttl, x, y):
    to_angle = ttl.towards(x, y) # (x,y)の方向を返す(右0,上90,左180,下270)
    ttl.setheading(to_angle) # カーソルの向きを to_angle の方向にセット

#------- 家を描く関数 -------------------
# ttl: turtleクラスのインスタンス(カーソルの事)
# centerX: 正方形の中心のx座標
# centerY: 正方形の中心のy座標
# width: 家の横幅
def draw_house(ttl, centerX, centerY, width=100):
    square_length = width # 正方形の長さ
    triangle_height = square_length/4 # 三角形の高さ
    #--------------右上に移動-------------------
    x = centerX + square_length/2
    y = centerY + square_length/2
    ttl.penup() # ペンを上げる(移動中に線が引かれないようになる)
    ttl.goto(x, y) # 正方形の右上の点に移動
    #------------------屋根を描く---------------
    ttl.pendown() # ペンを下げる(移動中に線が引かれるようになる)
    x = centerX
    y = centerY + square_length/2 + triangle_height
    turnTo(ttl, x, y) # 現在地から見て(x,y)がある方向に向きを変える
    ttl.goto(x, y) # 屋根の一番上に移動
    x = centerX - square_length/2
    y = centerY + square_length/2
    turnTo(ttl, x, y) # 現在地から見て(x,y)がある方向に向きを変える
    ttl.goto(x, y) # 正方形の左上の点に移動
    #------------------正方形の部分を描く--------------
    ttl.setheading(270) # 下を向く
    for i in range(4): # 4回同じ事を繰り返す
        ttl.forward(square_length)
        ttl.left(90)
    #------------------真ん中に亀のスタンプを押す--------------------
    ttl.penup() # ペンを上げる(移動中に線が引かれないようになる)
    ttl.goto(centerX, centerY) # 真ん中に戻る
    ttl.setheading(90) # 上を向く
    size = ttl.shapesize() # 現在のカーソルのサイズを記録(タプル型のデータを返す)
    ttl.shapesize(int(width/100) +1) # カーソル(亀)の大きさを「家の大きさ」に合わせる
    ttl.stamp() # 亀のスタンプをつける
    ttl.shapesize(size[0]) # カーソルのサイズを戻す

# 画面を設定
width = 600
height = 600
scr = turtle.Screen() # 画面を作る
scr.title ('Houses') # 画面の上にタイトルを表示
scr.setup (width , height) # 画面のサイズを設定

# カーソル(亀)の設定
ttl = turtle.Turtle() # カーソル(亀)を作る
ttl.shape('turtle') # カーソルを亀に設定
ttl.screen.screensize(width+100 , height+100) # 画面をスクロールできる範囲
ttl.speed(2) # 絵を描くスピード
ttl.shapesize(1) # カーソル(亀)のサイズ
ttl.pensize(1) # ペンの太さ
ttl.color('brown') # ペンの色

# 6個の家を描く(横3x縦2)
for i in range(2):
    for j in range(3):
        x = -width/2 + 150 * (j+1)
        y = height/2 - 175 * (i+1)
        draw_house(ttl, x, y, 100) # 家を描く

# 画面をクリックしたら終了
scr.exitonclick()

家を描くプログラムを関数化させる

インデントのキーボードショートカットを覚えた方がいい

前回、 一軒の家を描くプログラム を書きました。 そのコードの一部をコピーして、「家を描く関数」 draw_house() の中に貼りました。 そして、インデント(字下げ)します。

インデント(indent) とは「コードの塊を右に移動させること」です。 通常、半角4文字分、右にずらします。 今回の場合、 「コードの塊を関数の中に入れる」と言ったほうが分かりやすいかもしれませんね。 indent なだけに。

逆に、「コードの塊を左に移動させること」をアウトデント(outdent) といいます。 for文 や def文 の外に出す感じです。

多くのエディタには、キーボードショートカット が割り当てられています。 「インデント ショートカット エディタ名」で検索してください。

ちなみに、私はテキストエディタAtomを使っています。 テキスト選択したあと、下のように入力すれば、インデントやアウトデントができます。

  • インデント:Ctrl + ]Ctrl を押しながら])
  • アウトデント:Ctrl + [Ctrl を押しながら[)

コメントアウトのキーボードショートカットを覚えたほうがいい

そして、不要になった処理を「コメントアウトまたは削除」します。 コメントアウト(comment out)とは、 「プログラムの記述」をコメントにして、その処理を無効化させることを言います。

Pythonで言うと、コメントアウトとは 「プログラムが記述されている部分の先頭に # を挿入する事」です。

その処理が完全に不要かはっきりしない場合、とりあえずコメントアウトする方が安全だと思います。 削除してしまったら、やっぱり必要になったとき、またコードを書く必要が生じます。

コメントアウトとは逆に、コメントの印を外して処理を有効化させる事 をアンコメント(uncomment)と言います。 pythonでいうと、アンコメントとは 「# を削除すること」です。 コメントによって無効化されていた処理が有効になります。

多くのエディタには キーボードショートカット が割り当てられているはずです。 「コメントアウト ショートカット エディタ名」で検索してください。

私はAtomというテキストエディタを使っています。 マウスでテキストを選択したあと、下のように入力すればコメントアウトまたはアンコメントできます。

  • コメントアウト:Ctrl + /Ctrlキーを押しながら/)
  • アンコメント:Ctrl + /Ctrlキーを押しながら/)

仕上げ

この時点で、draw_house() 関数 が 90%くらい完成しています。 さらに、下のように少し関数を変更しました。

  • 亀が進行方向を向くように turnTo(ttl, x, y) という関数を作った
  • 亀のスタンプの大きさを変えた

たったこれだけです。 工夫してコーディング(coding)すれば、短時間で関数をつくる事ができます。

forループの中にforループを入れる事ができる

下の画面はPythonコンソールです。

>>> # forループの中にforループを入れる事ができる
... for i in range(2):
...     for j in range(3):
...         # 2重にインデントされています
...         print("(i,j)=({0},{1})".format(i,j))
...
(i,j)=(0,0)
(i,j)=(0,1)
(i,j)=(0,2)
(i,j)=(1,0)
(i,j)=(1,1)
(i,j)=(1,2)
double_for_loop_example_20180615.py

forループ の中に forループ を入れる事ができます。 また、if文 の中に if文 を入れることもできます。

このようなプログラムの記述は 入れ子(nesting) と呼ばれています。 一番中の部分は2重にインデントされています。

range() は 等差数列 を 順番に返す 関数です。

  • range(2) は 数列 「0, 1」 を順番に返します(※2は含まれない)
  • range(3) は 数列 「0, 1, 2」を順番に返します(※3は含まれない)

forループの処理の順番を説明します。 外側のforループは i の値を操作します。 内側のforループは j の値を操作します。

  • i=0 とする
    • i=0, j=0 のときの処理をする
    • i=0, j=1 のときの処理をする
    • i=0, j=2 のときの処理をする
  • i=1とする
    • i=1, j=0 のときの処理をする
    • i=1, j=1 のときの処理をする
    • i=1, j=2 のときの処理をする

これを利用して、6軒の家(横3縦2) の家を描いています。

# 6個の家を描く(横3x縦2)
for i in range(2):
    for j in range(3):
        x = -width/2 + 150 * (j+1)
        y = height/2 - 175 * (i+1)
        draw_house(ttl, x, y, 100) # 家を描く

x座標をx = -width/2 + 150 * (j+1) としているので、まず家は左から右の順に描かれます

y座標をy = height/2 - 175 * (i+1) としているので、横1行の家を描きおえたら、下に行をずらして、もう一行の家を描きます。

0 件のコメント:

コメントを投稿

投稿されたコメントは承認後に公開されます。