Techbase Academy
Android · Lesson 09

Conditionals and Loops in Kotlin

12 phasesNumber PlaygroundAndroid Studio
Phase 1 of 12
Lesson Introduction

Until now your programs have been like a one-way road: every statement runs, in order, exactly once. Real programs need to decide ("if the user is under 18, show this message") and to repeat ("do this for every student in the class"). Those two powers, conditionals and loops, are what turn a list of instructions into a program that can handle many situations.

Think of a danfo conductor collecting fares. For each passenger he decides: is this a child? a student? an adult? That is a conditional. Then he does the same routine for every passenger on the bus until the bus is empty. That is a loop. By the end of this lesson you will be able to write both, and you will practise on a full set of problems.

By the end of this lesson you will be able to:

  • Make decisions with if, else if and else.
  • Use if as an expression that produces a value.
  • Choose between many options with when, including ranges and multiple values.
  • Create ranges with .., until, downTo and step.
  • Repeat work with for, while, do-while and repeat.
  • Control loops with break, continue and labels.
  • Combine conditions with &&, || and !.
  • Solve the full Practice: Kotlin Basics style problem set with worked solutions.

How this fits the bigger picture: This lesson covers the Write conditionals in Kotlin codelab and the full practice set that follows it in Unit 2, Pathway 1 of Android Basics with Compose. In lesson 17 you will use when to choose which dice image to show, and in lesson 21 you will turn a list into screen items. Both rely on what you learn here.

✏️ Your Task
Practise what you just learned about Lesson Introduction. Open Android Studio, type the examples by hand, change a value, and observe what happens.
Phase 2 of 12
Prerequisite Concepts

1. Boolean values and comparisons (lesson 07)

A Boolean is true or false. Comparison operators (==, !=, <, >, <=, >=) produce Booleans, and &&, || and ! combine them. Every decision in this lesson is based on a Boolean.

2. Functions (lesson 08)

We write most examples as small functions that return a value. If fun fareFor(age: Int): Int looks unfamiliar, revisit lesson 08.

3. Blocks and braces

A block is a group of statements inside { }. A variable created in a block lives only inside it (scope, lesson 08).

4. Remainder operator

n % 2 == 0 is true when n is even. We use % often in this lesson. If it is unfamiliar, see lesson 07.

✏️ Your Task
Practise what you just learned about Prerequisite Concepts. Open Android Studio, type the examples by hand, change a value, and observe what happens.
Phase 3 of 12
Conceptual Understanding: Decisions and Repetition

The decision picture

text
              +-----------------+
              |  age >= 18 ?    |
              +--------+--------+
                 yes   |   no
          +------------+-----------+
          v                        v
   "You may vote"          "Come back later"
          \                        /
           +----------+-----------+
                      v
            program carries on

An if checks a Boolean condition. If it is true, one block runs. If not, Kotlin skips it (or runs the else block). After that, the program carries on.

The loop picture

text
        +--------------------+
   +--->| is there more work?|--- no ---> carry on after the loop
   |    +---------+----------+
   |          yes |
   |              v
   |      do the loop body
   |              |
   +--------------+

A loop asks "is there more work?" before each pass. As long as the answer is yes, the body runs again. A common bug is a loop whose answer is always yes, which never ends. We will see how to avoid that.

Choosing the right tool

You want to... Use
Run code only when something is true if
Pick one of two values if ... else as an expression
Pick among several cases for one value when
Repeat a known number of times for over a range, or repeat
Repeat until something changes while
Repeat at least once, then check do-while
✏️ Your Task
Practise what you just learned about Conceptual Understanding: Decisions and Repetition. Open Android Studio, type the examples by hand, change a value, and observe what happens.
Phase 4 of 12
Conditionals: `if`, `else if`, `else`

Example 1: A simple if

kotlin
fun main() {
 val temperature = 33
 if (temperature > 30) {
 println("It is hot. Drink water.")
 }
 println("Done checking.")
}

