一、學習目標
重點
- 以表格/格子作直觀比喻,理解二維陣列的結構。
- 掌握列(row,橫向)與欄(col / column,縱向),並能用兩個索引定位元素。
- 能用
arr[row][col]存取或修改指定格子,並避免把 row/col 顛倒。 - 理解二維陣列的大小是列數 × 欄數,並能處理常見錯誤(索引越界、列長不一致)。
- 能使用雙重循環(nested loops)逐格掃描,完成計數、搜尋、條件檢查等任務。
二維陣列可理解為「清單中的清單」(list of lists):外層清單代表多列,而每一列本身又是一條清單,列內有多個元素(多欄)。
因此,每一個元素都需要兩個索引定位:row(列)與col(欄)。
在 Python 的 list-of-lists 中:
arr[row]:先取出第row列(得到一條一維清單)。arr[row][col]:再在該列內取第col欄的元素(得到某一格)。
所以,arr[row][col] 的閱讀方法是:「先找第幾列,再找該列的第幾欄」。
- 座位表:每格存放學生姓名或點名狀態。
- 棋盤:每格存放棋子(空 / X / O)。
- 迷宮地圖:每格存放地形(0=可走、1=牆)。
這些情境共同特徵:你一定會用到「第幾列 + 第幾欄」去描述一格的位置。
一維陣列:像一條清單,只需「第幾個」定位。
二維陣列:像一張表格,需要「列 + 欄」定位。
若資料天然是表格(例如:學生 × 測驗次數),用二維會更清晰;若資料只是順序清單(例如:10 次跳遠距離),用一維更直接。
- 顛倒 row/col:把「列」當成「欄」用,會取錯格,甚至越界。
- 索引越界(out of range):rows=3 時,合法 row 只有 0、1、2。
- 錯誤初始化:Python 寫
[[0]*c]*r會令多列共用同一條清單,修改一格會「連帶」改到其他列。
在日常生活中,我們經常接觸到「表格」:例如座位表、時間表、成績表、棋盤、像素圖像。二維陣列的用途,就是把這些「表格」用程式的方式表達出來,讓電腦可以逐格處理。
本頁會循序介紹二維陣列的概念、arr[row][col] 的讀法、大小(列數×欄數)、以及雙重循環逐格掃描。學到最後,你應該能把二維陣列套用到不同情境,並能自行寫出處理表格的程式。
二、概念引入:二維陣列是甚麼
重點
- 一維陣列像一條清單;二維陣列像一張表格。
- 二維陣列可以理解為由多個一維陣列組成(清單中的清單)。
- 每格要用兩個索引定位:row(列)與col(欄)。
在 Python 中,二維陣列通常用「list-of-lists」表示,例如:
外層清單有 2 列;每一列內有 3 欄。整體看起來就像 2×3 的表格。
把二維陣列想成「一列一列地排」:
arr[0]代表第 0 列(例如[10, 20, 30])。arr[1]代表第 1 列(例如[40, 50, 60])。
所以二維陣列最外層的索引(row)其實是「你要哪一列」。
若你要記錄 3 位同學、每人 2 次測驗分數:
- 用二維:
scores[row][col]清楚表示「第 row 位同學、第 col 次測驗」。 - 硬用一維:你要自己把(同學, 次數)轉換成單一索引,程式會更容易出錯。
規則矩陣:每一列的欄數相同(學習與處理都較容易)。
不規則清單:不同列的欄數不同(需要更小心處理)。
初學階段建議先使用規則矩陣,概念穩固後再接觸不規則情況。
arr[row][col] 其實是兩步:(arr[row])[col]。
補充:在 Python 的 list-of-lists 中,二維索引通常寫作 arr[row][col]。
有些偽代碼/教材會用 arr[row, col] 來表示二維索引(只是記法)。
但在 Python 一般 list(未用 NumPy)中,arr[row,col] 會被當成用一個 tuple 作索引,通常會報錯。
一維陣列可以想像成「一列清單」,例如分數清單、商品價格清單;只要用一個位置(第幾個)就能找到資料。
二維陣列則是「表格化」的清單:它由多列資料組成,而每列又有多欄。當資料天然呈現為表格(例如:座位表、棋盤、地圖、試算表)時,用二維陣列可以令資料結構更貼近問題本身。
三、為甚麼需要二維陣列
重點
- 當資料需要同時用兩個方向(列與欄)定位時,二維陣列最自然。
- 二維陣列令程式更容易寫出「逐格處理」:計數、搜尋、檢查。
- 若硬用一維存表格,往往要自行換算索引,較易出錯。
「表格式資料」的核心特徵是:每個資料點都必須用列 + 欄定位,例如座位表的「第 3 列第 2 欄」。
二維陣列天生支援這種定位:arr[row][col] 一眼就能看出你想取哪一格。
若把 2D 壓成 1D,你就要自己做換算:
一旦 cols 記錯、row/col 調轉,資料就會對不到。使用二維陣列可以把這些風險降到最低。
成績表天然是一個「學生 × 測驗」的表格。用二維陣列:
scores[row][col]:第 row 位同學、第 col 次測驗分數。- 要找某同學平均分:固定 row,走遍 col。
- 要找某次測驗最高分:固定 col,走遍 row。
一維也能存下所有分數,但程式會充滿索引換算:
- 你要記住 cols 代表甚麼。
- 你要不斷用公式把 (row, col) 轉成 index。
二維陣列雖然概念稍多,但換來的是可讀性、可維護性與較低的出錯率。
- 把二維當一維:只用單一索引走訪,導致漏格或錯格。
- 把列/欄顛倒:你以為固定某同學,其實固定了某次測驗。
- 以為二維一定是正方形:其實可為 2×5、3×7 等任何矩形。
很多問題本身就是「表格」:資料不是排成一條直線,而是有兩個方向可延伸。當你需要用「第幾列 + 第幾欄」去描述位置時,二維陣列能直接反映問題結構,程式也更容易閱讀。
此外,二維陣列非常適合配合雙重循環逐格處理。只要建立一個固定的掃描骨架,你便可以在表格上完成大量任務,例如統計、搜尋、判斷某一列是否全部符合條件等。
表格例子:成績表(3 位同學 × 3 次測驗)
| 測驗 0 | 測驗 1 | 測驗 2 | |
|---|---|---|---|
| 同學 0 | 72 | 68 | 80 |
| 同學 1 | 91 | 86 | 88 |
| 同學 2 | 60 | 73 | 70 |
若用二維陣列表示,這張表可寫成 scores[row][col]:row 代表「第幾列(哪位同學)」,col 代表「第幾欄(第幾次測驗)」。
Check Point 1:何時要用二維陣列?
重點
- 若資料天然是格子/表格,通常應考慮二維陣列。
- 若只是一條清單(只有一個方向),一維會更簡潔。
- 按情境判斷:座位表、棋盤、地圖 → 二維;分數清單、紀錄序列 → 一維。
選擇資料結構時,最重要是「貼近問題」。如果問題本身是表格(有列與欄),二維陣列最自然;反之若資料只是一條清單,一維更好。
問自己一條最直接的問題:我需要幾個索引才能定位一個資料?
- 只需 1 個(第幾個)→ 一維。
- 需要 2 個(第幾列 + 第幾欄)→ 二維。
座位表:每個座位要用 (row, col) 表示,適合二維。
分數清單:每人只有一個分數,只需用第幾個定位,適合一維。
二維陣列功能更強,但也帶來更多概念(列、欄、雙重循環)。如果問題不需要兩個方向的定位,用一維反而更清晰、更不易出錯。
有些資料雖然可以排成表格,但實際上只用到一個方向,例如「每月氣溫(12 個數)」:這其實是一條清單,不一定需要二維。
小測:何時要用二維陣列?
(載入中…)
四、結構理解:列(Row)與欄(Column)
重點
- 香港教材常用:Row(橫向)= 列;Column(縱向)= 欄。
- 二維陣列常用
arr[row][col]:先列(row),後欄(col)。 - 索引多數由 0 開始:第一列是 row=0,第一欄是 col=0。
列(Row):橫向排列,由左至右的一排格子。
欄(Column):縱向排列,由上至下的一列格子。
記法:「列橫、欄直」。
在 list-of-lists 中,外層清單是一列一列地排起來:
arr[row]先取出第 row 列(得到一條清單)。- 再用
[col]在該列中取第 col 欄(即其中一格)。
所以,arr[row][col] 的本質是:(arr[row])[col]。
如果某格位於第 2 列第 3 欄(以 0 起算),它的索引就是:
讀法:先找第 2 列,再在該列找第 3 欄。
在 Python、JavaScript 等語言中,索引多數由 0 開始:
- 第一列 → row = 0
- 第一欄 → col = 0
有些工具(例如試算表的列/欄標示)則是由 1 開始。寫程式時要留意你使用的索引系統。
- 語法寫了
arr[row][col],但心裡把 row 當欄、col 當列,邏輯就會錯。 - 最容易出錯的情況:固定「某同學」計算總和時,你可能固定了 col 而不是 row。
要處理二維陣列,第一步必須把「列」與「欄」分清楚。當你看到 arr[row][col],請把它理解成「先選一列,再選該列中的一欄」。
香港教材常見譯法是:Row(橫向)稱為「列」,Column(縱向)稱為「欄」。只要你在整個題目中保持一致,不論採用哪一種叫法,最重要都是弄清楚:哪一個索引代表哪一個方向。
表格例子:按格子顯示它的 row/col
請按任何一格,系統會顯示它屬於第幾列(row)及第幾欄(col)。
Check Point 2:arr[row][col] 的讀法與常見混淆
重點
arr[row][col]讀法:先列(row),後欄(col)。- 把 row/col 顛倒,最常見後果是取錯格或越界。
- Python 的 list-of-lists:通常用
arr[row][col]。 - 偽代碼/部分語言(或 NumPy 陣列):有時會見到
arr[row, col]這種記法(逗號代表同時提供兩個索引)。
在規則矩陣中,每個格子都唯一對應一組 (row, col)。只要 row、col 正確,你就能精準存取同一格。
arr[row][col] 是「先取一列清單,再取該列中的一欄」的兩步操作(list-of-lists)。
arr[row, col] 則常見於偽代碼/部分語言用來表示「二維索引」的記法;
但在 Python 一般 list(未用 NumPy)中,arr[row, col] 會被視為用一個 tuple 作索引,通常會報錯。
假設矩陣大小是 rows=3、cols=5:
- 正確:
arr[row][col],row 範圍是 0..2,col 範圍是 0..4。 - 顛倒:
arr[col][row],若 col=4,就會嘗試取第 4 列(越界)。
即使語法寫對(arr[x][y]),如果你把變數含義講反(把 x 當欄、y 當列),程式仍會取錯格。
所以,寫程式時要同時顧及:語法與變數含義。
row是某一列的索引;rows是總列數。col是某一欄的索引;cols是總欄數。
小測:arr[row][col] 的讀法
(載入中…)
五、基本操作:存取(讀取)與更新(修改)
重點
- 存取某一格:
value = arr[row][col]。 - 更新某一格:
arr[row][col] = newValue。 - 本節的表格會跟隨 Python 程式更新,讓你看到「改哪一格」的效果。
讀取:知道某格在 (row, col),就能取得該格的值。
修改:同樣指定 (row, col),把該格更新成新值。
二維陣列不只是靜態資料,它也常用來記錄「狀態」,並隨操作而改變,例如:
- 座位表:把某座位標記為「缺席」。
- 棋盤:把某格由空格改成玩家棋子。
- 地圖:把某格由「空地」改成「已走過」。
這是很常見的模式:先取出舊值,再用舊值計算新值,最後寫回去。
修改單格:直接指定 row 與 col。
修改整列:固定 row,用循環走遍 col。
修改整欄:固定 col,用循環走遍 row。
以下寫法會令每一列其實指向同一條清單:
結果:你修改 mat[0][0],其他列的第 0 欄也會一起改。正確做法是用 list comprehension 建立獨立的列。
二維陣列的「地址」是 (row, col)。一旦你能正確指出某格的位置,讀取與更新就只是兩行程式:讀取用 arr[row][col],修改則把它放在等號左邊。
為了把概念連到具體效果,本節提供一個可互動表格:你可以直接執行(或修改)Python 程式,表格會同步顯示目前的二維陣列內容,讓你觀察「改哪一格」會怎樣影響整張表。
互動示範:Python 修改二維陣列 → 表格同步更新
步驟:① 修改下面的 Python 程式(例如改某一格的值)→ ② 按 Run 程式 → ③ 觀察表格變化。
# 1) 建立二維陣列(列×欄)
arr ← [[10,20,30],
[40,50,60]]
# 2) 讀取:輸出第 0 列第 2 欄
輸出 arr[0][2]
# 3) 更新:把第 1 列第 1 欄改成 999
arr[1][1] ← 999
# 4) 輸出整個 arr(方便檢查)
arr[1][1] 改成其他座標,例如 arr[0][0] 或 arr[1][2],再觀察表格哪一格會改變。
六、大小與形狀:列數 × 欄數
重點
- 二維陣列大小可描述為:列數(rows)× 欄數(cols)。
- 合法索引範圍:
row = 0..rows-1,col = 0..cols-1。 - 列長不一致(不規則陣列)會增加處理難度;初學建議先用規則矩陣。
- rows(列數):外層清單有多少列(有多少條子清單)。
- cols(欄數):每一列有多少欄(每條子清單有多少元素)。
例如 3×4 表示 3 列、每列 4 欄。
索引由 0 開始,總數若是 rows,最後一個索引就是 rows-1;欄亦同理。
總格數 = rows × cols = 3 × 4 = 12 格。
但要注意:你寫程式時不是用 1..12 去定位,而是用 (row, col) 兩個索引定位每一格。
規則矩陣最適合初學:你可以假設每列欄數一樣,所以 cols = len(arr[0]) 成立。
若每列欄數不同,你就要在循環中用 len(arr[row]) 逐列處理,否則容易越界。
- 把
for row in range(cols)寫成外層,導致越界。 - 把上界寫成
range(rows+1),最後會跑到 row=rows(越界)。
理解二維陣列的大小,最直接的方法是把它當成一張表格:有多少列,就代表你可以用多少個 row 索引;每列有多少欄,就代表你可以用多少個 col 索引。
寫程式時,最常見錯誤就是「索引越界」。所以請牢記:總列數是 rows,但最後一列索引是 rows-1;總欄數是 cols,但最後一欄索引是 cols-1。
互動練習:輸入列數與欄數,生成一張表格
提示:按格子可查看其座標(row/col)。
Check Point 3:索引範圍與越界(out of range)
重點
- Python 的 list 索引通常由 0 開始(0-based)。
- rows 代表總列數,但合法 row 索引是
0..rows-1。 - 越界最常見原因:把上界寫成 rows 或 cols。
IndexError: list index out of range 表示:你嘗試用一個不合法的索引去取 list 的元素。
若一共有 rows 列:
- 第一列索引:0
- 最後一列索引:rows-1
欄亦同理。
如果你用 row=3,就等於取第 4 列,必然越界。
若題目保證輸入一定合法,你可以不做檢查;但在真實系統中,輸入未必可靠,越界檢查能避免程式崩潰。
row 是索引(位置),rows 是總列數。把兩者混淆會令 range 上界寫錯。
小測:索引範圍(避免越界)
(載入中…)
七、核心能力:雙重循環(Nested Loops)逐格掃描
重點
- 二維陣列最重要用途之一:用程式逐格處理整張表格。
- 最典型掃描骨架:外層走 row(列),內層走 col(欄)。
- 本節提供「Step 模式」:你可以逐步看到程式走到哪一格。
二維表格有兩個方向:列與欄。要走遍每一格,最常用方法是:
外層循環每次決定「現在處理哪一列」。內層循環則在同一列內由左至右走遍所有欄。
這就像閱讀:先讀完第一行,再讀第二行……(先列後列)。
- 計數:統計某個數字出現次數。
- 搜尋:找出第一個符合條件的位置。
- 檢查:判斷某一列是否全部通過(例如全為 0)。
逐列掃描(row-major):外層 row、內層 col(最常見)。
逐欄掃描(column-major):外層 col、內層 row(適合按欄統計時)。
- 外層用
range(cols),卻在內層用arr[row][col],容易越界。 - 寫成
arr[col][row],導致取錯格。
二維陣列的強大之處不只在於「可以存表格」,更在於「可以逐格處理表格」。只要你掌握雙重循環,就能用程式走遍整張表,完成大量重複工作。
很多題目其實都是同一套路:先用雙重循環逐格掃描,然後在循環內做條件判斷或累加。以下的 Step 模式示範,會把掃描過程可視化,幫助你真正理解程式是如何一格一格走過表格。
互動示範:逐格掃描(Step 模式)
步驟:① 按 Run 程式 產生掃描步驟 → ② 用「下一步」觀察掃描順序(目前所在格會以黃色標示)。
grid ← 3×4 的二維陣列(0/1)
steps ← 空清單
walls ← 0
for row = 0 到 rows-1
for col = 0 到 cols-1
把 (row, col) 加入 steps
若 grid[row][col] == 1
walls ← walls + 1
輸出 walls
Check Point 4:雙重循環的掃描順序
重點
- 最常見逐格掃描:外層 row(列),內層 col(欄)。
- 若要「按欄」統計,可改為外層 col、內層 row。
- 二維資料若不先轉換,通常需要雙重循環才能遍歷每一格。
外層循環控制你先固定哪個方向;內層則是在固定的情況下掃另一個方向。
若你想逐列處理(例如每列計算一個總和),外層用 row 最直觀;內層用 col 把該列所有元素走一次。
每列總和:外層 row、內層 col。
每欄總和:外層 col、內層 row。
兩種安排都可以遍歷全表,但思路不同:一種是「逐列」,另一種是「逐欄」。題目問你要計算甚麼,就選最貼近的寫法。
除非你把二維先轉成一維,否則只用單循環很難同時處理列與欄兩個方向。
小測:雙重循環掃描順序
(載入中…)
八、典型情境連結:二維陣列在現實中出現在哪裡?
重點
- 二維陣列最常見於格子化資料:座位表、棋盤、迷宮地圖、試算表、像素圖像。
- 同一個概念,可以在不同場景套用:每格都有 (row, col)。
- 理解情境有助你在題目中快速辨認「這其實是一張表格」。
不論你見到的是座位、棋盤、像素或地圖,只要每格都需要用兩個方向定位,就很自然會用到二維陣列。
你可以把二維陣列想成通用的「格子容器」:
grid[row][col]是最核心的存取方式。- 雙重循環是最核心的掃描方式。
不同情境,只是格子內容(數字/文字/狀態)不同。
- 座位表:統計缺席人數(掃描每格狀態)。
- 棋盤:判斷是否連成一線(掃描某幾條列/欄/斜線)。
- 迷宮:檢查某格是否牆/是否可走。
- 像素:把某種顏色改成另一種顏色(逐格替換)。
試算表的每一格也有地址,只是習慣用 A1、B2 這種表示法;而程式中則常用 arr[row][col]。
兩者概念一致:都是用「列 + 欄」定位一格。
學習時請把焦點放在「共通結構」:每格有座標、可逐格掃描。只要掌握結構,你就能快速把技能轉移到新題目。
要真正掌握二維陣列,你需要能把它「對應到現實中的表格」。以下提供五個常見情境的迷你模擬器:它們看似不同,但本質都是同一件事——用 (row, col) 表示一格,並在格子上存放狀態或數值。
你可以在不同情境之間切換,觀察每個模擬器背後的二維資料如何改變。特別留意:無論是座位、棋子、迷宮格、試算表格,或像素點,操作時其實都是在修改某一個 grid[row][col]。
座位表(每格存放姓名/狀態)
操作:先按格子選取座位,再在右邊輸入內容並按「更新此格」;這就相當於更新 seat[row][col]。
編輯選取座位
seat[row][col] = ...顯示二維陣列資料(seat)
棋盤(井字棋 3×3 示範)
操作:按空格落子(X / O 交替);每次落子就是更新 board[row][col]。
迷宮地圖(0=可走,1=牆)
操作:用「十字按鈕」移動玩家(🙂)。如果下一格是牆(1),就不能走;這就像檢查 maze[row][col] 是否可走。
顯示二維陣列資料(maze)
試算表(格子地址 A1…)
操作:先按格子選取,再在右邊輸入新數值並按「更新此格」;系統會顯示試算表地址(例如 B2)及對應的 arr[row][col]。
編輯選取格子
arr[row][col] = 新值顯示二維陣列資料(sheet)
像素圖像(每格存放顏色代號)
操作:先選擇顏色代號(0–4),再按格子上色;這等同修改 pixels[row][col]。
顯示二維陣列資料(pixels)
九、20 條偽代碼挑戰:偽代碼 → Python
重點
- 每題都有偽代碼、Python 編輯器、以及「核對答案」。
- 建議先寫讀入與建立矩陣,再寫雙重循環骨架,最後處理 if 條件。
- 遇到錯誤可用
print輸出中間結果(row、col、累加值)協助除錯。
挑戰題的目的不是背答案,而是訓練你把「表格思維」翻譯成程式:建立矩陣 → 逐格掃描 → 判斷與累加 → 輸出。
只要換一換 if 條件,你就能解到很多題。
大部分題目用逐列(外層 row、內層 col)已足夠;但若題目問「每欄」統計,請考慮外層 col、內層 row。
- 輸出格式:題目要求每列輸出一行、空格分隔,卻輸出成一行。
- 索引錯:row/col 顛倒,或 range 用錯 rows/cols。
- 初始化陷阱:用
[[0]*m]*n導致共享列(其中一題會特別測)。
以下 20 題已按難度由淺入深排列。每題都提供偽代碼與 Python 編輯器;你可以直接在頁面內撰寫程式並執行。若想快速檢查是否做對,可以使用「核對答案」。
建議做題流程:先根據偽代碼把輸入讀入與矩陣建立完成,再寫雙重循環骨架,最後才處理 if 條件與輸出格式。若核對失敗,可以暫時在循環內加入 print 輸出中間結果(例如目前的 row/col、目前累加值),找出哪一步與偽代碼不一致。
① 是否把
rows / cols 寫反?② range 的上界是否正確?③ 是否把 row/col 顛倒?④ 是否按題目要求輸出(換行/空格)?