JavaScript CSS3

Javascript 動態網頁程式設計 - 上課教材

動畫互動網頁程式設計 > 課程內容 > 第 05 章 - 使用 for, while 等進行迴圈與控制

第 05 章 - 使用 for, while 等進行迴圈與控制

上次更新日期 2020/10/05

前一章節討論了邏輯判斷,然後以 if 或 switch 的方式來處理邏輯的『真』與『假』的判斷。那如果需要進行多次判斷呢? 那如果需要進行多次重複的動作呢?那如果需要進行某些次數的累加而進一步處理的任務呢?這就需要所謂的『迴圈』功能了。 單純的迴圈可以透過 for 這個功能,如果是透過條件判斷的迴圈,則可以使用 while 來協助。

學習目標:

  1. 了解 for 迴圈是精準固定次數的迴圈
  2. 了解 while 迴圈是某條件成立下才會進行的迴圈
  3. 了解 do, while 迴圈是至少一定會進行一次的迴圈

5.1: 使用 for 進行迴圈設計

某些時刻我們需要『重複』進行某件事情,如果你重複兩三次程式碼,可能還覺得沒什麼了不起,但是,如果你需要的是幾十次、幾百次重複的程式碼, 並且需要 (1)指定固定的次數或者是 (2)需要某個情境下才結束(或開始)某個持續不斷的程式碼,這個時候,你不能使用撰寫多次程式碼的方式, 而是需要透過『使用迴圈來執行某些個特定的程式碼』,這樣的想法才合理。例如底下的流程:

迴圈執行示意圖

你可以發現圖示的箭頭中,當某條件持續成立時,就會持續不斷的運作右側的程式,直到條件失敗為止,這就是迴圈了。 JavaScript 通常可以使用兩種方式來執行迴圈,分別是:

  • 使用 for 來精準的進行某些次數的迴圈
  • 使用 while 來進行某條件的迴圈 (次數可能不固定)

我們先來介紹簡單的 for 迴圈,for 迴圈的基本語法有點像底下這樣:

for ( 變數初始值; 條件運算式; 變數變化步階) {
	procedure ...
	...;
}

// 例如底下的範例,從 0 到 99 之間的執行順序
var i;
for ( i = 0; i < 100; i++ ) {
	....
}

第四章我們談到擲骰子時,那時有固定需要 3 個骰子,如果現在我們提供使用者自行指定骰子的數量時, 因為骰子的數量不固定了,此時,你就得要根據骰子數量來處理亂數的取得次數啊!不過,如果讓使用者以輸入數值的方式來處理, 類似 input type='text' 的 UI 設計時,使用者如果輸入非數值的字元,那要分析就很討厭!我們想要使用方向鍵按鈕來搞定它, 似乎可以這樣做:

例題 5-1-1:使用按鈕來決定數值的變化,針對 UI 的設計想法
  1. 建立名為 unit05-1-1.php 的新檔,並在 index.php 裡面加上相關的超連結,target 指向 js 視窗。
  2. 這個檔案的內容 貼到 unit05-1-1.php 檔案內,同時查看一下網頁顯示的內容, 並且了解一下各按鈕的功能設計依據。
  3. 設計名為 goup() 的函數,該函數主要的目的在讓骰子數量『增加』,所以,該函數的功能大致上是:
    • 先取得 mynu 那個 ID 的元素控制,假設此元件為 myobj 好了
    • 設計一個變數,假設為 mynu 好了,該變數可以取得 myobj.value 之外,並且需要轉成數值格式
    • 讓 mynu +1
    • 判斷 mynu 的數值,若 mynu 大於等於 10 的時候,將 mynu 直接指定為 10
    • 最終將該數值回傳給 myobj.value
  4. 同理,設計讓骰子數量下降的 godown() 函數,且骰子數量不得低於 3 喔!
設計 UI 畫面,讓骰子數量可以增減

