Swift Playground Part 6: While Loops   

In this section we look at while loops. While loops are similar to for loops but the main difference is that in a for loop, you specify the number of times to loop. A while loop continues to run “while” some condition is true. What this can mean is that it may be possible to get stuck in an infinite loop so be careful!

Running code while

This challenge is a nice introduction into while loops. Notice how the switch in the last tile is on? This means that you can test for when your switch is NOT on or “closed” and when it reaches the last time, the condition will be false and the loop will stop.

Inside the loop you will need only 2 lines of code. Have a go yourself first otherwise take a sneak peak at the solutions below.

Running code while - Solution
while isOnClosedSwitch {
    toggleSwitch()
    moveForward()
}

Creating smarter while loops

The key to this puzzle is to figure out the ending or terminating condition. In other words, what will make the while loop stop. If you look at the very end you’ll see that Byte will hit a dead end which means we can use the “isBlocked” command. But the secret is to use our knowledge of the previous section on logical operators and say “move forward and do stuff while Byte is NOT blocked ahead”. That is enough of a hint for you. Go and give it a try.

Creating smarter while loops - Solution
while !isBlocked {
    moveForward()
    if isOnClosedSwitch{
        toggleSwitch()
        moveForward()
    }
}

Choosing the correct tools

In this puzzle, start off by finding a repeatable pattern and just try it out. Don’t worry about using functions yet, we can convert it into a function at the end. Also remember to think about the ending condition of our while loop. Hint: It is the same as the previous puzzle!

Choosing the correct tools - Simple solution
while !isBlocked {
    moveForward()
    turnLeft()
    moveForward()
    collectGem()
    turnRight()
}
Choosing the correct tools - Solution using functions
func turnAndCollectGem() {
    moveForward()
    turnLeft()
    moveForward()
    collectGem()
    turnRight()
}

while !isBlocked {
    turnAndCollectGem()
}

Four by four*

There are a few solutions here. You can use a for loop because you turn right 3 times and hit a dead end so you know how many times to loop. You can also use a while loop with the same starting condition of “is NOT blocked”. Of course it is better to use a while loop because this is what we are practising but using a for loop is not wrong.

Also, don’t forget to check out the while loop with a function that has a for loop inside! This solution is a little longer but has the advantage of not checking every tile if there is a switch to toggle. What this means is that the code will run faster.

Four by four - Solution using for
for i in 1 ... 4 {
    moveForward()
    moveForward()
    moveForward()
    if isOnClosedSwitch{
        toggleSwitch()
        turnRight()
    } else {
        turnRight()
    }
}
Four by four - Solution using while
while !isBlocked {
    moveForward()
    if isOnClosedSwitch {
        toggleSwitch()
        turnRight()
    } else if isOnOpenSwitch{
        turnRight()
    }
}
Four by four - Solution using while with functions
func moveForwardThreeAndToggle() {
    for i in 1 ... 3 {
        moveForward()
    }
    if isOnClosedSwitch {
        toggleSwitch()
    }
}

while !isBlocked {
    moveForwardThreeAndToggle()
    turnRight()
}

Turned around

The trick to this puzzle is to recognise how to get into a starting position. Once you have “moved forward” and “turned left”, you should then start to see a pattern emerge.

Try working it out the long way first before trying to optimise the code using functions. Also remember that for a while loop, you’ll need to figure out your ending condition. Here, we use “while isOnGem” but you could use others like is NOT blocked.

Turned around - Simple solution 1
func collectGemOnOneSide() {    
    moveForward()
    collectGem()
    turnLeft()
    moveForward()
    collectGem()
    turnLeft()
    moveForward()
    turnRight()
}

collectGemOnOneSide()
collectGemOnOneSide()
collectGemOnOneSide()
collectGemOnOneSide()
Turned around - Simple solution using for
func collectGemOnOneSide() {
    moveForward()
    collectGem()
    turnLeft()
    moveForward()
    collectGem()
    turnLeft()
    moveForward()
    turnRight()
}
for i in 1 ... 4 {
    collectGemOnOneSide()
}
Turned around - Solution using while
func collectMyGem() {
    collectGem()
    moveForward()
    collectGem()
}
func turnCorner() {
    turnLeft()
    moveForward()
    turnRight()
    moveForward()
    turnLeft()
}

moveForward()
turnLeft()

while isOnGem {
    collectMyGem()
    turnCorner()
}

Land of bounty

Things are getting trickier! These dynamic puzzles are challenging because you don’t know how long each row is. This means you can rule out a for loop.

The way to solve this is to try and do it the long way. Move along each row and toggle the switch and collect the gem. Then find ways to improve it. The improved solution uses a bunch of if conditions to figure out what to do along with how to turn.

Land of bounty - First easy solution
moveForward()
while !isBlocked {
    if isOnClosedSwitch{
        toggleSwitch()
    } else {
        moveForward()
    }
}
turnRight()
moveForward()
turnRight()

while !isBlocked {
    if isOnGem{
        collectGem()
    } else {
        moveForward()
    }
}

turnLeft()
moveForward()
turnLeft()
moveForward()

while !isBlocked {
    if isOnClosedSwitch{
        toggleSwitch()
    } else {
        moveForward()
    }
}
Land of bounty - An improved solution
while !isBlocked{
    moveForward()
    if isOnClosedSwitch && !isBlocked {
        toggleSwitch()
    } else if isBlocked && isBlockedLeft {
        turnRight()
        moveForward()
        turnRight()
    } else if isOnGem {
        collectGem()
    } else if isBlocked && isBlockedRight {
        turnRight()
    } else if isBlocked {
        turnLeft()
        moveForward()
        turnLeft()
    }
}

Nesting Loops

This puzzle is a nice simple introduction to nesting loops or in other words, putting a loop inside a loop. These can get tricky so it is always best to start simple and understand the fundamentals.

The key is to add a condition to the outer loop so that the inner loop repeats until Byte is blocked. So the outer loop should say “keep on doing stuff until you are blocked” which is the end condition that will stop the entire code. Then you say while you are NOT on a gem, do stuff, otherwise do other stuff. Have a go and if you get stuck, look at the answer below or in the video.

Nesting loops - Solution
while !isBlocked {
    while !isOnGem {
        moveForward()
    }
    collectGem()
    turnLeft()
}

Random rectangles

This challenge uses a nested loop and conditions to move around a changing world. The size of the path, or the perimeter changes so you need to keep on walking and figure out when to turn.

Remember to start with the end condition first. What will make the while loop stop? Then, what condition will make Byte turn right?

Random rectangles - Answers
while !isOnClosedSwitch {
    while !isBlocked {
        moveForward()
    }
    turnRight()
}
toggleSwitch()

You’re always right

In this challenge you can use any of your new programming skills to toggle all the switches and collect the single gem. The fact that there is only 1 gem should be a clue. ie it is your end condition.

Just use your skills to move through step by step and if you get stuck, take a sneak peak at the various solutions below.

You're always right - Solution with while and if
while !isOnGem {
    if !isBlocked {
        moveForward()
        if isOnClosedSwitch {
            toggleSwitch()
        }
    } else if isBlocked &&  !isBlockedRight{
        turnRight()
    }
}
collectGem()
You're always right - Solution with nested while
while !isOnGem {
    while !isBlocked {
        moveForward()
        if isOnClosedSwitch {
            toggleSwitch()
        }
    } 
    turnRight()
}
collectGem()

See all solutions in the video below

Leave a Reply

Your email address will not be published. Required fields are marked *