多重ループ
繰り返しを繰り返す
もちろん、ループ内でもループを書ける。
for ( /* ~ */ ) {
for ( /* ~ */ ) {
}
}
これを 二重ループ とか、更に何個も連ねるのを 多重ループ とかいう。
外側で 10
回、内側で 10
回繰り返すと、10 × 10 = 100
回繰り返す。
外側で N
回、内側で M
回繰り返すと、N × M
回繰り返す。
以下、よくやる使い方を紹介しておく。
二つの値の組み合わせをすべて網羅する場合
ここでは、与えられた半径 radius
に対して、その半径の円の中に、中心から敷き詰めた正方形のタイルの数を数えてみる。
double radius = 1.42; // 約 √2、標準入力でもいいけど今回は決め打ち
int count = 0;
int limit = radius + 0.5;
// まず X と Y が + の方向の点だけ数える
for (int x = 1; x <= limit; ++x) {
for (int y = 1; y <= limit; ++y) {
if (x * x + y * y < radius * radius) { // 円の方程式 x^2 + y^2 < r^2 をしている
++count;
}
}
}
// 4 倍にする
count = count * 4 ;
一応この例では、x
のループの中に y
のループを書いてもいいし、y
のループの中に x
のループを書いてもいい。
複数行に渡って、パターンを画面に出力する場合
一行ずつに着目して考えると良い。
今回は、"#"
を黒点、" "
を白点として、画面に半径 radius
の円を描いてみる。
今の行の y
座標がわかっていると仮定しよう。これはあとで追加する 外側の for
ループ の制御変数だよ。
x
座標を増やしていくループを書く。
for (int x = -radius; x <= radius; ++x) {
// x^2 + y^2 <= r^2
if (x * x + y * y <= radius * radius) {
std::cout << "#";
} else {
std::cout << " ";
}
}
こんな感じの一行を考えたら、それを繰り返す場合を考える。
for (int y = -radius; y <= radius; ++y) {
// ここは一行の処理が始まる前
for (int x = -radius; x <= radius; ++x) {
// x^2 + y^2 <= r^2
if (x * x + y * y <= radius * radius) {
std::cout << "#";
} else {
std::cout << " ";
}
}
// ここは一行の処理が終わった後
// この改行を忘れないように
std::cout << "\n";
}
行を繰り返すので、外側の for
はこれだけ。
これで完成。実行してみると、きれいな円 が見られるはず。他にもいろいろやってみてね。
この場合は、ループの内側と外側を逆にしたりはできない。
横方向 (行) の出力を縦に繰り返しているからね。
順序を逆にするわかるけど、表示が崩れちゃう。
多重ループのときの break
多重ループしたときの break
は、その直近、つまり内側のループしか抜けられないので注意。
while (true) {
while (true) {
break;
}
// break したらここに来る
}
// このままだと無限ループだぁ
外側のループとかを抜ける方法は次の章でやるよ。
そういう処理はただのループでは向いてないはずだからね。