處理了避免使用者發傻的數值情境之後,接下來則是處理迴圈的事項!先來設計電腦的骰子,按下骰子之後,整個程式會先讀取骰子數量, 再根據骰子的數量來決定迴圈的次數啊!

例題 5-1-2:開始使用迴圈擲骰子
  1. 將 unit05-1-1.php 另存新檔為 unit05-1-2.php,並在 index.php 裡面加上相關的超連結,target 指向 js 視窗。
  2. 設計名為 pcgo() 的函數,這個函數就是透過分析骰子的數量,然後給予擲骰子的次數行為:
    • 取得骰子數量,並且必需要是『數值』才可以,假設此變數為 mynu
    • 因為我們需要改變元素內容,所以,先以 myobj1 取得 pcnum 的元素,以 myobj2 取得 pcall 的元素
    • 宣告 i, j 變數,預計用來設計迴圈,宣告 count=0 ,預計用來設計骰子加總,宣告 mymsg = "",預計用來設計所有骰子的結果彙整
    • 使用 for 迴圈,假設 i 初始值為 1 ,且步階為 i++,設計此迴圈的條件!
      • 以 j 作為變數取得骰子數值的判斷
      • 將 count 累加 j 這個數值
      • 將 mymsg 累加 j 以及 <br /> ,讓骰子的點數可以持續累加到 mymsg 中
    • 最後,將 myobj1, myobj2 以上述的結果取代,就可以得到我們需要的點數了!
  3. 同理,設計使用者擲骰子的 mygo() 函數喔!
使用 for 擲骰子
  • 巢狀迴圈設計

有很多時候,迴圈不是一層而已,可能迴圈裡面還有迴圈,這就是雙層迴圈啦!那麼如何測試雙層迴圈呢?最簡單的方法,就是透過製作 9X9 乘法表啦! 因為 9X9 乘法表,就得要透過兩層 1~9 的互相乘法來處理才行啊!

例題 5-1-3:使用巢狀迴圈處理 9X9 乘法表
  1. 新建檔案 unit05-1-3.php,並在 index.php 裡面加上相關的超連結,target 指向 js 視窗。
  2. 這個檔案內容 放入 unit05-1-3.php 檔案內,並且觀察一下檔案的樣式
  3. 設計名為 go99() 的函數,這個函數會使用到兩層迴圈:
    • 第一層迴圈使用 i 從 2 到 9 (因為 1 不太需要理他) 設計
    • 第二層迴圈使用 i 從 1 到 9 設計,並且在第二層迴圈使用如下的方式指定訊息累加:
      res=res+i+ " x " + j + " = " + (i*j) + "<br />";
  4. 將 res 的結果丟進 div 的內部 HTML 環境下。
巢狀迴圈

上面的案例只是將結果列出來而已~顯示的效果當然是很糟糕!如果你將每個第一層迴圈的開始與結束,都加上 div 的話,那麼就能夠隔出 8 個 div 了! 同時,將 div 加入 display: inline-block 的話,就能夠處理的比較完美!請依據這個想法,設計出 5-1-4.php 的內容。

例題 5-1-4:加上一點點 UI 的設計
  1. 將 unit05-1-3.php 另存為 unit05-1-4.php,並在 index.php 裡面加上相關的超連結,target 指向 js 視窗。
  2. 如上的說明,請加入 div 的樣式,同時自己處理 CSS 的樣式表,看看情況會變如何!

巢狀迴圈

請前往課後作業查看第一題,看看你能不能設計出三層迴圈的網頁安全色!

5.2: for 迴圈的數值應用

其實迴圈還挺常應用於數值計算中!舉個例子來說,你想要判斷一個數值它是不是『質數』,所謂的『質數』指的是『因數只有自己跟 1 』的意思。 例如 5, 7, 11, 13 等等。那怎麼算出質數呢?假設一個數值為 num 好了,那麼我讓它從 2~(num-1) 取餘數,如果為 0 ,就是可以被某個數整除, 那就代表不是質數。如果一直找不到,那就代表這個數是質數!

