CodeGym /課程 /JAVA 25 SELF /巢狀迴圈及其應用

巢狀迴圈及其應用

JAVA 25 SELF
等級 4 , 課堂 5
開放

1. 介紹

先問一個問題:為什麼要把一個迴圈放進另一個迴圈裡?因為我們的資料或任務常常不是單一直線,而是例如表格、網格,甚至多維結構。比方說,你想在螢幕上輸出乘法表、走訪二維陣列,或計算所有元素兩兩之間的交會。這裡只用一個迴圈顯然不夠——需要迴圈套迴圈。

在程式設計中,巢狀迴圈就像兩個鬧鐘:外層開始響,裡面又啟動另一個,只要外層還在響,內層就會一次次地響。也就是說,在每一次「外層」迭代期間,內層都會完整走一遍(並在每次外層迭代時不斷重複)。

一個好例子——小時與分鐘。小時是外層迴圈從 023,分鐘是內層迴圈從 059。外層每變動一次,內層都會把自己的所有取值跑過一遍。

2. 巢狀迴圈的語法

在 Java 中,巢狀迴圈的語法與一般迴圈沒有不同——你只要把一個迴圈寫在主體內的另一個迴圈裡即可。來看使用 forwhile 的範例:

// 外層 for 迴圈
for (int i = 0; i < 3; i++)
{
    for (int j = 0; j < 4; j++)  // 內層 for 迴圈
    {
        System.out.print(i + "," + j + " ");
    }
    System.out.println(); // 內層迴圈結束後換行
}

這裡外層迴圈控制變數 i(從 02),內層則是變數 j(從 03)。對於每個 i 的值,內層迴圈會完整走過從 j == 0j == 3。如果你執行這段程式,會看到一個漂亮的座標表:

0,0 0,1 0,2 0,3 
1,0 1,1 1,2 1,3 
2,0 2,1 2,2 2,3 

使用 while 的等效範例:

int i = 0;
while (i < 3)
{
    int j = 0;
    while (j < 4)
    {
        System.out.print(i + "," + j + " ");
        j++;
    }
    System.out.println();
    i++;
}

請注意:在外層迴圈的每一次執行期間,內層迴圈的變數(j)必須重新初始化,否則我們只會看到一行!

3. 巢狀迴圈的實作範例

範例 1:輸出西洋棋棋盤 (8x8)

就讓第一個任務——在螢幕上輸出經典的西洋棋棋盤,以黑白格表示(假設 「#」——黑格,「.」——白格)。使用巢狀 for 來實作:

for (int row = 0; row < 8; row++)
{
    for (int col = 0; col < 8; col++)
    {
        // 如果列與欄的索引和為偶數——該格是白色,否則為黑色
        if ((row + col) % 2 == 0)
            System.out.print("_");
        else
            System.out.print("#");
    }
    System.out.println(); // 每輸出一列後換行
}

結果:

_#_#_#_#
#_#_#_#_
_#_#_#_#
#_#_#_#_
_#_#_#_#
#_#_#_#_
_#_#_#_#
#_#_#_#_

重要提醒:巢狀確保對於每一列(row),我們都會完整走過所有欄(col)。沒有巢狀我們得不到棋盤的結構——只能得到單一列或單一欄。

範例 2:乘法表

這是巢狀迴圈的經典題!我們來輸出 1–9 的乘法表:

for (int i = 1; i <= 9; i++)
{
    for (int j = 1; j <= 9; j++)
    {
        System.out.print(i * j + "\t");
    }
    System.out.println();
}

格式 i * j + "\t" 會加入製表字元,讓表格看起來整齊。

結果:

  1   2   3   4   5   6   7   8   9 
  2   4   6   8  10  12  14  16  18 
  3   6   9  12  15  18  21  24  27 
  4   8  12  16  20  24  28  32  36 
...
  9  18  27  36  45  54  63  72  81 

4. 巢狀迴圈與其控制——一些細節

break 與 continue 在巢狀迴圈中的影響

很多新手會在這裡栽跟頭!如果你在內層迴圈使用 breakcontinue,它們影響僅限該內層迴圈。外層會照常執行。

範例:僅提前跳出內層迴圈

for (int i = 0; i < 3; i++)
{
    for (int j = 0; j < 5; j++)
    {
        if (j == 3)
            break; // 只跳出內層迴圈!
        System.out.print(i + "," + j + " ");
    }
    System.out.println();
}

結果:

0,0 0,1 0,2 
1,0 1,1 1,2 
2,0 2,1 2,2 

如果你需要同時跳出兩層巢狀迴圈(例如在表格中第一次匹配成功就要立刻結束搜尋),通常會使用旗標變數或特殊手法(例如 return——若一切發生在方法內)。

5. 巢狀迴圈的可視化

有時很難「看見」巢狀迴圈的執行順序。來看下面這張流程圖:

巢狀迴圈示意圖

以表格方式來看——當 i13j14 時,總共會有多少次迭代?

i j(對每個 i 逐一取值) 內層迴圈的迭代次數
1 1, 2, 3, 4 4
2 1, 2, 3, 4 4
3 1, 2, 3, 4 4
合計:3 × 4 = 12

6. 使用巢狀迴圈時的錯誤與陷阱

常見錯誤——內層迴圈變數初始化不正確。例如把它宣告在外層迴圈之外,卻沒有在每一步重設。結果內層迴圈可能完全不執行,或執行不正確。

int j = 0;
for (int i = 0; i < 3; i++)
{
    while (j < 4) // 糟糕!j 在第一次迭代後就可能已經等於 4 了。
    {
        System.out.print(i + "," + j + " ");
        j++;
    }
    System.out.println();
}

這裡的迴圈只會執行一次。請務必在外層迴圈初始化內層迴圈的變數!

另外,如果不小心寫出兩個巢狀迴圈使用相同的變數(for (int i = 0; ...) { for (int i = 0; ...) { ... } }),編譯器會抱怨:該變數已經被定義。

1
問卷/小測驗
迴圈,等級 4,課堂 5
未開放
迴圈
迴圈 while, for, do-while
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION