第6章 反復は同じ形を別の景色に変える
円を 10 個描くために ellipse を 10 行書くこともできます。位置が少しずつ変わるなら、その違いを規則として書けます。反復回数や間隔を変えたり、一つだけ色を変えたりすると、同じ図形から異なる模様を作れます。
6.1 5 回描く times
まず、同じ場所へ円を 5 回描きます。
def setup
createCanvas(500, 220)
background(245)
5.times do
ellipse(100, 110, 60, 60)
end
end
見える円は一つです。同じ場所へ完全に重ねたからです。反復回数は増えましたが、位置が変わっていません。
times(タイムズ)は、何回目の反復かをブロック変数へ渡せます。直前の長いコードにある 5.times do から対応する end までを、次の変更部分と置き換えます。
5.times do |i|
x = 70 + i * 90
ellipse(x, 110, 60, 60)
end
初めて見る記号がいくつかあります。左から順に読みます。
5.timesは、その後の処理を 5 回繰り返しますdoは、繰り返す処理の始まりです|i|は、今が何回目かを受け取るための書き方です。縦線 2 本の間に変数名を書きます- 最後の
endは、繰り返す範囲の終わりです
i は 0、1、2、3、4 と変わります。プログラムでは番号を 0 から数える場面が多くあります。5 回繰り返しても最後が 4 なのは、最初が 0 だからです。
最初の x は 70 + 0 * 90 なので 70、次は 70 + 1 * 90 なので 160 です。* は掛け算を表します。反復回数を 8 へ変えるだけで、同じ間隔の円が増えます。
6.2 行と列を重ねる
横方向の反復を、縦方向の反復の内側へ置きます。
def setup
createCanvas(480, 360)
background(28, 32, 50)
noStroke
4.times do |row|
6.times do |column|
x = 50 + column * 75
y = 55 + row * 85
fill(240, 180, 70)
ellipse(x, y, 44, 44)
end
end
end
外側の row が 1 回進む間に、内側の column が 0 から 5 まで進みます。4 行 × 6 列なので、円は 24 個です。
反復を重ねるとコードは短くなりますが、最初は動きを追いにくくなります。行数を 2、列数を 3 へ減らすと、どの順で描かれるか想像しやすくなります。
6.3 規則の中の一つだけを変える
すべて同じだと、画面は安定します。直前の長いコードの二重反復部分を、次の変更部分と置き換え、条件分岐で一つだけ色を変えます。
4.times do |row|
6.times do |column|
x = 50 + column * 75
y = 55 + row * 85
if row == 1 && column == 3
fill(235, 80, 120)
else
fill(240, 180, 70)
end
ellipse(x, y, 44, 44)
end
end
== は値が等しいかを比べ、&& は「かつ」です。2 行目であり、かつ 4 列目の円だけが別の色になります。ブロック変数は 0 から始まるため、row == 1 が 2 行目です。
6.4 同じ間隔からずれを作る
列ごとに y 座標を少し変えると、格子が波打って見えます。二重反復の中にある y = 55 + row * 85 の 1 行だけを、次の 1 行と置き換えます。
y = 55 + row * 85 + (column % 2) * 20
% は余りを求める演算子です。column % 2 は、column が偶数なら 0、奇数なら 1 になります。番号が奇数の列だけ 20 下がるため、互い違いの配置になります。
さらに ellipse の大きさへ row や column を使えば、左から右、上から下への変化を作れます。二重反復の中にある ellipse(x, y, 44, 44) の 1 行を、次の変更部分と置き換えます。
size = 24 + column * 6
ellipse(x, y, size, size)
反復の番号を位置、色、大きさへ使うと、同じ図形の並び方を変えられます。
6.5 同じ反復から三つの作品を選ぶ
今の行と列のコードは、形を変えるだけで別の風景になります。
ellipseの色を緑にし、円の大きさを行ごとに変えると植物園rectへ変え、黄色を一部だけ灯すと夜の窓rectの横幅を細くし、列ごとに高さを変えると街の輪郭
三つの案から一つ選び、まず図形と背景色だけを変えてみましょう。そのあと、一個だけ色か大きさを変え、最初に目へ入る図形を作ります。どの位置の図形を変えると目立つかも比べられます。
6.6 発展:形の中へ同じ形を描く
大きな円の中へ半分の円を描き、その円の中へさらに半分の円を描くと、同じ規則が小さくなりながら続く模様ができます。このように、全体と似た形が一部分にも現れる構造をフラクタルと呼びます。
def setup
createCanvas(500, 320)
background(20, 25, 45)
noStroke
draw_circles(width / 2, height / 2, 240)
end
def draw_circles(x, y, size)
return if size < 12
fill(120 + size / 3, 100, 210, 150)
ellipse(x, y, size, size)
next_size = size / 2
draw_circles(x - size / 4, y, next_size)
draw_circles(x + size / 4, y, next_size)
end
draw_circles の中から、もう一度 draw_circles を呼んでいます。自分自身を呼び出す方法を再帰と呼びます。return if size < 12 は、円が 12 より小さくなったら、その呼び出しをそこで終える条件です。この条件がないと、いつまでも小さくしようとして処理を終えられません。
この発展例は、同じ形の中へ形を描くときの変化を画面から確かめます。まずそのまま実行し、setup の 240 だけを 180 へ変えて実行します。模様全体が小さくなるか見たら、240 へ戻して実行します。次に、return if size < 12 の 12 だけを 24 へ変えて実行し、小さい円の数が減るか見ます。エラーが出たら、変更した数字を元へ戻して実行します。その次に、円を四角形へ変える、左右ではなく上下へ分ける、色を大きさから決める、といった改造へ進めます。
格子模様とフラクタルでは、同じ反復でも違う画面になりました。残したいほうへ短い名前を付けたら、第7章で規則的な動きと予想できない変化を比べます。
参考資料
- Ruby 公式
Integer#times— 回数を決めた反復 - Ruby 公式「制御構造」 — ブロック、
return、条件分岐