不過你得知道,事實上不用取 2~(num-1) 這麼多數值,只要從 2 到 (該數 num 的平方根 +1) 當中去找餘數即可! 另外,在 javascript 裡面,找平方根的方法後,進行無條件進入 (就不用+1了) 的方式為:

  • 取平方根且無條件進入:Math.ceil(Math.sqrt(num))
  • 取餘數: A%B
  • 判斷是不是數值: isNaN(num)
例題 5-2-1:判斷質數
  1. 建立 unit05-2-1.php,並在 index.php 裡面加上相關的超連結,target 指向 js 視窗。
  2. 這個檔案的內容 貼到 unit05-2-1.php 檔案內,同時查看一下網頁顯示的內容,
  3. 建立名為 gosee() 的函數,函數內容在取得使用者輸入的資料,判斷為數值之後,才加以計算是否為質數:
    1. 取得 num 變數,內容為 num 元素的 value,且已經轉成整數
    2. 判斷是否為非數值 (isNaN),若為非數值,就顯示錯誤!
    3. 承上,如果是數值,但是小於等於 10 的話,就顯示需要大於 10 以上的數據
    4. 再承上 (用 if, else if, else 等),確認是大於 10 的數據後:
      • 先指定一個字串變數,內容為『是質數』;
      • 取得平方根之後,從 2 到平方根數據,去處理迴圈:
      • 計算餘數,如果等於 0 的話,就顯示不是質數,然後跳脫迴圈 (break)
    5. 將最終的結果帶入 res 元素的 innerHTML 當中!
找尋質數 找尋質數 找尋質數 找尋質數

請前往作業處,看看能不能變形成為找出最接近的質數?可能也是需要設計雙重迴圈喔!

5.3: while 迴圈的應用

while 迴圈透過一個條件判斷來決定是否要進行迴圈的設計,與 for 固定次數的迴圈並不相同。不過,即使語法不太一樣, 事實上,概念是相同的。while 迴圈的語法是這樣:

while (條件成立時) {
	程式碼...
}

另外,你可以透過兩個控制方式來調整迴圈的運作:

  • continue:直接跳到下一次迴圈的開始處,本次迴圈的後面程式碼都不執行;
  • break:直接離開 while 迴圈。

在開始底下的題目之前,先來理解一下,當 10 進位要轉成 16 進位的資料時,你可以怎麼做呢?最簡單的作法, 就是透過 X.toString(16) 這樣的設計來處理即可!

例題 5-3-1:使用 while 迴圈來設計 1~15 之間的數字三角形習題 (事實上 for 比較好算!不過,我們用 while 處理)
  1. 建立名為 unit05-3-1.php 的新檔,並在 index.php 裡面加上相關的超連結,target 指向 js 視窗。
  2. 這個檔案的內容 貼到 unit05-3-1.php 當中,並先查看一下網頁結果
  3. 以 unit05-2-1.php 的部份內容為主,拿出 javascript 的資訊,然後帶入防呆 (非數字、不在數值規範內) 的結果。
  4. 在可用的範圍內,規定兩層 while 迴圈,第一個迴圈開始前,規範 i 值為 1,然後;
    • 條件判斷為 i <= num 才對喔!
    • 強迫下一個迴圈的 j 值為 1
    • 規範 x 為 i.toString(16); 的呈現結果
    • 進入第二層 while 迴圈
      • 條件判斷為 j <= i 才對喔!
      • 設定一個變數,假設為 msg,這個 msg 需要累加 x 值
      • j 加1
    • i 加1
    • msg 加上斷行 (br)功能
  5. 讓 res 的 innerHTML 為 msg 的結果。
  6. 最終呈現讓人很不滿意,請依據自己的判斷,修改 CSS 數值 (line-height, letter-spacing, font-family...)
數字三角形用 while 的結果

上面的題目其實與固定迴圈數量有關,因此使用 for 迴圈看起來似乎會更快些。不過,使用 while 迴圈也不算太慢! 現在,讓我們來使用迴圈抽取上台報告的號碼吧!

  • 抽抽樂,抽出上台的座號