It is hot. Drink water.
Done checking.

The condition goes inside parentheses, and must be a Boolean. Kotlin (unlike some languages) does not accept if (1) or if (name).

Example 2: if with else

kotlin
fun main() {
 val age = 16
 if (age >= 18) {
 println("You can vote.")
 } else {
 println("You are too young to vote.")
 }
}

You are too young to vote.

Example 3: Several branches with else if

Kotlin checks conditions from top to bottom and runs the first block whose condition is true, then skips the rest.

kotlin
fun main() {
 val score = 67
 if (score >= 70) {
 println("Grade A")
 } else if (score >= 60) {
 println("Grade B")
 } else if (score >= 50) {
 println("Grade C")
 } else {
 println("Grade F")
 }
}

Grade B

67 is not at least 70, so the first block is skipped. It is at least 60, so "Grade B" prints and the remaining branches are ignored. Order matters. If you tested score >= 50 first, every score from 50 upwards would get Grade C.

Example 4: Combining conditions

kotlin
fun main() {
 val age = 15
 val hasTicket = true
 val isMember = false
 if (age >= 12 && hasTicket) {
 println("Welcome in.")
 }
 if (isMember || age < 10) {
 println("Free snack.")
 } else {
 println("No free snack today.")
 }
 if (!hasTicket) {
 println("Please buy a ticket.")
 }
}

Welcome in.
No free snack today.

The first condition needs both parts true (&&). The second needs at least one (||). The third flips the Boolean (!). && and || are short-circuit: if the left side already settles the answer, Kotlin does not look at the right side.

Example 5: if as an expression

In Kotlin, if ... else can produce a value. This is a favourite feature because it removes a lot of clutter:

kotlin
fun main() {
 val a = 12
 val b = 30
 val larger = if (a > b) a else b
 println("Larger: $larger")
 val label = if (a % 2 == 0) "even" else "odd"
 println("$a is $label")
 println("Pass? ${if (a >= 50) "yes" else "no"}")
}

Larger: 30
12 is even
Pass? no

Rules: when if is used as an expression, an else is required (otherwise there would be no value in the "false" case). The last expression in each block is the value of that branch. Because of this, Kotlin has no ? : ternary operator. if already does the job.

A function can return an if directly:

kotlin
fun maxOf(a: Int, b: Int): Int = if (a > b) a else b

(The standard library already has a function called maxOf; defining your own in a file of your own is fine for learning, but you may see a name clash warning in a bigger project.)

✏️ Your Task
Practise what you just learned about Conditionals: `if`, `else if`, `else`. Open Android Studio, type the examples by hand, change a value, and observe what happens.
Phase 5 of 12
Choosing with `when`

When you compare one value against many possibilities, a long else if chain gets tiring. Kotlin's when is a cleaner tool, like a sorting machine with labelled chutes.

Example 6: when with a subject

kotlin
fun dayName(number: Int): String {
 return when (number) {
 1 -> "Monday"
 2 -> "Tuesday"
 3 -> "Wednesday"
 4 -> "Thursday"
 5 -> "Friday"
 6, 7 -> "Weekend"
 else -> "Not a valid day"
 }
}
fun main() {
 println(dayName(3))
 println(dayName(7))
 println(dayName(9))
}

Wednesday
Weekend
Not a valid day

Each line has a condition, an arrow -> and a result. Kotlin checks from the top and stops at the first match. 6, 7 -> groups several values on one line. The else branch catches everything else. When when is used as an expression (as here, because we return it), else is required (unless the subject is an enum or sealed type, which you will meet later).

Example 7: when with ranges

kotlin
fun fareFor(age: Int): Int = when (age) {
 in 0..5 -> 0
 in 6..17 -> 100
 in 18..59 -> 200
 in 60..130 -> 50
 else -> -1 // -1 means "invalid age"
}
fun main() {
 println(fareFor(4))
 println(fareFor(10))
 println(fareFor(30))
 println(fareFor(65))
 println(fareFor(-3))
}

0
100
200
50
-1

in 6..17 means "is the value from 6 up to and including 17?". We will study ranges properly in a moment.

Example 8: when without a subject

If you leave out the subject, each branch is a full Boolean condition. This replaces an else if chain neatly:

kotlin
fun describeTemperature(c: Int): String = when {
 c <= 0 -> "freezing"
 c < 15 -> "cold"
 c < 30 -> "pleasant"
 else -> "hot"
}
fun main() {
 println(describeTemperature(-3))
 println(describeTemperature(12))
 println(describeTemperature(22))
 println(describeTemperature(35))
}

freezing
cold
pleasant
hot

Example 9: when with types (is)

when can also test what kind of value something is. This is a preview of ideas used later with sealed classes (lesson 29). Any means "a value of any type".

kotlin
fun describe(x: Any): String = when (x) {
 is Int -> "Int: $x"
 is String -> "String of length ${x.length}"
 else -> "Something else"
}
fun main() {
 println(describe(42))
 println(describe("Kotlin"))
 println(describe(3.5))
}

Int: 42
String of length 6
Something else

Notice x.length works inside the is String branch. Kotlin knows x is a String there. This feature is called a smart cast, and you will see more of it in lesson 10.

✏️ Your Task
Practise what you just learned about Choosing with `when`. Open Android Studio, type the examples by hand, change a value, and observe what happens.
Phase 6 of 12
Ranges

A range is a sequence of values with a start and an end. Ranges power both when conditions and for loops.

Expression Values Notes
1..5 1, 2, 3, 4, 5 both ends included
1 until 5 1, 2, 3, 4 the end is excluded
5 downTo 1 5, 4, 3, 2, 1 counting down
1..10 step 3 1, 4, 7, 10 skipping
10 downTo 1 step 3 10, 7, 4, 1 down with a step
'a'..'e' a, b, c, d, e characters work too
kotlin
fun main() {
 val age = 15
 println(age in 13..19) // is age inside the range?
 println(age !in 13..19) // is it outside?
 println(10 in 1 until 10) // end excluded, so false
}

true
false
false

Note 10..1 is an empty range because it counts up from 10 and never reaches 1. To count down, you must say 10 downTo 1.

✏️ Your Task
Practise what you just learned about Ranges. Open Android Studio, type the examples by hand, change a value, and observe what happens.
Phase 7 of 12
Loops

The for loop

A for loop takes each value of a range (or collection) in turn:

kotlin
fun main() {
 for (i in 1..5) {
 println("Round $i")
 }
}

Round 1
Round 2
Round 3
Round 4
Round 5

i is the loop variable. Kotlin creates it for you, and it takes the next value each time round. You do not write val, and you cannot reassign it inside the loop.

More shapes:

kotlin
fun main() {
 for (i in 1 until 4) print("$i ") // 1 2 3
 println()
 for (i in 10 downTo 1 step 3) print("$i ") // 10 7 4 1
 println()
 for (c in 'a'..'e') print("$c ") // a b c d e
 println()
 for (letter in "Kota") print("$letter-") // a string is a sequence of characters
 println()
}

1 2 3
10 7 4 1
a b c d e
K-o-t-a-

print keeps everything on one line, and each println() ends the line. (Lines may show a trailing space.) Lesson 14 shows for over lists, sets and maps.

Counting with a running total

kotlin
fun main() {
 var total = 0
 for (n in 1..100) {
 total += n
 }
 println("Sum of 1 to 100 = $total")
}

Sum of 1 to 100 = 5050

The variable total must be a var, since it changes in every round. This is the standard pattern: a var outside the loop, updated inside.

The while loop

Use while when you do not know in advance how many rounds are needed. It keeps going as long as its condition is true.

kotlin
fun main() {
 var saved = 0
 var weeks = 0
 while (saved < 15000) {
 saved += 2000
 weeks++
 }
 println("It takes $weeks weeks to save at least ₦15000. Saved: ₦$saved")
}

