Reputation: 57
So i'm still learning but i'm struggling to understand a certain part of this code:
case let newSquare where newSquare > finalSquare:
// diceRoll will move us beyond the final square, so roll again
continue gameLoop
Why does newSquare end up being 27, 28 and 29 each time I run through the loop?
Shouldn't newSquare be 0 each time? I've tried printing out newSquare in the loop and each time it turns out to be 27, 28, 29.
Here is the full code for reference:
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
gameLoop: while square != finalSquare {
if ++diceRoll == 7 { diceRoll = 1 }
switch square + diceRoll {
case finalSquare:
// diceRoll will move us to the final square, so the game is over
break gameLoop
case let newSquare where newSquare > finalSquare:
// diceRoll will move us beyond the final square, so roll again
continue gameLoop
default:
// this is a valid move, so find out its effect
square += diceRoll
square += board[square]
}
}
print("Game over!")
Sorry i'm sure it's simple but I'm not quite getting it :/
Upvotes: 1
Views: 488
Reputation: 10136
The construct is actually not just mere:
case let newSquare where newSquare > finalSquare: // ...
... but:
switch square + diceRoll {
// ...
case let newSquare where newSquare > finalSquare: // ...
switch
statement evaluates (square + diceRoll)
and compares it to all specified cases in the order. First one to be true
wins and assumes the control of execution.
In this particular example, case let newSquare where newSquare > finalSquare
will "win" every time when (square + diceRoll) > finalSquare
, which in terms of the game-logic means that we run over the board limit. In-place constant newSquare
is of no real use here (i.e. we do not use its value anyhow) and is introduced just to be able to use where
statement of switch-case.
Temporary constant newSquare
gets initialised via so called value binding:
A
switch
case can bind the value or values it matches to temporary constants, for use in the body of the case. This is known as value binding, because the values are “bound” to temporary constants within the case’s body.
BTW, alternative way of saying almost the same thing as in the example would be:
switch square + diceRoll {
// ...
case finalSquare..<Int.max: // ...
... as preceding case finalSquare
will take care of the option that we end up precisely on the final square, while range finalSquare..<Int.max
will get to be evaluated only afterwards, therefore will only trigger if (square + diceRoll)
is greater than finalSquare
.
Upvotes: 1
Reputation: 1461
It's because newSquare
becomes the value (because of let
) of square + diceRoll
when (where
) the condition newSquare > finalSquare
is true.
Since finalSquare
is 25, then only when square + diceRoll
will be over 25, this case will execute.
Upvotes: 1