while
ループは条件が false
になるまでループブロックを実行します。この種のループは事前に繰り返し処理すべき回数がわからない場合に適しています。Swift には、while
ループが 2 種類あります。
while
は、繰り返し処理のたびに、最初に条件を評価します。repeat
–while
は、繰り返し処理のたびに、最後に条件を評価します。
while
while
ループは、条件の評価から開始します。条件が true
の場合、条件が false
になるまでループブロックを繰り返します。
while
ループの一般的な形式は、次のようになります。
while condition {
statements
}
この例は、シンプルな「蛇と梯子」(Chutes and Ladders としても知られる)ゲームです。
ゲームのルールは、以下のようになります。
- ボードには 25 マスあり、目的は 25 マス目に到着するか、越えることです。
- 各ターンで、6 面のサイコロを振って出た数だけ、矢印の方向にマスを移動します。
- 梯子の下側で止まった場合、梯子の上側に移動します。
- 蛇の頭側で止まった場合、蛇の下側に移動します。
ゲームボードは、Int
値の配列で表現されています。サイズは定数 finalSquare
で、配列の初期化と、勝利条件の判定に使用されます。ボードは 25 個ではなく、(0
から 25
までの)26 個の Int
値ゼロで初期化されます。
let finalSquare = 25
var board = [Int](count: finalSquare + 1, repeatedValue: 0)
いくつかのマスには、蛇および梯子用に特別な値が設定されています。梯子の下側のマスには、ボード上方に進めるためのプラス値があります。一方で、蛇の頭側のマスには、ボード下方に戻すためのマイナス値があります。
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
マス 3 は梯子の下側で、マス 11 に進みます。これを表現するために、board[03]
を整数値の 8
(3
と 11
の差)に相当する +08
としています。単項プラス演算子 (+i
) を付けて単項マイナス演算子 (-i
) と釣り合わせ、10
未満の数値をゼロ埋めすることで、すべてのボード定義がそろうようにしています。(調整する必要は無いですが、コードがすっきりします。)
プレイヤーの開始マスは「ゼロ」で、ボード左下の外になります。最初のサイコロで、プレイヤーはボード上を移動することになります。
var square = 0
var diceRoll = 0
while square < finalSquare {
// サイコロを振る
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
// 出た数だけ進む
square += diceRoll
if square < board.count {
// まだボード上にいる場合、蛇や梯子で上下に移動
square += board[square]
}
}
print("Game over!")
この例では、サイコロについてシンプルなアプローチを採っています。ランダムな数値を生成せずに、diceRoll
の値を 0
で開始しています。while
でループするたびに、diceRoll
を 1 増加させ、大きくなりすぎることがないようチェックしています。この戻り値が 7
のときに、サイコロが大きくなりすぎたと判定し、サイコロは 1
にリセットされます。diceRoll
の値は、1
、2
、3
、4
、5
、6
、1
、2
、と続くことになります。
サイコロを振った後、プレイヤーは diceRoll
の数だけマスを進みます。サイコロの数によっては、25 マス目を通り越す場合がありますが、そこでゲーム終了となります。このシナリオに対処するために、プレイヤーが梯子や蛇を上下に移動する board[square]
の値を square
値に追加する前に、square
が board
配列の count
プロパティよりも小さいことをチェックします。
このチェックが実行されない場合、board[square]
が board
配列の範囲外の値にアクセスしようとし、エラーを引き起こします。square
が 26
の場合には、コードは配列のサイズより大きい board[26]
の値をチェックしようとしてしまいます。
現在の while
ループの終了時に、ループを再実行すべきかの条件がチェックされます。プレイヤーが移動して 25
マス目に達するか、または越えた場合、ループの条件は false
と評価され、ゲーム終了となります。
while
ループは、while
ループの開始時点でゲームの長さが明確でないため、このケースに適しています。特定の条件が満たされるまでループは実行されます。
repeat-while
while
ループのもう一方のバリエーションが repeat
–while
ループで、ループ条件の前にまず一度ループブロックを実行します。そして、条件が false
になるまでループを繰り返します。
repeat
–while
ループは、他の言語での do
–while
ループに類似しています。
repeat
–while
ループの一般的な形式は、次のようになります。
repeat {
statements
} while condition
次の例は再び「蛇と梯子」で、while
ループでなく repeat
–while
ループで記述されています。finalSquare
、board
、square
、diceRoll
の値は、while
ループとまったく同じように初期化されています。
let finalSquare = 25
var board = [Int](count: finalSquare + 1, repeatedValue: 0)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
var square = 0
var diceRoll = 0
ゲームのこのバージョンでは、ループ内での最初のアクションは梯子と蛇をチェックすることです。ボード上にプレイヤーをそのまま 25 マス目に進める梯子は無いため、梯子を進み上がってゲームに勝つことはありません。そのため、ループ内での最初のアクションとして蛇と梯子をチェックしても安全です。
ゲーム開始時に、プレイヤーはゼロマス目にいます。board[0]
は常に 0
で、何の影響もありません。
repeat {
// 蛇や梯子で上下に移動
square += board[square]
// サイコロを振る
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
// 出た数だけ進む
square += diceRoll
} while square < finalSquare
print("Game over!")
蛇と梯子をチェック後、サイコロを振り、プレイヤーは diceRoll
の数だけ進み、現在のループを終了します。
ループの条件 (while square < finalSquare
) は前と同じですが、今回は最初のループ実行が終了するまで評価されません。repeat
–while
ループの仕組みは、前の例での while
ループよりもこのゲームに適しています。上の repeat
–while
ループでは、square
がボード上にあることをループの while
条件が確認できた後すぐに、square += board[square]
が常に実行されます。前のバージョンにあった配列の範囲を確認する処理を無くすことができています。
Portions of this page are translations based on work created and shared by Apple and used according to terms described in the Creative Commons Attribution 4.0 International License.