Working: after 7 weeks the total is 14000 (still under 15000), so the loop runs once more, giving 16000 after 8 weeks.

It takes 8 weeks to save at least ₦15000. Saved: ₦16000

Danger: if nothing inside a while ever makes the condition false, the loop never ends and the program hangs. Always ask: what changes each round so that the loop eventually stops? Here it is saved.

The do-while loop

do-while runs the body first and checks the condition afterwards, so the body always runs at least once:

kotlin
fun main() {
 var n = 10
 do {
 println("n is $n")
 n++
 } while (n < 5)
 println("Finished with n = $n")
}

n is 10
Finished with n = 11

A plain while (n < 5) would have printed nothing, because 10 is not less than 5. Use do-while for "try at least once" tasks such as showing a menu and asking again.

repeat

When you simply want something done n times, repeat is the shortest form. Inside, it is the round number, starting at 0:

kotlin
fun main() {
 repeat(3) {
 println("Hip hip hooray! (round ${it + 1})")
 }
}

Hip hip hooray! (round 1)
Hip hip hooray! (round 2)
Hip hip hooray! (round 3)

(repeat takes a lambda, which is the { } block. Lesson 12 explains lambdas and it fully.)

Nested loops

A loop inside a loop runs the inner one fully for each round of the outer one:

kotlin
fun main() {
 for (row in 1..4) {
 for (col in 1..row) {
 print("*")
 }
 println()
 }
}

*
**



Row 1 prints one star, row 2 prints two, and so on, because the inner range 1..row grows with the row.

break and continue

  • break leaves the loop completely.
  • continue skips the rest of this round and moves to the next.
kotlin
fun main() {
 for (i in 1..9) {
 if (i % 2 == 0) continue // skip even numbers
 if (i > 7) break // stop after 7
 print("$i ")
 }
 println()
}

Round by round: 1 prints, 2 is skipped, 3 prints, 4 skipped, 5 prints, 6 skipped, 7 prints, 8 is skipped (continue happens first), 9 triggers break.

1 3 5 7

Labels: breaking out of nested loops

A plain break leaves only the innermost loop. To leave an outer loop, put a label (name@) on it and write break@name:

kotlin
fun main() {
 outer@ for (i in 1..5) {
 for (j in 1..5) {
 if (i * j == 12) {
 println("Found $i x $j = 12")
 break@outer
 }
 }
 }
 println("Search finished")
}

For i = 1 and i = 2 no product reaches 12. For i = 3, j = 4 gives 12, so we print and jump out of both loops.

Found 3 x 4 = 12
Search finished

Labels also work with continue@outer. Use them sparingly. If you need many, a function with an early return is often clearer.

✏️ Your Task
Practise what you just learned about Loops. Open Android Studio, type the examples by hand, change a value, and observe what happens.
Phase 8 of 12
Trying It in Android Studio

All the code above runs in a scratch file or the Kotlin library module from lesson 06. In an Android app, if and when appear inside composable functions to decide what to show. For example, in lesson 17 you will see something like this (shown here only to preview the idea, so imports are minimal):

kotlin
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@Composable
fun StatusMessage(isOnline: Boolean) {
 if (isOnline) {
 Text("You are online")
 } else {
 Text("No connection")
 }
}

The if is the same if you learnt today, deciding which Text to put on screen. Loops like for and repeat are also available inside composables, though lists of items usually use lazy lists (lesson 21).

✏️ Your Task
Practise what you just learned about Trying It in Android Studio. Open Android Studio, type the examples by hand, change a value, and observe what happens.
Phase 9 of 12
Practice: Kotlin Basics (Full Practice Set)

This set mirrors the style and difficulty of the official Practice: Kotlin Basics problems, using original problems and original wording. Work in the Playground and try each problem before revealing the solution. Do not skip these. The writing of the code is where the learning happens.

🎯 Your Challenge

Problem 1: Notification summary

