Iteration (loopar)

Iteration är ett annat ord för upprepning. Detta använder man när någonting ska utföras flera gånger. Det finns olika sätt att bestämma hur många gånger koden ska upprepas.

Datorer är väldigt bra på att upprepa samma sak många gånger. Dom tröttnar inte på det som vi människor ofta gör. Till exempel om jag vill visa en animation av ett hjärta som slår går det bra med en upprepning av två bilder.

basic.showIcon(IconNames.SmallHeart)
basic.showIcon(IconNames.Heart)
basic.showIcon(IconNames.SmallHeart)
basic.showIcon(IconNames.Heart)
basic.showIcon(IconNames.SmallHeart)
basic.showIcon(IconNames.Heart)
basic.showIcon(IconNames.SmallHeart)
basic.showIcon(IconNames.Heart)

Länk till koden.

Men oj vad många block det blev. För ett hjärta som slår fyra gånger blev det nio block att pyssla ihop. Kan vi inte göra det enklare? Javisst! Ett enkelt sätt att få det att hända många gånger är att lägga det i ”för alltid”-blocket (kategori Grundläggande). Då behöver vi bara två ikon-block som upprepas för alltid.

basic.forever(function () {
    basic.showIcon(IconNames.SmallHeart)
    basic.showIcon(IconNames.Heart)
})

Länk till koden.

Ett bestämd antal gånger

Men om vi nu inte vill att det upprepas för alltid, men ett bestämd antal gånger? Då finns det också ett block för det, och den hittar vi kategori Loopar. ”upprepa 4 gånger, gör” är ett block som utför allt i den, så många gånger som står i det gråa fältet. Så denna kod gör precis samma som det första exemplet, men använder fem färre block. Och vi kan super enkelt ändra hur många gånger det ska upprepas.

for (let i = 0; i < 4; i++) {
    basic.showIcon(IconNames.SmallHeart)
    basic.showIcon(IconNames.Heart)
}

Länk till koden.

Beroende på en variabel

Att enkelt ändra på hur många gånger hjärtan slår är redan smidigt, men det blir ännu bättre när man kan ändra på det medans programmet körs. Följande program använder sig av en variabel som heter ”antalSlag”. Den börjar med värdet 1, och ökar varje gång man trycker på A-knappen. När man sen trycker på B-knappen slår hjärtan så många gånger som just då ”antalSlag” innehåller för värde. I ”upprepa”-blocket ser vi att siffran fyra är ersätt med variabel blocket, som ger det värdet som finns i variabeln.

let antalSlag = 1
input.onButtonPressed(Button.A, () => {
    antalSlag += 1
    basic.showNumber(antalSlag)
})
input.onButtonPressed(Button.B, () => {
    for (let i = 0; i < antalSlag; i++) {
        basic.showIcon(IconNames.SmallHeart)
        basic.showIcon(IconNames.Heart)
    }
})

Länk till koden.

Beroende på ett villkor

Ett annat sätt att få kod att upprepas ett visst antal gånger är med hjälp av villkor. Med ett ”medan sant”-blocket (while true) kommer allt inuti hända så länge villkoret (som kommer istället för platshållaren ”sant”) resulterar i svaret sant. I följande exempel slår hjärtat bara så länge som A-knappen är nertryckt (villkoret ”knapp A trycks” är sant).

basic.forever(() => {
    while (input.buttonIsPressed(Button.A)) {
        basic.showIcon(IconNames.SmallHeart)
        basic.showIcon(IconNames.Heart)
    }
    basic.clearScreen()
})

Länk till koden.

Flytta en pixel

En annan kul grej vi kan göra med upprepning baserad på villkor är att använda en variabel i det villkoret. Värdet av variabeln kan ändra på sig när loopen körs, så att någon gång villkoret blir falskt och loopen slutar. I nästa koden kommer vi, när Knapp A trycks, tända en LED lampa på skärmen, med en viss x- och y-koordinat. X-koordinaten styrs av en variabel (”xPosition”), som varje gång börjar på 0 och ökar med 1 varje genomgång av loopen. Kan du lista ut vad x kommer innehålla som högsta värde?

let xPosition = 0
input.onButtonPressed(Button.A, () => {
    xPosition = 0
    while (xPosition < 5) {
        led.plot(xPosition, 0)
        xPosition += 1
        basic.pause(300)
        basic.clearScreen()
    }
})

Länk till koden.

Vi ser att xPosition börjar med 0, det är för att koordinaterna på micro:bit börjar räkna med 0. I varje iteration visas pixeln, och höjs xPosition med 1. Sen upprepas det igen, om xPosition är mindre än 5. Så den sista pixel som blir tänd har x-koordinat 4. Efter det höjs xPosition till 5, men när då villkoret blir kontrollerat en gång till är det falskt (5 är inte mindre än 5), och är koden färdigt.

Kan det bli kortare?

