整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ
FizzBuzz for JavaScript

前言
FizzBuzz 其實是一個遊戲,而這個遊戲也被作為一個程式設計面試考題,尤其是 Google、Facebook 等這些大公司都會使用這個 FizzBuzz 來考驗應徵者的基本程式能力,因此這個遊戲也是一個很好的練習題目。
簡單認識一下 FizzBuzz
相信滿多人都聽過 FizzBuzz,就算不知道也沒關係,其實 FizzBuzz 是一個很簡單的數學遊戲,而這個數學遊戲也廣泛被使用在程式設計的面試中,所以如果你是一位求職者,我會非常推薦你要去了解什麼是 FizzBuzz,以及它的規則。
那麼 FizzBuzz 的規則如下:
- 如果這個數字可以被 3 整除,則輸出
Fizz - 如果這個數字可以被 5 整除,則輸出
Buzz - 如果這個數字可以被 3 與 5 同時整除,則輸出
FizzBuzz - 如果這個數字都不符合上述條件,則輸出這個數字
所以基於以上規則來講,玩法就會如下:
- 一群玩家圍繞起來
- 從指定的第一位玩家開始,第一位玩家說
1 - 第二位玩家接著說
2 - 第三位玩家時,第三位玩家要說
Fizz,而不是3 - 第四位玩家時,第四位玩家要說
4 - 第五位玩家時,第五位玩家要說
Buzz,而不是5
以此類推,當玩家說到 15 時,第十五位玩家要說 FizzBuzz,而不是 15。
以上就是 FizzBuzz 的規則。
FizzBuzz for JavaScript
那麼套用到程式語言中,常見的考題不外乎是以下:
「請建立一個 FizzBuzz 函式,當傳入一個數字時,請回傳符合 FizzBuzz 規則的結果,這邊將會傳入 1 到 100 的數字。」
1 | |
那麼透過上述考題以及 FizzBuzz 的規則,我們可以分析出幾個步驟:
步驟一:建立 FizzBuzz 函式
由於會傳入 1~100 的數字,代表著我們這邊會需要使用到迴圈,跑 1~100 的數字,因此我們會使用 for 迴圈來處理
1 | |

第一個步驟相對比較單純簡單,只需要建立一個 FizzBuzz 函式,並且使用 for 迴圈跑 1~100 的數字,這樣就完成了第一步驟。
步驟二:判斷是否為 3 的倍數
接著我們要判斷是否為 3 的倍數,當出現可以被 3 整除的倍數時,就要回傳 Fizz,那麼如何判斷是否為 3 的倍數呢?這邊就要使用到餘數運算子 %。
那麼什麼是 % 呢?% 叫做餘數運算子,使用方式很簡單,只需要 a % b,當 a 能被 b 整除時,則會回傳 0,否則會回傳餘數,舉例來講:
1 | |

那麼為什麼會回傳 2 呢?你可以想像成有五顆蘋果,然後要分給 3 個人,一開始一人一顆,接下來會剩下兩顆無法分,因此這兩顆就是餘數。
如果以計算公式來講,通常會區分成兩個部分,首先要先計算商數,然後再計算餘數:
- 商數:
5/3 = 1.6666666666666667,這邊會取整數部分,也就是1,代表蘋果一個人只能拿一顆 - 餘數:
5 - 3 x 1 = 2,這邊就是餘數,也就是剩下的蘋果
了解餘數的計算方式之後,讓我們回到 Fizz 的判斷上,當這個數字可以被 3 整除時,就要回傳 Fizz,這邊就要使用到餘數運算子 % 來判斷
1 | |

這時候有些人可能會寫一個錯誤判斷,也就是使用了 / 運算子來判斷
1 | |