Write printNotificationSummary(count: Int). If count is less than 100, print You have N notifications. Otherwise print Your phone is blowing up! You have 99+ notifications. Call it with 5 and 250.

kotlin
fun printNotificationSummary(count: Int) {
 if (count < 100) {
 println("You have $count notifications.")
 } else {
 println("Your phone is blowing up! You have 99+ notifications.")
 }
}
fun main() {
 printNotificationSummary(5)
 printNotificationSummary(250)
}

You have 5 notifications.
Your phone is blowing up! You have 99+ notifications.

🎯 Your Challenge

Problem 2: Bus fare

A bus charges ₦0 for ages 0 to 5, ₦100 for 6 to 17, ₦200 for 18 to 59, and ₦50 for 60 and over (up to 130). Anything else is invalid. Write fareFor(age: Int): Int using when with ranges (return -1 for invalid). Then write printFare(age: Int) that prints either Age 30: ₦200 or Age -3: invalid age.

kotlin
fun fareFor(age: Int): Int = when (age) {
 in 0..5 -> 0
 in 6..17 -> 100
 in 18..59 -> 200
 in 60..130 -> 50
 else -> -1
}
fun printFare(age: Int) {
 val fare = fareFor(age)
 if (fare == -1) {
 println("Age $age: invalid age")
 } else {
 println("Age $age: ₦$fare")
 }
}
fun main() {
 printFare(30)
 printFare(4)
 printFare(70)
 printFare(-3)
}

Age 30: ₦200
Age 4: ₦0
Age 70: ₦50
Age -3: invalid age

🎯 Your Challenge

Problem 3: Leap year

A year is a leap year if it is divisible by 4, except century years (divisible by 100), which must also be divisible by 400. Write isLeapYear(year: Int): Boolean as a single expression, and test 2024, 1900, 2000 and 2026.

kotlin
fun isLeapYear(year: Int): Boolean =
 (year % 4 == 0 && year % 100 != 0) || year % 400 == 0
fun main() {
 println(isLeapYear(2024))
 println(isLeapYear(1900))
 println(isLeapYear(2000))
 println(isLeapYear(2026))
}

2024: divisible by 4 and not by 100, so true. 1900: divisible by 100 but not by 400, so false. 2000: divisible by 400, so true. 2026 is not divisible by 4, so false.

true
false
true
false

🎯 Your Challenge

Problem 4: FizzBuzz

Print the numbers 1 to 15, one per line. For multiples of 3 print Fizz instead, for multiples of 5 print Buzz, and for multiples of both print FizzBuzz. (Hint: test "both" first.)

kotlin
fun main() {
 for (n in 1..15) {
 val text = when {
 n % 15 == 0 -> "FizzBuzz"
 n % 3 == 0 -> "Fizz"
 n % 5 == 0 -> "Buzz"
 else -> n.toString()
 }
 println(text)
 }
}

The "both" case must come first. Otherwise 15 would match n % 3 == 0 and print only Fizz. A multiple of 3 and 5 is a multiple of 15.

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz

🎯 Your Challenge

Problem 5: Times table

Write printTable(n: Int, upTo: Int = 5) that prints lines like 7 x 1 = 7, up to upTo. Call printTable(7) and printTable(12, 3).

kotlin
fun printTable(n: Int, upTo: Int = 5) {
 for (i in 1..upTo) {
 println("$n x $i = ${n * i}")
 }
}
fun main() {
 printTable(7)
 println("---")
 printTable(12, 3)
}

7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35


12 x 1 = 12
12 x 2 = 24
12 x 3 = 36

🎯 Your Challenge

Problem 6: Count the digits

Write countDigits(number: Int): Int using a loop that repeatedly divides by 10. It should return 1 for the number 0. Test with 4096, 7 and 0. (Hint: this is a good place for do-while.)

kotlin
fun countDigits(number: Int): Int {
 var n = number
 var count = 0
 do {
 n /= 10
 count++
 } while (n != 0)
 return count
}
fun main() {
 println(countDigits(4096))
 println(countDigits(7))
 println(countDigits(0))
}

