2  H2: Knoppen en keuzes — Getal raden

Een computer volgt niet altijd dezelfde weg. Soms moet hij kiezen: doe dit, of doe dat. Denk aan een stoplicht — als het groen is, rij je door; als het rood is, stop je. In dit hoofdstuk leer je hoe je zulke keuzes in Swift schrijft, hoe je een knop maakt die iets doet, en hoe je een getal kunt invoeren. Aan het einde bouw je je eerste echte spel: Getal raden.

2.1 Wat gaan we bouwen?

De app kiest een geheim getal tussen 1 en 100. Jij raadt welk getal het is. De app zegt “te laag”, “te hoog” of “goed geraden!” — totdat je het juiste getal hebt gevonden. De app telt ook bij hoeveel pogingen je nodig hebt gehad.

Screenshot van de getal-raden app met een tekstveld en een raad-knop

Het getal-raad-spel

2.2 Playground-voorbeeld

Open Xcode, maak een nieuwe Playground aan via File > New > Playground, kies platform macOS en template Blank. Sla hem op als Playground Hoofdstuk 2.

Typ dit over:

let geheim = 42
let gok = 60

if gok < geheim {
    print("Te laag!")
} else if gok > geheim {
    print("Te hoog!")
} else {
    print("Goed geraden!")
}

Druk op play. Je ziet “Te hoog!” — want 60 is groter dan 42. Verander gok in 30 en druk opnieuw op play. Nu staat er “Te laag!”. Probeer 42 — dan krijg je “Goed geraden!”.

Dit is de kern van het spel. Nu gaan we dit uitleggen.

2.3 Als dit, dan dat

In Swift schrijf je een keuze met if:

if leeftijd >= 18 {
    print("Je mag mee naar de film")
}

Alles tussen de accolades { } wordt alleen uitgevoerd als de voorwaarde klopt. Klopt hij niet, dan slaat Swift dat stuk over.

Wil je ook iets doen als de voorwaarde niet klopt? Dan voeg je else toe:

if leeftijd >= 18 {
    print("Je mag mee naar de film")
} else {
    print("Je bent nog te jong")
}

En als je meerdere keuzes wilt checken, gebruik je else if:

if gok < geheim {
    print("Te laag!")
} else if gok > geheim {
    print("Te hoog!")
} else {
    print("Goed geraden!")
}

Swift doorloopt de voorwaarden van boven naar beneden en stopt zodra er één klopt.

2.3.1 Vergelijkingstekens

Om twee waarden te vergelijken gebruik je deze tekens:

Teken Betekenis Voorbeeld
== Is gelijk aan score == 10
!= Is niet gelijk aan naam != "Pim"
< Is kleiner dan gok < geheim
> Is groter dan gok > geheim
<= Is kleiner dan of gelijk aan leeftijd <= 12
>= Is groter dan of gelijk aan leeftijd >= 18

Let op: == is niet hetzelfde als =. Met = geef je een waarde, met == vergelijk je.

NoteVerdieping: Bool en voorwaarden

Een vergelijking zoals gok < geheim levert altijd een Bool op — true of false. Je kunt dat ook direct opslaan:

let teHoog = gok > geheim   // true of false

if werkt altijd met een Bool. Schrijf je if teHoog { ... }, dan controleert Swift of teHoog gelijk is aan true.

2.4 Onthouden wat er verandert

In H1 leerde je var voor een wisbordje. In een app wil je soms dat het scherm verandert als de waarde op het bordje verandert. Daarvoor gebruik je @State.

Denk aan een memobriefje op de koelkast: “Score: 0”. Als je punten scoort, schrijf je het briefje over. SwiftUI kijkt constant naar dat briefje — zodra het verandert, vernieuwt het scherm vanzelf.

@State private var aantalPogingen = 0

Elke keer als aantalPogingen verandert, tekent SwiftUI het scherm opnieuw. Zonder @State ziet SwiftUI de verandering niet en blijft het scherm hetzelfde.

2.5 Tekst invoeren

Tot nu toe toonde je alleen tekst. Maar in het spel moet de speler een getal invoeren. Daarvoor gebruik je TextField:

TextField("Jouw gok", text: $invoer)
    .textFieldStyle(.roundedBorder)
    .frame(width: 150)

Het dollarteken $ voor invoer is belangrijk: daarmee zeg je “koppel dit tekstveld aan de variabele invoer”. Wat de speler typt, komt in invoer te staan — en andersom.

TextField geeft altijd tekst terug, ook als je een getal typt. Om er een Int van te maken gebruik je Int(invoer). Dat kan mislukken — als iemand “abc” typt, is er geen getal. Daarom gebruik je guard:

guard let gok = Int(invoer) else {
    boodschap = "Vul een getal in."
    return
}

guard controleert of het omzetten lukt. Lukt het niet, dan voert Swift de else-tak uit en stopt de rest van de code.