當你傳入 3 時,你會發現結果是 Fizz,感覺似乎是正確的,但是當你傳入 6 時,你會發現還是出現了 6 而不是 Fizz,這就不符合 FizzBuzz 的規則,也就是可以被 3 整除時就要回傳 Fizz。
步驟三:判斷是否為 5 的倍數
接著我們要判斷是否為 5 的倍數,當出現可以被 5 整除的倍數時,就要回傳 Buzz,觀念與前面的 Fizz 一樣,只是改成 5 而已
1 | |

步驟四:判斷是否為 FizzBuzz
最後一個條件就是當這個數字可以被 3 與 5 同時整除時,就要回傳 FizzBuzz。
這邊其實會牽扯到一個觀念,也就是數學的最小公倍數,而最小公倍數就是兩個數字的倍數中最小的那個數字,有點難懂吧?讓我來舉例一下…
舉例來講,有兩個數字 3 與 5,那麼它們的最小公倍數就是 15,為什麼呢?讓我們看一下彼此的倍數:
3的倍數:3, 6, 9, 12, 15, 18, 21, 24, 27, 305的倍數:5, 10, 15, 20, 25, 30
反之,如果今天是 7 跟 4 的話,那麼結果就會是 28,因為…
4的倍數:4, 8, 12, 16, 20, 24, 287的倍數:7, 14, 21, 28
由此可知,我們可以看到 4 與 7 的最小公倍數就是 28。
理解最小公倍數的部分後,讓我們拉回到 FizzBuzz 的判斷上,當這個數字可以被 3 與 5 同時整除時,就要回傳 FizzBuzz,基本上在程式上就會使用到 && 邏輯運算子,也就是 AND 運算子,當兩個條件都符合時,才會執行。
有些人可能會躍躍欲試寫成了以下這種版本:
1 | |

雖然看似沒有錯,但其實這樣是有錯誤的,因為當你傳入 15 時,你會發現結果是 Fizz,而不是 FizzBuzz,這是因為程式是從上往下判斷,當 15 能被 3 整除時,就會回傳 Fizz,而不會再往下判斷是否為 FizzBuzz,所以正確的寫法是要先判斷 FizzBuzz,再判斷 Fizz 與 Buzz。
1 | |

這樣子就會是一個正確的 FizzBuzz 函式了。
TDD?
這邊突然插入一個 TDD 大家應該會感到混亂(笑)
首先 TDD 是什麼?TDD 全名是 Test-Driven Development,中文翻譯為「測試驅動開發」,簡單來講就是先寫測試,再寫程式碼,那麼為什麼突然提到這個呢?因為 FizzBuzz 就非常適合用來練習 TDD,當你寫完 FizzBuzz 函式後,你可以透過 TDD 來驗證你的程式碼是否正確,這樣子就可以確保你的程式碼是正確的。
除此之外,為了讓程式碼可以「被測試」,所以你的程式碼就必須要寫成可以被測試的程式碼,並且要符合單一職責原則,這樣子才能夠讓程式碼更加容易被測試。
TDD 練習
底下是一個最簡單的修改方式,也就是將結果改回傳陣列,並將結果都推到陣列中:
1 | |
但這一段程式碼再修改上其實並不容易,所以我們可以更抽象化一點,也就是將判斷的部分抽出來並優化不使用 else if,這樣子就可以讓程式碼更加容易被測試:
1 | |
還有呢?字串可不可以也抽出來?當然可以:
1 | |
那麼透過以上範例可以看到光 FizzBuzz 這個簡單題目就可以練到滿多東西的,其中包含了:
- 基本程式碼認知(如:
if判斷式、for迴圈、function宣告、return回傳、console.log輸出、&&邏輯運算子、%餘數運算子等) - 單元測試(TDD)
- 重構程式碼
- 抽象化程式碼
- 單一職責原則
- 了解最小公倍數觀念
透過上面我們就可以知道,為什麼 FizzBuzz 這個簡單的題目可以被廣泛使用在面試中,因為它可以讓面試者了解到面試者的基本程式能力,以及面試者是否有能力將程式碼寫得更加優化哩~
整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