For 4096: dividing gives 409, then 40, then 4, then 0, so four rounds. For 0: the body runs once before the check, so the answer is 1, which is correct. A plain while would have returned 0. (This simple version is meant for non-negative numbers.)

4
1
1

🎯 Your Challenge

Problem 7: Prime numbers

Write isPrime(n: Int): Boolean. Numbers below 2 are not prime. Test divisors starting at 2 while i * i <= n, and return false as soon as one divides evenly. Then print all primes from 1 to 20 on one line.

kotlin
fun isPrime(n: Int): Boolean {
 if (n < 2) return false
 var i = 2
 while (i * i <= n) {
 if (n % i == 0) return false
 i++
 }
 return true
}
fun main() {
 for (n in 1..20) {
 if (isPrime(n)) print("$n ")
 }
 println()
}

We only need to test divisors up to the square root of n, which is why the loop condition is i * i <= n. The early return false leaves the function the moment a factor is found.

2 3 5 7 11 13 17 19

🎯 Your Challenge

Problem 8: Star triangle and countdown

Using repeat, for and downTo, print this exactly: a countdown line 5 4 3 2 1 Lift off!, then a triangle of 3 rows of # (1, 2 then 3 characters). Use the String.repeat function for the triangle if you like: "#".repeat(2) gives ##.

kotlin
fun main() {
 for (i in 5 downTo 1) print("$i ")
 println("Lift off!")
 for (row in 1..3) {
 println("#".repeat(row))
 }
}

5 4 3 2 1 Lift off!

✏️ Your Task
Practise what you just learned about Practice: Kotlin Basics (Full Practice Set). Open Android Studio, type the examples by hand, change a value, and observe what happens.
Phase 10 of 12
Guided Practice Exercises
🎯 Your Challenge

Scenario: A teacher wants to turn exam scores into grades and see a short class report.

Exercise 1: Grade function

Write gradeFor(score: Int): String using when with ranges: 70 to 100 is A, 60 to 69 is B, 50 to 59 is C, 0 to 49 is F, and anything else is Invalid. Print the grade for 85, 60, 49 and 120.

kotlin
fun gradeFor(score: Int): String = when (score) {
 in 70..100 -> "A"
 in 60..69 -> "B"
 in 50..59 -> "C"
 in 0..49 -> "F"
 else -> "Invalid"
}
fun main() {
 println(gradeFor(85))
 println(gradeFor(60))
 println(gradeFor(49))
 println(gradeFor(120))
}

A
B
F
Invalid

🎯 Your Challenge

Exercise 2: Loop with a running count

Write a loop that goes through the numbers 1 to 30 and counts how many are divisible by 3, and also keeps the largest one. Print both results. Do not use any functions from the standard library such as count.

kotlin
fun main() {
 var howMany = 0
 var largest = 0
 for (n in 1..30) {
 if (n % 3 == 0) {
 howMany++
 largest = n
 }
 }
 println("Multiples of 3: $howMany")
 println("Largest: $largest")
}

The multiples of 3 up to 30 are 3, 6, 9 ... 30, which is ten numbers. Because we visit numbers in increasing order, the most recent one is always the largest.

Multiples of 3: 10
Largest: 30

✏️ Your Task

Write a program that uses a while loop to simulate a phone battery draining by 7 percent every hour, starting at 100. Print the hour and level each time, and stop when the level reaches 20 or less. Predict the number of hours before you run it.

Phase 11 of 12
Common Beginner Mistakes (and How to Fix Them)

Mistake #1: = instead of ==. The wrong code: if (age = 18). The error: assignments are not allowed as conditions. The fix: if (age == 18). In Kotlin the compiler catches this for you.

Mistake #2: A missing else when if is an expression. The wrong code: val label = if (score > 50) "Pass". The error: if must have both main and else branches if used as an expression. The fix: val label = if (score > 50) "Pass" else "Fail".

