7.Swift教程翻譯系列——控制流程之迴圈

來源:互聯網
上載者:User

英文版PDFhttp://download.csdn.net/detail/tsingheng/7480427

Swift提供了類C語言類似的控制流程結構。包括for迴圈和while迴圈來多次執行任務,if和switch語句根據不同的條件執行不同的分支代碼,break和continue語句將執行流程跳轉到其他語句。

除了C裡面傳統的for-條件-遞增迴圈,Swift還增加了for-in迴圈使得遍曆數組,字典,範圍,字串或者其他序列都很簡單。

Swift的switch語句也要比C語言的switch更強大。Swift裡面某個case語句執行完以後不會再去執行後面的case,避免C語言中由於忘記寫break而引起的錯誤。case可以匹配多種不同的類型模式,包括範圍匹配,元組或者某個特定的類型(casts to a specific type)。case當中被匹配的值可以與臨時常量或者變數綁定以便在case裡面可以使用,複雜的匹配條件可以使用where來表示。

1.for迴圈

for迴圈反覆執行語句指定次數。Swift提供兩種形式的for迴圈:

  • for-in在某個範圍,序列,集合或者系列中對每個元素執行一次。
  • for-condition-increment反覆執行直到滿足某個特殊條件,一般在每次迴圈之後計數器遞增。

for-in

你可以使用for-in迴圈來遍曆集合的元素,比如一個範圍的數字,某個數組中的元素或者字串中的字元。

下面的例子輸出乘法表中乘5的那一行:

for index in 1...5 {    println("\(index) times 5 is \(index * 5)")}// 1 times 5 is 5// 2 times 5 is 10// 3 times 5 is 15// 4 times 5 is 20// 5 times 5 is 25
要遍曆的元素集合是使用...建立的1到5的一個閉區間。index的值被設定為範圍的第一個值1,迴圈體中的語句被執行。這個例子中迴圈體只包含一條語句,就是輸出乘法表。語句執行完以後,index的值使用範圍的第二個值2更新,輸出語句又被執行了。這個過程一直範圍的最後一個值。

上面資曆中,index是常量,在每次進行迴圈的時候自動被賦值。這種情況index沒有必要再使用前就聲明。在for-in當中直接使用index就相當於是隱式聲明了常量index,都不需要再使用let關鍵字。

NOTE 常量index的作用範圍僅僅是迴圈體,如果你想在迴圈結束以後查看index的值,或者你想讓index作為變數而不是常量,那你必須在迴圈之前自己去聲明index。

如果你並不是需要範圍中的所有值,你可以通過使用在變數的位置使用底線來忽略元素的值。

let base = 3let power = 10var answer = 1for _ in 1...power {    answer *= base}println("\(base) to the power of \(power) is \(answer)")// prints "3 to the power of 10 is 59049"
這個例子計算base的power次方(例子中是3的10次方)。例子從1乘3開始,乘了10次,使用了從0到9的半閉區間(這裡有問題嗎,原文是using a half-closed loop that start with 0 and ends with9,但是例子沒有半閉區間也沒有0到9啊)。這個計算不需要知道每次迴圈計數器的值,只需要每次迴圈的之後給answer再乘base就行了。迴圈變數的位置使用的底線使得每次迴圈過程都忽略了迴圈變數的值,也不提供擷取迴圈變數值的途徑了。

使用for-in迴圈遍曆數組中的元素:

let names = ["Anna", "Alex", "Brian", "Jack"]for name in names {    println("Hello, \(name)!")}// Hello, Anna!// Hello, Alex!// Hello, Brian!// Hello, Jack!
你還可以遍曆擷取字典的key-value對。字典的每個元素以元組(key, value)的形式返回,你可以將其成員解析到指定的常量中以便迴圈中使用。下面例子將字典的key解析到常量animalName,字典的值被解析到常量legCount:

let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]for (animalName, legCount) in numberOfLegs {    println("\(animalName)s have \(legCount) legs")}// spiders have 8 legs// ants have 6 legs// cats have 4 legs
字典中的元素被遍曆的順序與插入時的順序是沒有關係的。字典中的元素是無序的,遍曆的時候也不會保證有什麼順序。

除了數組和字典,你還可以使用for-in迴圈遍曆字串中的字元:

for character in "Hello" {    println(character)}// H// e// l// l// o


for-condition-increment

除了for-in迴圈,swift還支援傳統的C風格的帶有條件和遞增語句的for迴圈:

for var index = 0; index < 3; ++index {    println("index is \(index)")}// index is 0// index is 1// index is 2
這種迴圈的一般格式是這樣的:

for initialization ; condition ; increment {
     statements
}

和C一樣分號分隔了迴圈定義的三個部分,但是和C不一樣的是Swift不需要在initialization ; condition ; increment外面加括弧。

迴圈的執行順序如下:

迴圈格式和執行過程可以使用下面等價的形式來表達:

initialization
while condition {
    statements
    increment
}

在初始設定式中聲明(比如var index = 0)的常量和變數只能在這個for迴圈中能夠使用,要在迴圈結束後使用index,必須在迴圈之前聲明index。

var index: Intfor index = 0; index < 3; ++index {    println("index is \(index)")}// index is 0// index is 1// index is 2println("The loop statements were executed \(index) times")// prints "The loop statements were executed 3 times"
注意迴圈完全結束以後index的值是3而不是2.最後一次遞增語句++index被執行,index變為3,然後index<3等於false,迴圈結束。

2.while迴圈

