今回は繰り返しの入れ子(繰り返しの中に繰り返しがあること)に挑戦してみましょう。
次のプログラムを見てみましょう。
1: /* 2: * 複数の円を書くプログラム 3: * (角度を増やしていく版) 4: * 2003/06/08 5: * Yoshiaki Matsuzawa 6: */ 7: public class MultiCircle extends Turtle { 8: 9: //起動処理 10: public static void main(String[] args) { 11: Turtle.startTurtle(new MultiCircle()); 12: } 13: 14: //タートルを動かす処理 15: public void start(){ 16: 17: int i;//ループ用1 18: int j;//ループ用2 19: 20: int length;//1回に進む距離 21: int angle;//1回に曲がる角度 22: 23: //円を10個書くためのループ 24: i = 1; 25: while(i <= 10){ 26: angle = i; 27: length = 1; 28: 29: //円を書くためのループ 30: j = 1; 31: while(j <= 360){ 32: fd(length); 33: rt(angle); 34: j = j + angle; 35: } 36: 37: i = i + 1; 38: } 39: 40: } 41: 42: }
下のボタンを押すと、このプログラムが実行できます。 ここをクリックすると、プログラムをダウンロードできます。
前回、円を書くには繰り返しを使うことを習いました。今回は、さらにその円を何個も書くために、 もう一つ外側に繰り返しを作って、"繰り返しを繰り返す"ということをやっています。
ブロックは中括弧({})で囲まれた部分のことを言います。
下図のように、プログラムのifブロックやwhileブロックはいくつでも入れ子にすることができます。
ブロックを示す中括弧は必ず対応していなくてはなりません。 開き括弧が余ったり、閉じ括弧が余ったりすると、コンパイルエラーとなります。
括弧違いの場合、コンピュータはブロックを勘違いしてしまうので、 よけいなコンパイルエラーが(たくさん)でます。 たくさんのコンパイルエラーが一気にでたら、まず括弧の対応関係を確かめましょう。
第3回の時にも指摘しましたが、インデントをつけると括弧の対応関係やブロックの範囲が分かりやすくなります。 インデントがついていないソースは受理しません。
見やすいだけでなく、これができていないためにコンパイルエラーで動かない場合が非常に多いので、 注意してください。
論プロエディタでは、フォーマットをするとよいです。
剰余演算子(%)を使うと、割り算のあまりを求めることができます。 これを使うと、例えば奇数と偶数を判定することができます。
1: /* 2: * 四角と三角を並べていくプログラム 3: * 2003/06/08 4: * Yoshiaki Matsuzawa 5: */ 6: public class SquareAndTriangle extends Turtle { 7: 8: //起動処理 9: public static void main(String[] args) { 10: Turtle.startTurtle(new SquareAndTriangle()); 11: } 12: 13: //タートルを動かす処理 14: public void start(){ 15: 16: int i;//ループ用1 17: int j;//ループ用2 18: 19: int length = 50;//1辺の長さ 20: 21: //8回繰り返す 22: i = 0; 23: while(i < 8){ 24: 25: if(i % 2 == 0){//偶数なら 26: //四角形を書く 27: j = 1; 28: while(j <= 4){ 29: fd(length); 30: lt(90); 31: 32: j++;//jを1増やす([j = j + 1] の省略形) 33: } 34: }else{//奇数なら 35: //三角形を書く 36: j = 1; 37: while(j <= 3){ 38: fd(length); 39: lt(120); 40: 41: j++;//jを1増やす([j = j + 1] の省略形) 42: } 43: } 44: 45: //次の図形を書く位置に移動 46: up(); 47: rt(135); 48: fd(length); 49: rt(180); 50: down(); 51: 52: i++;//jを1増やす([i = i + 1] の省略形) 53: } 54: 55: } 56: 57: }
下のボタンを押すと、このプログラムが実行できます。 ここをクリックすると、プログラムをダウンロードできます。
応用として、花を描くプログラムを考えてみましょう。
花を描くには、まず花びらをかいて、それを繰り返す必要があります。
1: /* 2: * 花びらを書くプログラム 3: * 2003/06/08 4: * Yoshiaki Matsuzawa 5: */ 6: public class Petal extends Turtle { 7: 8: //起動処理 9: public static void main(String[] args) { 10: Turtle.startTurtle(new Petal()); 11: } 12: 13: //タートルを動かす処理 14: public void start(){ 15: 16: int i;//ループ用 17: 18: int length = 1; 19: int angle = 1; 20: 21: //円弧を書く 22: i = 1; 23: while(i <= 120){ 24: rt(angle); 25: fd(length); 26: i = i + angle; 27: } 28: 29: //次の円弧の角度へ 30: rt(60); 31: 32: //円弧を書く 33: i = 1; 34: while(i <= 120){ 35: rt(angle); 36: fd(length); 37: i = i + angle; 38: } 39: 40: } 41: }
下のボタンを押すと、このプログラムが実行できます。 ここをクリックすると、プログラムをダウンロードできます。
花びらを描くには繰り返しが必要で、花を描くにはさらにそれを繰り返す必要があります。 以下のように、繰り返しの入れ子を使います。
1: /* 2: * 花を書くプログラム 3: * 2003/06/08 4: * Yoshiaki Matsuzawa 5: */ 6: public class Flower extends Turtle { 7: 8: //起動処理 9: public static void main(String[] args) { 10: Turtle.startTurtle(new Flower()); 11: } 12: 13: //タートルを動かす処理 14: public void start(){ 15: 16: int i;//ループ用 17: int j;//ループ用 18: 19: int length = 1; 20: int angle = 1; 21: 22: 23: //6枚の花びらを書く 24: i = 1; 25: while(i <= 6){ 26: 27: //円弧を書く 28: j = 1; 29: while(j <= 120){ 30: rt(angle); 31: fd(length); 32: j = j + angle; 33: } 34: 35: //次の円弧の角度へ 36: rt(60); 37: 38: //円弧を書く 39: j = 1; 40: while(j <= 120){ 41: rt(angle); 42: fd(length); 43: j = j + angle; 44: } 45: 46: i++; 47: } 48: } 49: }
下のボタンを押すと、このプログラムが実行できます。 ここをクリックすると、プログラムをダウンロードできます。
ポイントは、花びらを書くループの外側にそれを6回繰り返すループをつくる (つまりループを入れ子にする)ことです。 「繰り返しを繰り返す」ためには、繰り返す繰り返しの外側に繰り返しループ を書く必要がありました。構造は以下のようになります。
以下に、よくある間違いの例を示します。
1: /* 2: * 花を書くプログラム(うまくいかない版) 3: * 2003/06/08 4: * Yoshiaki Matsuzawa 5: */ 6: public class InvalidFlower extends Turtle { 7: 8: //起動処理 9: public static void main(String[] args) { 10: Turtle.startTurtle(new InvalidFlower()); 11: } 12: 13: //タートルを動かす処理 14: public void start(){ 15: 16: int i;//ループ用 17: int j;//ループ用 18: 19: int length = 1; 20: int angle = 1; 21: 22: 23: //6枚の花びらを書く 24: i = 1; 25: while(i <= 6){ 26: rt(angle); 27: fd(length); 28: i = i + angle; 29: } 30: 31: //円弧を書く 32: j = 1; 33: while(j <= 120){ 34: rt(angle); 35: fd(length); 36: j = j + angle; 37: } 38: 39: //次の円弧の角度へ 40: rt(60); 41: 42: //円弧を書く 43: j = 1; 44: while(j <= 120){ 45: rt(angle); 46: fd(length); 47: j = j + angle; 48: } 49: 50: } 51: }
下のボタンを押すと、このプログラムが実行できます。 ここをクリックすると、プログラムをダウンロードできます。
これがうまくいかない理由が説明できるでしょうか? 以下に、このプログラムの構造を示しますので、 うまくいく方と比較してみましょう。
このように、入れ子を作る時には、{}の位置に注意する必要があります。
ヒント: 下の四角形を100個描くプログラムを参考にせよ
1: /* 2: * 四角を並べていくプログラム 3: * 2003/06/08 4: * Yoshiaki Matsuzawa 5: */ 6: public class HandredBlock extends Turtle { 7: 8: //起動処理 9: public static void main(String[] args) { 10: Turtle.startTurtle(new HandredBlock()); 11: } 12: 13: //タートルを動かす処理 14: public void start(){ 15: 16: int i;//ループ用1 17: int j;//ループ用2 18: int k;//ループ用3 19: 20: int length = 10;//四角の大きさ 21: int margin = 5;//隣の四角との間隔 22: 23: //縦に10回繰り返すためのループ 24: i = 1; 25: while(i <= 10){ 26: 27: //横に10回繰り返すためのループ 28: j = 1; 29: while(j <= 10){ 30: 31: //四角形を書くためのループ 32: k = 1; 33: while(k <= 4){ 34: fd(length); 35: rt(90); 36: 37: k++; 38: } 39: 40: //四角形を書いたら隣に移動 41: up(); 42: rt(90); 43: fd(length); 44: fd(margin); 45: lt(90); 46: down(); 47: 48: j++; 49: } 50: 51: //横一列が終ったら左下に移動 52: up(); 53: lt(90); 54: fd((length + margin) * 10); 55: lt(90); 56: fd(length + margin); 57: rt(180); 58: down(); 59: 60: i++; 61: } 62: 63: } 64: 65: }
下のボタンを押すと、このプログラムが実行できます。 ここをクリックすると、プログラムをダウンロードできます。
ヒント:四角を大きくしながら、角度を変えていく ( 繰り返しの変数を利用すること )
ヒント:ずらす角度は8度, 四角の1辺は10歩にするとうまくいく。 真ん中の円は多少ずれていても構わない。
ノーヒント
ノーヒント