2.6 Het spel bouwen

Open Xcode en maak een nieuw macOS App-project aan. Noem het GetalRaden. Klik op ContentView.swift en vervang alles door:

import SwiftUI

struct ContentView: View {
    @State private var geheimGetal = Int.random(in: 1...100)
    @State private var invoer = ""
    @State private var boodschap = "Ik denk aan een getal tussen 1 en 100."
    @State private var aantalPogingen = 0
    @State private var gewonnen = false

    var body: some View {
        VStack(spacing: 20) {
            Text("Getal raden")
                .font(.largeTitle)
                .bold()

            Text(boodschap)

            if !gewonnen {
                TextField("Jouw gok", text: $invoer)
                    .textFieldStyle(.roundedBorder)
                    .frame(width: 150)

                Button("Raden") {
                    raad()
                }
                .buttonStyle(.borderedProminent)
            }

            Text("Pogingen: \(aantalPogingen)")
                .foregroundStyle(.secondary)

            Button("Nieuw spel") {
                nieuwSpel()
            }
        }
        .padding()
        .frame(width: 300, height: 280)
    }

    func raad() {
        guard let gok = Int(invoer) else {
            boodschap = "Vul een getal in."
            return
        }
        aantalPogingen += 1
        invoer = ""

        if gok < geheimGetal {
            boodschap = "Te laag! Probeer hoger."
        } else if gok > geheimGetal {
            boodschap = "Te hoog! Probeer lager."
        } else {
            boodschap = "Goed geraden in \(aantalPogingen) pogingen!"
            gewonnen = true
        }
    }

    func nieuwSpel() {
        geheimGetal = Int.random(in: 1...100)
        invoer = ""
        boodschap = "Ik denk aan een getal tussen 1 en 100."
        aantalPogingen = 0
        gewonnen = false
    }
}

Druk op play en speel het spel.

2.6.1 Wat doet de code?

Int.random(in: 1...100) kiest een willekeurig heel getal tussen 1 en 100. Elke keer als het spel opnieuw begint, kiest Swift een ander getal.

func raad() is een functie — een stukje code met een naam. Je kunt het aanroepen door de naam te schrijven: raad(). Alles tussen de accolades wordt dan uitgevoerd. Functies gebruik je om code op te ruimen: in plaats van twintig regels in de knop-actie, roep je gewoon raad() aan.

func nieuwSpel() zet alles terug naar het begin. Dezelfde aanpak: één naam, en de knop “Nieuw spel” roept hem aan.

if !gewonnen — het uitroepteken ! voor een Bool betekent “niet”. !gewonnen is dus “niet gewonnen”. Het tekstveld en de raad-knop zijn alleen zichtbaar zolang het spel nog bezig is.

NoteVerdieping: functies

Een func is een manier om code een naam te geven en op te ruimen. Je schrijft de code één keer en kunt hem daarna op meerdere plekken aanroepen.

func begroet() {
    print("Hallo!")
}

begroet()   // roept de functie aan
begroet()   // en nog een keer

Functies kunnen ook iets meekrijgen — een parameter — en iets teruggeven:

func dubbelOp(_ getal: Int) -> Int {
    return getal * 2
}

let uitkomst = dubbelOp(5)  // uitkomst is 10

In latere hoofdstukken kom je functies overal tegen.

2.7 Apple documentatie

Alles over if, else en vergelijken vind je hier:

developer.apple.com/documentation/swift/control-flow

En over TextField:

developer.apple.com/documentation/swiftui/textfield

2.8 Samenvatting

In dit hoofdstuk heb je geleerd hoe je keuzes maakt met if en else, hoe je een waarde onthoudt met @State, en hoe je invoer van de speler verwerkt met TextField. Daarmee heb je je eerste echte spel gebouwd.

Begrip Betekenis
if Voer dit uit als de voorwaarde klopt
else Voer dit uit als de voorwaarde niet klopt
== Vergelijk of twee waarden gelijk zijn
@State Waarde die het scherm vernieuwt als hij verandert
TextField Invoerveld waar de gebruiker tekst kan typen
func Een stukje code met een naam dat je kunt aanroepen
Int.random(in:) Kies een willekeurig heel getal uit een reeks
guard Controleer een voorwaarde; stop als die niet klopt

2.9 Opdracht

Maak een nieuwe Xcode Playground aan en geef hem de naam Playground Hoofdstuk 2. Schrijf een mini-versie van het spel zonder scherm — alleen met print(). Kies een vast geheim getal en schrijf drie gokken met if/else if/else. Laat de computer voor elke gok afdrukken of hij te laag, te hoog of goed is.

let geheim = 73
let gok1 = 50
let gok2 = 80
let gok3 = 73

// Schrijf hier de if/else-code voor elke gok

Xcode Playground met drie gokken en de bijbehorende uitvoer

Het resultaat van de opdracht in Xcode Playground