while迴圈反覆執行迴圈體直到條件變為false。這種迴圈非常適用於在迴圈體執行之前迴圈次數未知的情況。Swift提供兩種while迴圈形式:

  • while:每次執行迴圈體之前先計算條件的值。
  • do-while:每次執行完迴圈體之後計算條件的值。

while
while迴圈以計算條件運算式開始。如果條件為true,迴圈體就被反覆執行知道條件為false,下面是while迴圈的一般形式

while condition {

statements

}

下面玩一個蛇與梯子的遊:



遊戲規則:

  • 棋盤有25個方格,遊戲的目的是要到達或者超過第25格。
  • 每次一輪,你需要搖色子來決定你走幾格,路線如虛線所示。
  • 如果這一輪結束的時候你到了梯子的底部,就順著梯子上去。
  • 如果你這輪結束的時候碰到了舌頭,就順著射移到下面去。

棋盤可以使用一個Int數組來表示。棋盤大小使用常量finalSquare儲存,用來初始化數組以及後面檢查遊戲是否通關。棋盤使用26個0來初始化,而不是25個(下標從0到25):

let finalSquare = 25var board = Int[](count: finalSquare + 1, repeatedValue: 0)
一些涉及到蛇和梯子的方格要被設定為特殊值。挨著梯子底部的方格設定為整數用來向上移動,而挨著蛇頭的方格被設定為負數用來向下滑:

board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08

第3格有一個梯子,可以爬到第11格,所以borad[03]被設定為+8,上面整數前面帶加號知識為了看起來更清楚,下標小於10的前面加0隻是為了代碼整齊。(加號和多餘的0都不是必須的,但是這裡加上能讓代碼更清晰。)

遊戲從第0格開始,就是在棋盤左下角之外。第一次擲色子就能移到棋盤上了:

var square = 0var diceRoll = 0while square < finalSquare {    // roll the dice    if ++diceRoll == 7 { diceRoll = 1 }    // move by the rolled amount    square += diceRoll    if square < board.count {        // if we're still on the board, move up or down for a snake or a ladder        square += board[square]    }}println("通關!")
上面例子裡使用很簡單的方式來擲色子。讓diceRoll從0開始,每次迴圈給他加1,++diceRoll返回的是+1後的值,所以當diceRoll+1等於7的時候再把diceRoll設定為1,所以色子的結果是1,2,3,4,5,6,1,2,3...而不是用隨機數。

色子投出來以後,玩家移動diceRoll對應的格數。如果玩家移動以後的格數大於或者等於25就贏了。考慮這種情況,代碼在移動以後檢測當前位置是不是比棋盤格數要小,如果比棋盤格數小才加上那一格中的值,如果不小,就說明過關了。那一格中儲存的值就是順著梯子往上爬或者順著蛇往下爬的格數。如果不加這個判斷,board[square]就有可能要去擷取數組board範圍外的值,將會引起運行錯誤。如果現在squre等於26,代碼會去擷取board[26],這個下標超過數組board的範圍了。

當前迴圈體執行完了以後,執行迴圈條件陳述式,看迴圈是否繼續執行。如果玩家已經移動到或者超過第25格,迴圈條件結果就是false,遊戲就結束了。

這個例子使用while迴圈是比較合適的,因為在迴圈開始之前是不知道遊戲要進行的次數的。相反,迴圈是一直執行到某個特定的條件滿足才停止。

do-while

另一種while迴圈do-while先執行一次迴圈體,然後才去判斷迴圈條件。然後迴圈執行迴圈體直到迴圈條件為false。

下面是do-while的一般形式:

do {
statements
} while condition

下面還是蛇與梯子的遊戲,這次使用do-while而不是while了。finalSquare,board,square和diceRoll的初始化方式還和上面一樣:

let finalSquare = 25var board = Int[](count: finalSquare + 1, repeatedValue: 0)board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08var square = 0var diceRoll = 0

這次遊戲迴圈第一步就是檢查是否在梯子或蛇上。因為沒有梯子可以直接通到第25格,所以玩家不可能通過梯子移動就直接通關。所以迴圈第一步直接檢查蛇或者梯子是安全的。(這裡讀起來挺彆扭的好像沒有解釋清楚,應該是說用do-while的時候迴圈第一步就可以直接加上當前格子對應的數字,而不是先擲色子,因為擲色子移動然後就可能到達25格,那你再爬梯子之前就需要前面那個if了,但是如果先爬梯子,就不用判斷接著就擲色子,因為從圖上看出來爬梯子不可能會通關的。)

遊戲開始的時候玩家在第0格上,board[0]還是0,沒有什麼影響:

do {<span style="white-space:pre"></span>// move up or down for a snake or ladder<span style="white-space:pre"></span>square += board[square]<span style="white-space:pre"></span>// roll the dice<span style="white-space:pre"></span>if ++diceRoll == 7 { diceRoll = 1 }<span style="white-space:pre"></span>// move by the rolled amount<span style="white-space:pre"></span>square += diceRoll} while square < finalSquareprintln("Game over!")
代碼檢查過梯子或者蛇以後,再通過擲色子移動,然後一輪迴圈結束。

迴圈條件跟前面的是一樣的,但是這次迴圈條件只有當第一次迴圈結束的時候才會被第一次計算。對於這個遊戲來說do-while迴圈要比while迴圈更合適。上面do-while的迴圈裡,當迴圈條件確定squre還在棋盤上的時候開始下一次迴圈,並且進入迴圈一開始就執行squre+=board[square]。這樣就免去了前面對於square邊界的檢查。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.