Den här typen av loop, där en variabel skapas, används inom loopen, ändras på varje steg, och är del av villkoret, används ganska ofta inom programmering. Det är därför det finns en variant av loopar som gör precis detta. Den kallas ”för loop” (for loop) och ser ut så här:

for (let plats = 0; plats <= 4; plats++) {
    
}

Standard kommer den med en variabel som heter ”plats”, vilken kommer börja med värdet 0, och ökar varje loop med 1, till och med värdet 4 (den innehåller 4 i sista genomgång).

I JavaScript heter loopen ”for” och har den tre delar inom sina parenteser, som är separerad med ;. Första delen är där variabeln är skapad och får sitt första värde (let plats = 0). Andra delen är villkoret (plats <= 4). Här ser vi att det är ”mindre än eller lika med”, vilket gör att 4 är inkluderad som sista genomgång av loopen. Sista delen är vad som ska hända efter varje genomgång, vilket i det här fall är öka plats med 1 (plats++). ”plats++” är bara en förkortad sätt att skriva plats = plats + 1. (Läs mer om det här.) Genom att ändra på dom tre delar kan man få loopen att genomföras på många olika sätt. Detta är ett tydligt fall där JavaScript ger mer möjligheter än blockprogrammering.

En rolig detalj är att blocket som vi använde i början, ”upprepa 4 gånger” faktiskt översätts till samma typ av for-loop. Det är bara att man inte ser variabeln i block-läget. Villkoret är också skriven i ”mindre än” format (istället för ”mindre än eller lika med”), vilket är också hur det används väldigt ofta inom programmering.

for (let i = 0; i < 4; i++) {
    
}

Men! Tillbaka till våra pixlar. Hur skulle den koden se ut när vi använder en för-loop (for loop)? Det blir mycket kortare. Man behöver inte använda variabelnamn ”plats”, så jag bytte den till ”xPosition”. Den här koden gör precis samma som våra förre pixel koden, men med mindre block eller rader kod.

input.onButtonPressed(Button.A, () => {
    for (let xPosition = 0; xPosition <= 4; xPosition++) {
        led.plot(xPosition, 0)
        basic.pause(300)
        basic.clearScreen()
    }
})

Länk till koden.

Dubbelt så kul

Om man trycker att det var kul att flytta en pixel vänster till höger, kommer det nu bli dubbelt så kul. För att vi kan också styra y-koordinaten. Ska vi flytta en pixel över hela skärmen? Det kan man göra med hjälp av två loopar, där en loop ligger på insidan av den andra. Hur funkar det? Se om du kan följa vad som händer i denna kod:

input.onButtonPressed(Button.A, () => {
    for (let yPosition = 0; yPosition <= 4; yPosition++) {
        for (let xPosition = 0; xPosition <= 4; xPosition++) {
            led.plot(xPosition, yPosition)
            basic.pause(300)
            basic.clearScreen()
        }
    }
})

Länk till koden.

För att förstå vad som händer kan vi läsa oss igenom koden, i samma ordning som micro:bit läser, och se vad som händer steg för steg. Koden börjar när A-knappen är tryckt. Vi hoppar in i yttersta loopen. Där skapas variabeln yPosition med värdet 0. Nu hoppar vi in i innersta loopen och skapa variabeln xPosition med värdet 0. Näst tänds lampan med koordinaterna som vi har i variablerna, så (0,0). Efter en liten paus rensas skärmen, vilket gör att lampan släcks igen. Då hoppar vi tillbaka till början av innersta loopen, och xPosition höjs med 1. Nu tänds en lampa igen, med koordinaterna som dom är nu: punkt (1,0). Skärmen rensas igen. Innersta loopen upperpas en gång till, med xPosition lika med 2… Detta fortsätter tills loopen är genomförd med xPosition lika med 4. Då är innersta loopen färdigt. Nu hoppar vi tillbaka till början av yttersta loopen, och ökar yPosition med 1. Då kommer vi fram till innersta loopen igen. xPosition skapas på nytt, med värdet 0 igen. In i loopen tänds en lampa igen med koordinaterna som finns i variablerna, vilket nu blir (0,1). Innersta loopen körs en gång till och ger punkt (1,1). Detta fortsätter till punkt (4,1). Då är den färdigt igen och hoppar vi till början av yttersta loopen igen med yPosition höjd till 2. Man blir nästan snurrigt av alla upprepningar. Vi kan skriva ner i en tabell hur variablerna, och med dom koordinatpunkten, förändras under programmets körning.

xPositionyPositionPunkt
00(0,0)
10(1,0)
20(2,0)
30(3,0)
40(4,0)
01(0,1)
11(1,1)
21(2,1)
31(3,1)
41(4,1)
02(0,2)
12(1,2)
22(2,2)
32(3,2)
42(4,2)
03(0,3)
13(1,3)
23(2,3)
33(3,3)
43(4,3)
04(0,4)
14(1,4)
24(2,4)
34(3,4)
44(4,4)
Senast ändrad 2018-12-09