【Lua 筆記】迴圈 - part 4

由於有款遊戲叫做 CSO(Counter-Strike Online),內建模式創世者模式(Studio)新增使用 Lua 及其遊戲的 API,所以突發奇想製作這個筆記。

這個筆記會在一開始先著重純粹的程式設計自學,在最後的章節才會與 CSO 遊戲 API 進行應用。

迴圈(loop)

迴圈即一個循環。

很多時候我們會需要重複執行一個動作,以生活舉例,像是平時上廁所(無論小便、大便)會是一個迴圈,因為這是我們不斷持續在做的事情。又或者是在長跑時,跑了好幾圈操場,這也是一種迴圈。

回到正題,Lua 共支援以下幾種迴圈語法:

  • while
  • for
  • repeat…until
  • break
  • goto

while、for 一定是每個程式語言基本配備,接下來讓我們先來看看 while 迴圈:

while 迴圈

while 是一種具有條件判斷的迴圈,格式如下:

1
2
3
while (condition) do
statements
end

當 condition 這個條件成立,也就是 condition = true 的時候,迴圈才會執行。

至於執行什麼內容呢?執行 statements 裡面的內容。如果裡面都沒有設定可以讓條件變成 false 的機制,則會形成一個無窮迴圈,就會一直循環下去。

condition 可以是任意的運算式。

1
2
3
4
5
a = 10
while (a < 20) do
print("The value of a is:", a)
a = a + 1
end

輸出結果:

1
2
3
4
5
6
7
8
9
10
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。

1
2
3
while (true) do
print("Hi")
end

輸出結果:

1
2
3
4
5
Hi
Hi
Hi
HI
....

備註:按下 ctrl + C 在終端上表示中斷執行結果。

for 迴圈

for 迴圈的機制宛如等差數列,而以下是它的格式:

1
2
3
for var=exp1,exp2,exp3 do  
statements
end

這有點像 C 語言的寫法:

1
2
3
for (i; i < 10; i++){
statements
}

不過如果沒學過 C 語言的話,可以不用鳥這個東西。

exp1,是作為 var 的初始值,這邊要注意的是 var 是個變數,你想怎麼叫它都行,不過通常我們會用 i 來表示。

i 即 iteration,表示迭代,也就是重複的意思。

exp2,表示從 exp1 這個數值開始,要重複到 exp2 這個數值。

exp3,表示在當 exp1 重複到 exp2 的過程中,每次增加的數值,預設為 1,也可以不加 exp3。

看了這個解釋,如果你還是霧煞煞的話,我們來看個範例:

1
2
3
for i=1,10 do
print(i)
end

輸出結果:

1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10

for 就是個等差數列,上面程式碼的意思就是從 1,遞增 1 直到 10 結束。

使用 while 迴圈可以這樣表達:

1
2
3
4
5
i = 1
while (i <= 10) do
print(i)
i = i + 1
end

接下來我們來做個範例,從 2x1 ~ 2x10 的程式碼:

1
2
3
4
for i = 1, 10 do
i = i * 2
print(i)
end

輸出結果:

1
2
3
4
5
6
7
8
9
10
2
4
6
8
10
12
14
16
18
20

repeat…until

for 和 while 迴圈的條件語句在目前迴圈執行開始時判斷,而 repeat…until 迴圈的條件語句在目前迴圈結束後判斷。

語法格式:

1
2
3
repeat
statements
until( condition )

什麼意思?來看例子就知道(Lua repeat…until 循环 | 菜鸟教程):

1
2
3
4
5
a = 10
repeat
print("a is :", a)
a = a + 1
until( a > 15 )

輸出結果:

1
2
3
4
5
6
a is : 10
a is : 11
a is : 12
a is : 13
a is : 14
a is : 15

欸?如果我們改用 while 迴圈寫的話會怎樣?我們一樣來試試看:

1
2
3
4
5
a = 10
while (a < 15) do
print("a is :", a)
a = a + 1
end

輸出結果:

1
2
3
4
5
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 語句相當於打斷的意思,打斷什麼呢?打斷一個迴圈,所以它的功用就是能夠在迴圈途中打斷執行。

我們來做個範例:

1
2
3
4
5
6
for i=1,10 do
print(i)
if i == 5 then
break
end
end

輸出結果:

1
2
3
4
5
1
2
3
4
5

可以發現原本迴圈要遞增至 10 才會結束,而使用判斷式判斷如果 i == 5,執行 break 語句,使整體迴圈馬上結束,接著繼續執行後續的程式碼。

goto 語句

goto 語句是筆者認為 Lua 當中數一數二特別的語法,因為它能將控制流程無條件地轉到被標記的語句處。

什麼意思呢?待會解釋。

首先它的語法格式長這樣:

1
goto Label

Label 的格式:

1
:: Label ::

這個標籤後面可以放上要執行的程式碼,像是下面這個例子:

1
2
::Label:: print("Hello")
goto Label

輸出結果:

1
Hello

再來做這個例子(Lua goto 语句 | 菜鸟教程):

1
2
3
4
5
6
7
a = 1
::label:: print("--- goto label ---")

a = a + 1
if a < 3 then
goto label
end

輸出結果:

1
2
--- goto label ---
--- goto label ---

為什麼會輸出兩次?這是你我都會疑惑的問題,別忘了 goto 被執行時會「跳轉」到標籤的語句處,也就是程式碼將會在 ::label:: print("--- goto label ---") 這邊開始重複執行,這就是 goto 神奇的地方了。

最後,我們做完這個例子就放學了(Lua goto 语句 | 菜鸟教程):

1
2
3
4
5
6
7
8
9
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
2
3
4
5
6
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 语句 | 菜鸟教程):

1
2
3
4
5
6
7
8
9
i = 0
::s1:: do
print(i)
i = i+1
end
if i>3 then
os.exit()
end
goto s1

輸出結果:

1
2
3
4
0
1
2
3

總結

迴圈就是一個循環,一個 circle。

Lua 共支援以下幾種迴圈語法:

  • while
  • for
  • repeat…until
  • break
  • goto

while 是一個有條件判斷的迴圈:

1
2
3
while (condition) do
statements
end

無限迴圈即意味著一個迴圈指令判斷永遠都是 true。

1
2
3
while (true) do
print("Hi")
end

for 迴圈的格式:

1
2
3
for var=exp1,exp2,exp3 do  
statements
end

exp1 -> 初始值
exp2 -> 到哪個值停下
exp3 -> 等差數列的公差

repeat … until 語法格式:

1
2
3
repeat
statements
until( condition )

break -> 用於中斷迴圈執行的指令。

goto -> 能夠透過自定義的標籤,並且移轉到該標籤的地方,從此開始執行。

最後小提醒,雖然本篇沒有講到巢狀迴圈,但其實概念都是相同的,在這邊就不再贅述,備註:巢狀迴圈比巢狀條件判斷還重要哦。

參考資料

【30天Lua重拾筆記15】基礎2: Label and Goto - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天

Day7 開機學習 Lua - 條件判斷與迴圈控制 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天

【30天Lua重拾筆記13】基礎2: 控制-for迴圈 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天

Lua 循环 | 菜鸟教程

Lua while 循环 | 菜鸟教程

Lua for 循环 | 菜鸟教程

Lua repeat…until 循环 | 菜鸟教程

Lua break 语句 | 菜鸟教程

Lua goto 语句 | 菜鸟教程