###### tags: `CPP` `Arduino` # 09 利用多維陣列結合相關資料 如果不只是亮度要不規律的變化, 連時間也要隨意變化, 例如先稍微亮 0.5 秒、再暗一些 1 秒, 最後全亮 0.2 秒, 可以比照亮度的做法, 另外再定義一個陣列, 紀錄對應時間的亮暗切換次數, 像是這樣: ```cpp= const int duration = 100; // 單次亮/熄時長 (us) const int led_pin = 5; // 內建 LED 腳位 const int levels[3] = {30, 5, 100}; // 亮燈時長 const int totals[3] = {5000, 10000, 2000}; // 亮/熄切換次數 void twinkle(int led_pin, int duration, int duration_on, int total) { for(int count = 0;count < total; count++) { digitalWrite(led_pin, LOW); delayMicroseconds(duration_on); digitalWrite(led_pin, HIGH); delayMicroseconds(duration - duration_on); } } void setup() { pinMode(led_pin, OUTPUT); } void loop() { for(int i = 0; i < sizeof(levels)/sizeof(int); i++) { twinkle(led_pin, duration, levels[i], totals[i]); } } ``` 第 4 行的陣列就是對應第 3 行陣列的切換次數, 重新上傳程式後就可以看到不同亮度持續時間都不同的效果。 結果雖然正確, 不過卻有個潛在的問題, 因為兩個陣列是分開的, 就可能會發生想增加亮度變化的層次, 但卻忘了在 `totals` 陣列新增對應的切換次數。要解決這個問題, 可以使用**多維陣列 (multidimentional array)**。 ## 由陣列構成的陣列 你可以把多維陣列想成是由陣列構成的陣列, 也就是陣列中的每一項資料自己也是一個陣列, 例如: ```cpp int led_info[3][2]; ``` 這表示 `led_info` 是一個內含 3 項資料的陣列, 其中的每一項資料都是一個內含 2 項資料的陣列, 也就是說 `led_info` 總共內含 3×2 共 6 項資料。如果要定義多維陣列的內容, 可以用多層的大括號形式, 像是這樣: ```cpp int led_info[3][2] = { {30, 5000}, // 相當於 led_info[0] {5, 10000}, // 相當於 led_info[1] {100, 2000} // 相當於 led_info[2] }; ``` 內層的一對大括號就對應到陣列的一項資料, 你可以看到這每一項資料自己又是一對大括號定義的陣列。如果要取得最內層陣列的資料, 就要使用兩次中括號, 像是這樣: ```cpp led_info[0][1] // 取得 5000 led_info[1][0] // 取得 5 ``` 像是這樣的陣列我們就稱它為 **2 維陣列**, **第 1 個維度**有 3 項資料, 每 1 項資料自己又是 1 個 1 維陣列, 這稱為**第 2 維**, 存放宣告陣列時標示型別的資料。多維陣列並不限於 2 維, 若有需要, 還可無限延伸。 如此我們就可以改寫剛剛使用兩個單獨陣列的程式, 把亮燈時長和亮/熄切換次數整合在單一個多維陣列了: ```cpp= const int duration = 100; // 單次亮/熄時長 (us) const int led_pin = 5; // 內建 LED 腳位 const int led_info[3][2] = { {30, 5000}, // 亮燈時長與亮/熄切換次數 {5, 10000}, // 亮燈時長與亮/熄切換次數 {100, 2000} // 亮燈時長與亮/熄切換次數 }; void twinkle(int led_pin, int duration, int duration_on, int total) { for(int count = 0;count < total; count++) { digitalWrite(led_pin, LOW); delayMicroseconds(duration_on); digitalWrite(led_pin, HIGH); delayMicroseconds(duration - duration_on); } } void setup() { pinMode(led_pin, OUTPUT); } void loop() { for(int i = 0; i < sizeof(led_info)/sizeof(led_info[0]); i++) { twinkle(led_pin, duration, led_info[i][0], led_info[i][1]); } } ``` 1. 第 3~7 行就是剛剛舉例的陣列, 其實就是把前面例子中的兩個陣列內容整合在一起, 分別是三種亮度的亮燈時長與亮/熄切換次數。 2. 第 23 行我們使用陣列本身的大小與陣列第 1 項資料的大小來計算多維陣列中第 1 維的資料數量。 3. 第 24 行就改用取多維陣列中第 2 維陣列內的資料作為參數。 上傳後和原本的程式效果一樣。