6 ブロックの入れ子構造

6.1 学習目標

6.2 繰り返しの入れ子

今回は繰り返しの入れ子(繰り返しの中に繰り返しがあること)に挑戦してみましょう。

6.2.1 窓を描く(4つの四角形を描く)プログラム

次のプログラムを見てみましょう。

図 6.2.1.1 FourSquares
リスト 6.2.1.1 FourSquares.java
  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プログラムが実行できます。

図 6.2.1.2 窓を描くプログラム

前回、四角形を描くには繰り返しを使うことを習いました。今回は、さらにその四角形を何個も描くために、 もう一つ外側に繰り返しを作って、"繰り返しを繰り返す"ということをやっています。

入れ子の様子はフローチャートで示すとよく分かります.

図 6.2.1.3 窓を描くプログラム

6.2.2 ブロックの入れ子

ブロックは中括弧({})で囲まれた部分のことを言います。

下図のように、プログラムのifブロックやwhileブロックはいくつでも入れ子にすることができます。

図 6.2.2.1 ブロックの入れ子
コンパイルエラーに注意

ブロックを示す中括弧は必ず対応していなくてはなりません。 開き括弧が余ったり、閉じ括弧が余ったりすると、コンパイルエラーとなります。

括弧違いの場合、コンピュータはブロックを勘違いしてしまうので、 よけいなコンパイルエラーが(たくさん)でます。 たくさんのコンパイルエラーが一気にでたら、まず括弧の対応関係を確かめましょう。

6.2.3 インデント

第3回の時にも指摘しましたが、インデントをつけると括弧の対応関係やブロックの範囲が分かりやすくなります。 インデントがついていないソースは受理しません。

見やすいだけでなく、これができていないためにコンパイルエラーで動かない場合が非常に多いので、 注意してください。

図 6.2.3.1 インデント

論プロエディタでは、フォーマットをするとよいです。

6.3 入れ子と並列の違いの考察:花を描くプログラム

入れ子の応用として、花を描くプログラムを考えてみましょう。

図 6.3.1 花を書くプログラム

6.3.1 花びらを描く

花を描くには、まず花びらをかいて、それを繰り返す必要があります。

図 6.3.1.1 花びらを書くプログラム
図 6.3.1.2 Petal
リスト 6.3.1.1 Petal.java
  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プログラムが実行できます。

6.3.2 花を描く

花びらを描くには繰り返しが必要で、花を描くにはさらにそれを繰り返す必要があります。 以下のように、繰り返しの入れ子を使います。

図 6.3.2.1 Flower
リスト 6.3.2.1 Flower.java
  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回繰り返すループをつくる (つまりループを入れ子にする)ことです。 「繰り返しを繰り返す」ためには、繰り返す繰り返しの外側に繰り返しループ を書く必要がありました。構造は以下のようになります。

図 6.3.2.2 花を書くプログラムの構造

6.3.3 花を描く(間違い)

以下に、よくある間違いの例を示します。

図 6.3.3.1 BadFlower
リスト 6.3.3.1 BadFlower.java
  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プログラムが実行できます。

これがうまくいかない理由が説明できるでしょうか? 以下に、このプログラムの構造を示しますので、 うまくいく方と比較してみましょう。

図 6.3.3.2 うまくいかない花を書くプログラムの構造

このように、入れ子を作る時には、{}の位置に注意する必要があります。

6.4 繰り返し変数の利用

6.4.1 目玉を描くプログラム

次のプログラムを見てみましょう。

図 6.4.1.1 MultiCircle
リスト 6.4.1.1 MultiCircle.java
  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プログラムが実行できます。

図 6.4.1.2 たくさんの円を書くプログラム

「「円を描く繰り返し」を繰り返す」という入れ子のループになっています。ただし,単に10回円を描くのではなく, j回目のループの時にj度だけ回りながら円を作っています。つまり,繰り返しの回数を記憶しておくjという変数を利用して, 繰り返しの回数で円の大きさを変化させようとしているのです。

6.4.2 奇数と偶数を判定する

剰余演算子(%)を使うと、割り算のあまりを求めることができます。 これを使うと、例えば奇数と偶数を判定することができます。

図 6.4.2.1 SquareAndTriangle
リスト 6.4.2.1 SquareAndTriangle.java
  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プログラムが実行できます。

図 6.4.2.2 三角形と四角形を交互に書くプログラム

このプログラムでは、剰余演算子と、先ほど説明した繰り返しの変数を利用して、 繰り返した数が偶数なら四角,奇数なら三角を描くようにプログラムされています。

6.5 練習問題

6.5.1 四角形を10個描くプログラムを作ろう

図 6.5.1.1 10個描くプログラム

ファイル名は「TenBoxes.java」とすること.

6.5.2 四角形を100個描くプログラムを作ろう

図 6.5.2.1 四角形を100個描くプログラム

ファイル名は「HundredBoxes.java」とすること.

6.5.3 四角形と三角形を交互に100個描くプログラムを作ろう

図 6.5.3.1 四角形と三角形を交互に100個描くプログラム

ファイル名は「HundredBoxes2.java」とすること.

6.5.4 貝殻を描くプログラムを作ろう

図 6.5.4.1 貝殻を描くプログラム

ヒント1:まず以下のプログラムを作ってみよう。

図 6.5.4.2 貝殻を描くプログラムのヒント

ヒント2:ヒント1が出来たら、四角の大きさを指定するとき、上位ループの繰返しの変数を利用する。

ファイル名は「Shell.java」とすること.

6.5.5 タイヤを描くプログラムを作ろう

図 6.5.5.1 タイヤを描くプログラム

ヒント:ずらす角度は8度, 四角の1辺は10歩にするとうまくいく。 真ん中の円は多少ずれていても構わない。

ファイル名は「Tire.java」とすること.

6.5.6 ドラえもんを描くプログラムを作ろう

図 6.5.6.1 ドラえもんを描くプログラム

ファイル名は「Doraemon.java」とすること.

6.5.7 キーボードを描くプログラムを作ろう

図 6.5.7.1 キーボードを描くプログラム

ファイル名は「Keyboard.java」とすること.