【Lua 筆記】迴圈 - part 4
===
目錄(Table of Contents):
[TOC]
---
由於有款遊戲叫做 CSO(Counter-Strike Online),內建模式創世者模式(Studio)新增使用 Lua 及其遊戲的 API,所以突發奇想製作這個筆記。
這個筆記會在一開始先著重純粹的程式設計自學,在最後的章節才會與 CSO 遊戲 API 進行應用。
迴圈(loop)
---
迴圈即一個循環。
很多時候我們會需要重複執行一個動作,以生活舉例,像是平時上廁所(無論小便、大便)會是一個迴圈,因為這是我們不斷持續在做的事情。又或者是在長跑時,跑了好幾圈操場,這也是一種迴圈。
回到正題,Lua 共支援以下幾種迴圈語法:
* while
* for
* repeat...until
* break
* goto
while、for 一定是每個程式語言基本配備,接下來讓我們先來看看 while 迴圈:
### while 迴圈
---
while 是一種具有條件判斷的迴圈,格式如下:
```lua=
while (condition) do
statements
end
```
當 condition 這個條件成立,也就是 condition = true 的時候,迴圈才會執行。
至於執行什麼內容呢?執行 statements 裡面的內容。如果裡面都沒有設定可以讓條件變成 false 的機制,則會形成一個無窮迴圈,就會一直循環下去。
condition 可以是任意的運算式。
```lua=
a = 10
while (a < 20) do
print("The value of a is:", a)
a = a + 1
end
```
輸出結果:
```
The value of a is: 10
The value of a is: 11
The value of a is: 12
The value of a is: 13
The value of a is: 14
The value of a is: 15
The value of a is: 16
The value of a is: 17
The value of a is: 18
The value of a is: 19
```
可以看到上面的程式碼當中,當 a < 20 它才會執行 while 裡面的內容,然後裡面有設定不斷累加的機制,使條件變成 false 後才能離開迴圈。
### 無限迴圈
---
無限迴圈即意味著一個迴圈指令判斷永遠都是 true。
```lua=
while (true) do
print("Hi")
end
```
輸出結果:
```
Hi
Hi
Hi
HI
....
```
備註:按下 ctrl + C 在終端上表示中斷執行結果。
### for 迴圈
---
for 迴圈的機制宛如等差數列,而以下是它的格式:
```lua=
for var=exp1,exp2,exp3 do
statements
end
```
這有點像 C 語言的寫法:
```c=
for (i; i < 10; i++){
statements
}
```
不過如果沒學過 C 語言的話,可以不用鳥這個東西。
exp1,是作為 var 的初始值,這邊要注意的是 var 是個變數,你想怎麼叫它都行,不過通常我們會用 i 來表示。
i 即 iteration,表示迭代,也就是重複的意思。
exp2,表示從 exp1 這個數值開始,要重複到 exp2 這個數值。
exp3,表示在當 exp1 重複到 exp2 的過程中,每次增加的數值,預設為 1,也可以不加 exp3。
看了這個解釋,如果你還是霧煞煞的話,我們來看個範例:
```lua=
for i=1,10 do
print(i)
end
```
輸出結果:
```
1
2
3
4
5
6
7
8
9
10
```
for 就是個等差數列,上面程式碼的意思就是從 1,遞增 1 直到 10 結束。
使用 while 迴圈可以這樣表達:
```lua=
i = 1
while (i <= 10) do
print(i)
i = i + 1
end
```
接下來我們來做個範例,從 2x1 ~ 2x10 的程式碼:
```lua=
for i = 1, 10 do
i = i * 2
print(i)
end
```
輸出結果:
```
2
4
6
8
10
12
14
16
18
20
```
### repeat...until
---
> for 和 while 迴圈的條件語句在目前迴圈執行開始時判斷,而 repeat...until 迴圈的條件語句在目前迴圈結束後判斷。
語法格式:
```lua=
repeat
statements
until( condition )
```
什麼意思?來看例子就知道([Lua repeat…until 循环 | 菜鸟教程](https://www.runoob.com/lua/lua-repeat-until-loop.html)):
```lua=
a = 10
repeat
print("a is :", a)
a = a + 1
until( a > 15 )
```
輸出結果:
```
a is : 10
a is : 11
a is : 12
a is : 13
a is : 14
a is : 15
```
欸?如果我們改用 while 迴圈寫的話會怎樣?我們一樣來試試看:
```lua=
a = 10
while (a < 15) do
print("a is :", a)
a = a + 1
end
```
輸出結果:
```
a is : 10
a is : 11
a is : 12
a is : 13
a is : 14
```
其實 Lua 語言的設計都很直觀,像是 repeat ... until,「重複直到」。以上面例子就是,a 不斷 + 1 直到 a > 15。
而前面所述 for、while 迴圈的判斷都在迴圈執行時就馬上判斷了,也可以從上面例子看出來。
程式語言連結:repeat ... until 其實像是 C 的 do ... while。
### break 語句
---
break 語句相當於打斷的意思,打斷什麼呢?打斷一個迴圈,所以它的功用就是能夠在迴圈途中打斷執行。
我們來做個範例:
```lua=
for i=1,10 do
print(i)
if i == 5 then
break
end
end
```
輸出結果:
```
1
2
3
4
5
```
可以發現原本迴圈要遞增至 10 才會結束,而使用判斷式判斷如果 i == 5,執行 break 語句,使整體迴圈馬上結束,接著繼續執行後續的程式碼。
### goto 語句
---
goto 語句是筆者認為 Lua 當中數一數二特別的語法,因為它能將控制流程無條件地轉到被標記的語句處。
什麼意思呢?待會解釋。
首先它的語法格式長這樣:
```lua=
goto Label
```
Label 的格式:
```lua=
:: Label ::
```
這個標籤後面可以放上要執行的程式碼,像是下面這個例子:
```lua=
::Label:: print("Hello")
goto Label
```
輸出結果:
```
Hello
```
再來做這個例子([Lua goto 语句 | 菜鸟教程](https://www.runoob.com/lua/lua-goto.html)):
```lua=
a = 1
::label:: print("--- goto label ---")
a = a + 1
if a < 3 then
goto label
end
```
輸出結果:
```
--- goto label ---
--- goto label ---
```
為什麼會輸出兩次?這是你我都會疑惑的問題,別忘了 goto 被執行時會「跳轉」到標籤的語句處,也就是程式碼將會在 `::label:: print("--- goto label ---")` 這邊開始重複執行,這就是 goto 神奇的地方了。
最後,我們做完這個例子就放學了([Lua goto 语句 | 菜鸟教程](https://www.runoob.com/lua/lua-goto.html)):
```lua=
for i=1, 3 do
if i <= 2 then
print(i, "yes continue")
goto continue
end
print(i, " no continue")
::continue::
print([[i'm end]])
end
```
輸出結果:
```
1 yes continue
i'm end
2 yes continue
i'm end
3 no continue
i'm end
```
因為 lua 當中沒有 continue 這個語句,但是我們可以透過 goto 來還原,同樣能達到 continue 的效果,只是稍嫌麻煩而已。
備註:[[i'm end]] 的原來寫法格式為 [[...]],為什麼要這樣寫?因為原本寫 print("i'm end") 是會發生錯誤的,因為一個字串裡面只能有兩個成對的單雙引號,而用這個兩個中括號的格式寫,就能夠容許有引號或任何字元的出現。
字元:"一個"中文字、符號、英文字母等等都稱為字元。
字串:一串字元的結合體。
另外,標籤不一定只能夠設定單一條程式碼而已,如下範例([Lua goto 语句 | 菜鸟教程](https://www.runoob.com/lua/lua-goto.html)):
```lua=
i = 0
::s1:: do
print(i)
i = i+1
end
if i>3 then
os.exit()
end
goto s1
```
輸出結果:
```
0
1
2
3
```
總結
---
迴圈就是一個循環,一個 circle。
Lua 共支援以下幾種迴圈語法:
* while
* for
* repeat...until
* break
* goto
while 是一個有條件判斷的迴圈:
```lua=
while (condition) do
statements
end
```
無限迴圈即意味著一個迴圈指令判斷永遠都是 true。
```lua=
while (true) do
print("Hi")
end
```
for 迴圈的格式:
```lua=
for var=exp1,exp2,exp3 do
statements
end
```
exp1 -> 初始值
exp2 -> 到哪個值停下
exp3 -> 等差數列的公差
repeat ... until 語法格式:
```lua=
repeat
statements
until( condition )
```
break -> 用於中斷迴圈執行的指令。
goto -> 能夠透過自定義的標籤,並且移轉到該標籤的地方,從此開始執行。
最後小提醒,雖然本篇沒有講到巢狀迴圈,但其實概念都是相同的,在這邊就不再贅述,備註:***巢狀迴圈比巢狀條件判斷還重要哦。***
參考資料
---
[【30天Lua重拾筆記15】基礎2: Label and Goto - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10245675)
[Day7 開機學習 Lua - 條件判斷與迴圈控制 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10264262)
[【30天Lua重拾筆記13】基礎2: 控制-for迴圈 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10244489)
[Lua 循环 | 菜鸟教程](https://www.runoob.com/lua/lua-loops.html)
[Lua while 循环 | 菜鸟教程](https://www.runoob.com/lua/lua-while-loop.html)
[Lua for 循环 | 菜鸟教程](https://www.runoob.com/lua/lua-for-loop.html)
[Lua repeat…until 循环 | 菜鸟教程](https://www.runoob.com/lua/lua-repeat-until-loop.html)
[Lua break 语句 | 菜鸟教程](https://www.runoob.com/lua/lua-break-statement.html)
[Lua goto 语句 | 菜鸟教程](https://www.runoob.com/lua/lua-goto.html)