# ch05 — 入れ子ループ

Source: https://php-school.pages.dev/topics/loop/ch05-nested/
Site: AIと学ぶPHPの学校 (https://php-school.pages.dev)
Lesson: 繰り返し
Level: L2

Reference (official): https://www.php.net/manual/ja/control-structures.for.php

## 本文

# ch05 — 入れ子ループ

## 概要

ループは **入れ子** にできる。`for` の中にもう 1 つ `for` を書くと、外側が 1 回回るたびに内側のループが最初から最後まで全部回る、という二重構造になる。これは「**表のような 2 次元データ**」を扱うときに必須のテクニックで、九九表 (9 行 × 9 列)、星のピラミッド (行ごとに違う数の `*`)、行列演算、画像のピクセル走査など、現実のプログラミングで出てくる場面は数えきれない。

文法的には外側のループのカウンタを **`$i`**、内側を **`$j`** にする慣習がある。これは「i と j で区別がつきやすい」「**両方とも `$i` だと内側が外側のカウンタを破壊して** バグになる」という実害から来ている。3 重ループになれば `$k`、それ以上は名前を意味のあるもの (`$row` / `$col` / `$layer` 等) に切り替える、と段階的にスケールしていく。

入れ子で必ず意識すべきが **計算量** だ。外側が N 回・内側が M 回回るループは、本体が合計 **N × M 回** 実行される。N = M = 1000 なら 100 万回、10000 なら 1 億回。N が増えるほど一気に重くなるので、「これは本当に N × M 必要か」「片方は N 回で済まないか」を常に問う癖が、後の配列・アルゴリズムの章で効いてくる。入れ子ループは強力だが、雑に書くと簡単に重いコードになるという両刃の剣だと覚えておくと良い。

## 学習目標

- ループの中にループを書ける
- 内側のループが「外側 1 回ごとに最後まで回る」と理解する
- 表 (行 × 列) や図形を出力できる

## 所要時間

スライド 5 分 + ドリル 2 問 = **20 分**

## ドリル

| no | 内容 |
|---|---|
| 01 | 1×1 から 9×9 までの九九表 (81 行) を出力 |
| 02 | 入力 N で N 段の星 (*) のピラミッドを出力 |

## 採点

```bash
php scripts/grade.php topics/loop/ch05-nested/drill/01-multiplication-table/
```

## 関連チャプター

- [`ch01-for`](../ch01-for/) — 単一の `for` (このチャプターの前提)
- [`ch04-break-continue`](../ch04-break-continue/) — 入れ子内での `break` 挙動
- [`ch06-loop-with-input`](../ch06-loop-with-input/) — 入れ子で 2 次元データを読み込むパターン

## スライド

---
marp: true
theme: dojo
paginate: true
size: 16:9
---

<!--
LLM_CONTEXT:
  Lesson 3 / Chapter 5
  目的: ループの中にループを書く (入れ子) パターンを書けるようにする
  扱わない: 標準入力ループ (ch06) / 配列 (後続章)
  読み上げ時間目安: 4 分半〜5 分
-->

# 入れ子ループ

Lesson 3 / Chapter 5

---

## ループの中にループを書ける

```php
<?php
for ($i = 1; $i <= 3; $i++) {
    for ($j = 1; $j <= 3; $j++) {
        echo "$i-$j ";
    }
    echo "\n";
}
```

実行結果:

```
1-1 1-2 1-3
2-1 2-2 2-3
3-1 3-2 3-3
```

---

## 動きを 1 ステップずつ追う

```php
for ($i = 1; $i <= 3; $i++) {        // 外側
    for ($j = 1; $j <= 3; $j++) {    // 内側
        echo "$i-$j ";
    }
    echo "\n";
}
```

- 外側 `$i = 1` の間に、内側 `$j` が 1→2→3 と全部回る
- 内側が終わったら外側が `$i = 2` に進む
- 内側がまた 1→2→3 と回る
- これを `$i = 3` まで繰り返す

→ 内側ループは **外側 1 回ごとに最後まで** 回る。

---

## 行 × 列の表を作る

```php
<?php
for ($i = 1; $i <= 9; $i++) {
    for ($j = 1; $j <= 9; $j++) {
        echo $i * $j . " ";
    }
    echo "\n";
}
```

- 外側 = 行
- 内側 = 列
- 内側ループの後ろに `echo "\n";` を入れて改行

九九表のような格子状の出力は入れ子ループの定番。

---

## 図形を描く: 星のピラミッド

```php
<?php
$n = 4;
for ($i = 1; $i <= $n; $i++) {
    for ($j = 1; $j <= $i; $j++) {
        echo "*";
    }
    echo "\n";
}
```

実行結果:

```
*
**
***
****
```

- 外側 `$i` が「行数」を決める
- 内側 `$j` が `$i` 回まで回るので、星の数が行ごとに増える

---

## 内側の条件は外側の変数を使ってよい

ピラミッドの例で見た通り:

```php
for ($i = 1; $i <= $n; $i++) {
    for ($j = 1; $j <= $i; $j++) {  // ← 外側の $i を使っている
        echo "*";
    }
    echo "\n";
}
```

- 外側の `$i` は内側からも見える
- 内側の回数を外側の値で変えられる

---

## このチャプターでできるようになること

✅ ループの中にループを書ける
✅ 内側ループが外側 1 回ごとに最後まで回ると分かる
✅ 行 × 列の表を出力できる
✅ 外側の変数を内側の条件に使える

→ ドリルへ
