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