Mistake #3: A missing else in when. The wrong code: a when used as an expression with only some cases. The error: when expression must be exhaustive. The fix: add else -> ... as the last branch.

Mistake #4: Wrong branch order. The wrong code: testing score >= 50 before score >= 70. The result: an 85 gets the grade for 50. The fix: put the most specific condition first.

Mistake #5: Off-by-one with ranges. The wrong code: for (i in 1 until 5) when you wanted 1 to 5. The result: only 1 to 4 run. The fix: 1..5 includes the end, until excludes it.

Mistake #6: A backwards range. The wrong code: for (i in 5..1). The result: the loop body never runs, with no error. The fix: for (i in 5 downTo 1).

Mistake #7: An infinite loop. The wrong code: var i = 0 then while (i < 5) { println(i) } with no i++. The result: the program prints 0 forever. The fix: make something change inside the loop. In Android Studio, press the red stop button in the Run window to end a runaway program.

Mistake #8: Trying to change the loop variable. The wrong code: for (i in 1..5) { i = i + 1 }. The error: Val cannot be reassigned. The fix: use a while loop if you need to control the counter yourself.

Mistake #9: Comparing strings with a range or forgetting .toString(). The wrong code: val text = if (n % 3 == 0) "Fizz" else n makes the type a mix of String and Int. The fix: write n.toString() when you need text in both branches.

✏️ Your Task
Practise what you just learned about Common Beginner Mistakes (and How to Fix Them). Open Android Studio, type the examples by hand, change a value, and observe what happens.
Phase 12 of 12
Knowledge Check

Question 1. What is the value of val x = if (5 > 3) "big" else "small", and why is else needed?

x is "big". else is required because, used as an expression, if must produce a value in every case, including the "false" case.

Question 2. What does for (i in 1 until 4) print(i) print, and what changes with 1..4?

It prints 123, because until excludes the end value. With 1..4 it prints 1234, since .. includes the end.

Question 3. Why does a do-while loop with a false condition still run once?

Because do-while checks its condition after running the body. A while loop checks first and may never run.

Question 4. In a when used as an expression, which branch is chosen if two conditions match?

The first matching branch from the top. Kotlin stops at the first match and ignores the rest, so order matters.

Question 5. How do you stop an outer loop from inside an inner one?

Label the outer loop (outer@ for (...)) and use break@outer in the inner loop. A plain break only exits the innermost loop.

Go deeper: official resources

✏️ Your Task
Practise what you just learned about Knowledge Check. Open Android Studio, type the examples by hand, change a value, and observe what happens.
🏗️ Build It — Mini Project
Number Playground

Project goal: Build a small "Number Playground" program with five sections that each use a different tool from this lesson. It makes a good piece for your portfolio folder, because it shows clean, tested logic.

Requirements:

  1. Fare checker: write fareFor(age: Int): Int with when and ranges (0 to 5 free, 6 to 17 is ₦100, 18 to 59 is ₦200, 60 and above is ₦50) and print the fare for ages 4, 17, 18 and 64.
  2. Leap years: write isLeapYear and print every leap year from 1996 to 2012 on one line.
  3. FizzBuzz-style: print the numbers 1 to 20, but write Bounce for multiples of 4 and Tunde for multiples of 7 (and BounceTunde for numbers divisible by both, which will not occur before 28, so include 28 by looping 1 to 30 instead).
  4. Savings goal: use a while loop to count how many months it takes for a ₦5,000 monthly saving to reach at least ₦60,000, and print the answer.
  5. Triangle: print a right-angled triangle of 5 rows using nested loops or repeat.
  6. Every section starts with a heading line such as === Fares ===.

Stretch goal: Add isPrime from Problem 7 and print all primes up to 50.

Main.kt
fun fareFor(age: Int): Int = when (age) {
 in 0..5 -> 0
 in 6..17 -> 100
 in 18..59 -> 200
 in 60..130 -> 50
 else -> -1
}
fun isLeapYear(year: Int): Boolean =
 (year % 4 == 0 && year % 100 != 0) || year % 400 == 0
