Muren
buren geeft nu alle vakjes binnen de randen, ook als er een muur op staat.
Door een muur kan de robot niet. Daarom komt er een tweede if bij, die
de muren overslaat. De volgorde van de twee if's doet ertoe.
Voorspel
doolhof = [
"S.#",
".##",
"..E",
]
for r, k in [(0, 1), (0, 2), (2, 2)]:
if doolhof[r][k] != "#":
print(r, k, "is vrij")
Wat print dit programma?
Antwoord
0 1 is vrij
2 2 is vrij
Op (0, 2) staat een muur, dus die print hij niet. De E is geen muur: de
robot mag op de uitgang staan.
Zo werkt het
buren heeft nu twee if's. De eerste kijkt of het vakje binnen de randen
valt, de tweede of het geen muur is. De tweede staat ín de eerste: alleen een
vakje dat bestaat, kun je in het doolhof opzoeken.
Onderzoek
- Draai de code. Welke buren heeft
(2, 1)? Zoek ze op in het doolhof. - Waarom heeft de start
(0, 0)maar één buur? - Verander de eerste
ifinif True:, zodatburende randen niet meer controleert. Vraag danburen((0, 1)). Wat klopt er niet? - Vraag daarna, nog steeds zonder controle,
buren((4, 5)). Wat gebeurt er?
Antwoorden
[(1, 1), (3, 1), (2, 2)]: erboven, eronder en rechts. Links van(2, 1)staat een muur.- Boven en links van de start ligt de rand van het doolhof, en eronder staat
een muur. Alleen rechts,
(0, 1), is vrij. - Je krijgt
[(-1, 1), (1, 1), (0, 0), (0, 2)]. Het vakje(-1, 1)bestaat niet. Toch geeft Python geen fout: een negatieve index telt vanaf het eind, dusdoolhof[-1]is de onderste rij. Zonder controle springt de robot van de bovenrand naar de onderrand. - Python stopt met een foutmelding: rij 5 bestaat niet. Zie Er gaat iets mis.
Opdracht: muren rondom
Schrijf een functie muren(vakje) die telt hoeveel muren er naast een vakje
staan: erboven, eronder, links en rechts. De rand van het doolhof telt niet
als muur.
1
1
2
Begin klein, en breid de code stap voor stap uit:
- Draai de code:
murengeeft nog steeds 0, voor elk vakje. - Zet in
murende loop over de vier buren uitburen, en tel in de loop elke buur metteller = teller + 1. Nu print hij drie keer 4. - Tel alleen de buren binnen de randen, met de eerste
ifuitburen. Nu geeft(0, 0)er 2. - Tel alleen de buren waar een
#op staat. Nu print hij 1, 1 en 2.
Tip
Krijg je in stap 4 een foutmelding? Kijk dan in welke volgorde je de twee
if's hebt gezet.
Antwoord
Dit vervangt de functie muren en de prints in de editor:
def muren(vakje):
rij, kolom = vakje
teller = 0
for r, k in [(rij - 1, kolom), (rij + 1, kolom), (rij, kolom - 1), (rij, kolom + 1)]:
if r >= 0 and r < len(doolhof) and k >= 0 and k < len(doolhof[0]):
if doolhof[r][k] == "#":
teller = teller + 1
return teller
print(muren((2, 1)))
print(muren((0, 0)))
print(muren((3, 5)))
1
1
2
muren is bijna buren, met == in plaats van != en een teller in plaats
van een lijst. (3, 5) heeft een muur erboven en een links, en rechts de rand.
Er gaat iets mis
IndexError: list index out of range
Oorzaak: je vraagt een rij die niet bestaat. Het doolhof heeft rij 0 tot
en met 4; rij 5 ligt onder de onderrand. Dat gebeurt als je in het doolhof
kijkt voordat je de randen hebt gecontroleerd, bijvoorbeeld met de twee
if's in de verkeerde volgorde. Bij een kolom die niet bestaat krijg je
IndexError: string index out of range, want een rij is een tekst.
Oplossing: kijk eerst of het vakje binnen het doolhof ligt.
# FOUT
doolhof = ["S.", ".E"]
r = 2
print(doolhof[r][0])
# GOED
doolhof = ["S.", ".E"]
r = 2
if r >= 0 and r < len(doolhof):
print(doolhof[r][0])
Een negatieve rij geeft geen fout, maar wel een verkeerd vakje: doolhof[-1]
is de onderste rij. Daarom controleert buren ook op r >= 0.
Door naar doodlopende vakjes.