假設我們需要報告人上台,但是大家都不願意上來,怎辦?沒關係,用抽籤的!底下這個動作可以抽出數個人出來, 只是,只有大致上的防呆效果,沒有重複人的防呆效果~參考看看:

例題 5-3-2:使用 while 迴圈來設計上台的報告者順序
  1. 建立名為 unit05-3-2.php 的新檔,並在 index.php 裡面加上相關的超連結,target 指向 js 視窗。
  2. 這個檔案的內容 貼到 unit05-3-2.php 當中,並先查看一下網頁結果
  3. 以 unit05-3-2.php 的部份內容為主,拿出 javascript 的資訊,然後帶入防呆的設計:
    • 若為非數字,則回傳 false 結束
    • 若 nustart >= nuend ,代表開始號碼比較大,不合理,所以回傳 false 結束
    • 若 nuall >= (nuend-nustart) ,代表抽出的個數比所有個數還要大,回傳 false 結束
  4. 建立 goto() 函數,內容大致上是這樣的:
    • 以變數 (例如 j) 取得亂數結果,例如:
      Math.floor(Math.random() * (nuend - nustart + 1)) + nustart
    • 使用清單的方式加以累加數值
    • 做 i++
  5. 讓 res 的 innerHTML 為 msg 的結果。
抽籤的結果
  • 抽抽樂,抽出上台的座號:用 do 搭配的 while 迴圈,會變怎樣?

上面的案例中,鳥哥故意不做一個抽出個數為 0 的防呆,所以當你在上面的案例中,最底下一欄填寫為 0 時,就會發現沒有任何訊息喔! 因為 while 判斷了 1 不可能小於等於 0 ,於是就放棄 while 的運作了。那怎辦?如果要讓迴圈『至少一定要做一次』的情境下, 可以使用 do 迴圈:

do {
	程式碼...
} while (條件成立時)

while 變成在下方,意思是, do 過一次之後才開始進行條件判斷!所以這種迴圈一定會做一次以上!不會是 0 次迴圈!

例題 5-3-3:使用 do, while 迴圈來設計上台的報告者順序
  1. 將 unit05-3-2.php 另存新檔為 unit05-3-3.php ,並在 index.php 裡面加上相關的超連結,target 指向 js 視窗。
  2. 將 while 迴圈改以 do, while 迴圈取代,最終結果應該會與上一個例題相同。不過,最後一個欄位可以填入 0 喔! 還是會至少抽出一個報告者。

5.4: 課後作業

  • 第一題:製作網頁安全色的展示

與 9x9 乘法表類似的方式,如果要進行網頁安全色的展示時,該如何設計呢?所謂的網頁安全色,指的是以前的螢幕比較無法順利產生顏色時, 在網頁上面不容易出錯的顏色色碼。網頁安全色如果以 rgb 的函數來展示時,由 0 ~ 255 之間以 51 為倍數來作為顏色的展示, 即是所謂的網頁安全色。因為 rgb() 函數有三個數值,例如:『 rgb(0,0,0), rgb(0,0,51), rgb(0,51,51)...』等,所以可能會有 3 層迴圈展示。 請依據你的想法來設計出這個三層迴圈的網頁安全色展示。底下圖示為可能的範本: (沒有標準答案),建議:

  • 使用表格 (table) 來處理會比較漂亮些
  • 表格內部的 td 的 CSS 加上底色 (background-color) 搭配字體顏色為補色
網頁安全色的結果
  • 第二題:利用變形,找最近的質數

在 5-2-1 找出質數的案例中,過程似乎不太有趣!因為,我們很難去猜測質數啊!那可不可以換個角度, 讓你輸入一個數值,然後,讓程式自動去 num, num-1, num-2...去取得最接近這個數值的質數呢? 只是可能要變成雙重迴圈。第一個迴圈從數值的大到小去搜尋,第二個迴圈則針對第一個迴圈的數值去判斷是不是質數。

找尋最接近的質數