fun isPrime(n: Int): Boolean {
 if (n < 2) return false
 var i = 2
 while (i * i <= n) {
 if (n % i == 0) return false
 i++
 }
 return true
}
fun main() {
 println("=== Fares ===")
 for (age in listOf(4, 17, 18, 64)) {
 println("Age $age: ₦${fareFor(age)}")
 }
 println("=== Leap years 1996-2012 ===")
 for (year in 1996..2012) {
 if (isLeapYear(year)) print("$year ")
 }
 println()
 println("=== Bounce and Tunde ===")
 for (n in 1..30) {
 val text = when {
 n % 28 == 0 -> "BounceTunde"
 n % 4 == 0 -> "Bounce"
 n % 7 == 0 -> "Tunde"
 else -> n.toString()
 }
 print("$text ")
 }
 println()
 println("=== Savings goal ===")
 var saved = 0
 var months = 0
 while (saved < 60000) {
 saved += 5000
 months++
 }
 println("It takes $months months to save ₦$saved")
 println("=== Triangle ===")
 for (row in 1..5) {
 println("*".repeat(row))
 }
 println("=== Primes up to 50 ===")
 for (n in 1..50) {
 if (isPrime(n)) print("$n ")
 }
 println()
}

Reasoning through the output: the leap years from 1996 to 2012 are 1996, 2000, 2004, 2008 and 2012 (2000 is divisible by 400, and there is no century year problem in this range otherwise). The saving loop adds 5000 twelve times to reach exactly 60000. The program uses listOf as a preview of lesson 14: it simply gives a few values for the for loop to visit.

Expected output (trailing spaces omitted):

=== Fares ===
Age 4: ₦0
Age 17: ₦100
Age 18: ₦200
Age 64: ₦50
=== Leap years 1996-2012 ===
1996 2000 2004 2008 2012
=== Bounce and Tunde ===
1 2 3 Bounce 5 6 Tunde Bounce 9 10 11 Bounce 13 Tunde 15 Bounce 17 18 19 Bounce Tunde 22 23 Bounce 25 26 27 BounceTunde 29 30
=== Savings goal ===
It takes 12 months to save ₦60000
=== Triangle ===
*
**




=== Primes up to 50 ===
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

1

Open your finished project in Android Studio. Check that the .gitignore file the wizard created is in the project root. It keeps local.properties, build folders and keystores out of Git. Never commit passwords or signing keys.

2

Choose Git > Create Git Repository… (or VCS > Enable Version Control Integration in older versions), select the project folder, then open Git > Commit, tick every file, and write the message “Add Android lesson 09 project”.

3

On github.com click New repository, name it android-lesson-09-conditionals-and-loops-in-kotlin, set it to Public, leave Add a README unticked, and click Create repository.

4

Back in Android Studio choose Git > Manage Remotes…, add the repository URL as origin, then choose Git > Push… and push your main branch. Prefer the terminal? Run git remote add origin <your-url> then git push -u origin main.

5

Add a README.md with a screenshot of your app running and a short description. Employers and clients read READMEs first. Your project is now part of your public portfolio. 🎉

Lesson 09 complete! 🎉

You covered:

  • Lesson Introduction
  • Prerequisite Concepts
  • Conceptual Understanding: Decisions and Repetition
  • Conditionals: `if`, `else if`, `else`
  • Choosing with `when`
  • Ranges
  • Loops
  • Trying It in Android Studio
  • Practice: Kotlin Basics (Full Practice Set)
  • Guided Practice Exercises
  • Common Beginner Mistakes (and How to Fix Them)
  • Knowledge Check
All 72 lessons in Google Android Studio ·Techbase Academy ·© 2025–2026 Techbase Consultant Services, Ibadan
Esc
↑ ↓ to moveEnter to openEsc to close