Rochambeau¶
Opdracht: Rochambeau
De opgave vraagt één potje steen, papier en schaar: de gebruiker kiest een wapen, de computer kiest er willekeurig een, en het programma drukt af wie er wint.
Deze uitwerking blijft bij die drie wapens en speelt eerlijk. Koos jij andere wapens, of maakte je een spel waarin de speler altijd wint - de opgave geeft je die ruimte - dan is jouw programma daarom niet fout. Kijk in dat geval naar de opbouw hieronder en niet naar de woorden.
Op één regel na gebruikt de uitwerking alleen wat je deze week hebt gezien: input,
print, if, elif, else en ==. Die ene regel is from random import choice uit
de begincode, en die is met opzet een vooruitwijzing: neem hem voor nu aan. Hij
haalt de functie choice op, die een willekeurig element uit een lijst kiest. Wat een
module en een import precies zijn, komt in week 3.
Het commentaar uit de begincode staat hieronder niet, omdat de uitleg boven elk programma staat - in je eigen code mag je het gerust laten staan.
De cellen hieronder vragen om invoer en worden daarom niet uitgevoerd bij het maken van deze pagina. Wil je ze zien draaien, kopieer ze dan naar je eigen bestand.
De uitwerking¶
Het gaat om negen combinaties: drie keuzes van jou maal drie van de computer. Die negen hoef je niet stuk voor stuk op te schrijven, als je de vragen in de goede volgorde stelt.
Stel eerst de makkelijkste vraag: koos de computer hetzelfde als jij? Dan is het gelijkspel en valt er verder niets te vergelijken. Daarmee liggen drie van de negen combinaties al vast.
Blijft over: de computer koos iets anders dan jij. Dan bepaalt wat de computer koos welke ene vraag er nog overblijft. Koos de computer steen, dan heb jij papier of schaar - schaar verliest van steen, en anders heb je papier en win je. Zo houd je drie takken over met elk één vraag erin.
De laatste tak is elif comp == "schaar": en geen else:. Allebei mag: comp komt
uit choice en kan alleen steen, papier of schaar zijn, dus wie hier aankomt heeft
schaar. Met de naam erbij lees je in alle drie de takken waar het over gaat.
from random import choice
user = input("Kies een wapen (steen, papier of schaar): ")
comp = choice(["steen", "papier", "schaar"])
print("De gebruiker (jij) koos", user)
print("De computer (ik) koos", comp)
if comp == user:
print("Gelijkspel!")
elif comp == "steen":
if user == "schaar":
print("Steen verslaat schaar, ik win!")
else:
print("Papier verslaat steen, jij wint!")
elif comp == "papier":
if user == "steen":
print("Papier verslaat steen, ik win!")
else:
print("Schaar verslaat papier, jij wint!")
elif comp == "schaar":
if user == "papier":
print("Schaar verslaat papier, ik win!")
else:
print("Steen verslaat schaar, jij wint!")
Twee andere vormen¶
Dezelfde uitwerking is op meer manieren op te schrijven, en schreef je een van de twee hieronder, dan deed je het goed: alle drie de programma’s stellen dezelfde vragen en geven op elke combinatie hetzelfde antwoord.
Waarin ze verschillen is hoeveel ze hardop zeggen. De vorm hierboven benoemt elk geval apart - steen, papier, schaar - en daarom is het de vorm om nu te schrijven: je leert deze week condities, en dan helpt het als je in de code kunt lezen waar elke tak over gaat. De twee hieronder zeggen minder. De eerste zegt hetzelfde met meer regels, de tweede zegt alles in één voorwaarde.
Alleen met if en else¶
elif is een afkorting: het is een if binnen de else van de vorige vraag. Schrijf
je die afkorting uit, dan krijg je het programma hieronder - dezelfde drie vragen over
comp, alleen staat elke volgende vraag nu binnen de else van de vorige.
Daarmee zie je meteen waarvoor de afkorting goed is. Dit programma is vijf regels langer dan het vorige, en zijn diepste regel ligt vijf niveaus naar rechts tegen twee hierboven. Elk wapen dat je erbij zou verzinnen kost er nog een.
from random import choice
user = input("Kies een wapen (steen, papier of schaar): ")
comp = choice(["steen", "papier", "schaar"])
print("De gebruiker (jij) koos", user)
print("De computer (ik) koos", comp)
if comp == user:
print("Gelijkspel!")
else:
if comp == "steen":
if user == "schaar":
print("Steen verslaat schaar, ik win!")
else:
print("Papier verslaat steen, jij wint!")
else:
if comp == "papier":
if user == "steen":
print("Papier verslaat steen, ik win!")
else:
print("Schaar verslaat papier, jij wint!")
else:
# "schaar" is de laatste mogelijkheid, dus achter deze if
# hoeft geen else meer
if comp == "schaar":
if user == "papier":
print("Schaar verslaat papier, ik win!")
else:
print("Steen verslaat schaar, jij wint!")
Compacter, met and en or¶
De computer wint bij precies drie van de negen combinaties: steen tegen schaar, papier
tegen steen, en schaar tegen papier. Die drie kan je ook in één voorwaarde zetten, met
and voor “allebei waar” en or voor “een van beide”. Wint de computer niet en is het
geen gelijkspel, dan win jij - daar is geen aparte vraag meer voor nodig.
Haakjes ken je al uit het college, twee keer: als groepering in de operatorentabel, en
als het paar om een conditie dat in Python niet verplicht is. Hier doen ze allebei
tegelijk. Elk binnenste paar groepeert - het zegt welke twee vergelijkingen bij elkaar
horen voordat or ze naast elkaar zet - en het buitenste paar, direct achter elif,
doet er iets bij: zolang een haakje nog niet gesloten is, loopt de regel door op de
volgende. Zo past de voorwaarde over vier regels in plaats van op één hele lange, en
staat de : pas achter het sluithaakje.
Deze vorm is met tien regels de kortste van de drie, en toch niet de vorm om nu te schrijven: nergens staat meer welk geval je te pakken hebt, en om dat te weten moet je de voorwaarde regel voor regel nalopen. Herken haar dus; schrijf haar nog niet. Bij de uitbreiding hieronder verandert die afweging.
from random import choice
user = input("Kies een wapen (steen, papier of schaar): ")
comp = choice(["steen", "papier", "schaar"])
print("De gebruiker (jij) koos", user)
print("De computer (ik) koos", comp)
if comp == user:
print("Gelijkspel!")
elif (
(comp == "steen" and user == "schaar")
or (comp == "papier" and user == "steen")
or (comp == "schaar" and user == "papier")
):
print("Ik win!")
else:
print("Jij wint!")
Uitbreidingen¶
RPS-5 (RPSSL)¶
Met vijf wapens gaat het om vijfentwintig combinaties, en verslaat elk wapen er precies twee: steen verslaat schaar en hagedis, papier verslaat steen en Spock, schaar verslaat papier en hagedis, Spock verslaat schaar en steen, en hagedis verslaat papier en Spock.
Hier verandert de afweging. De opzet blijft dezelfde - eerst gelijkspel, dan de gevallen
waarin de computer wint, en anders win jij - maar de drie vormen groeien niet even hard
mee. Elk geval benoemen kost nu vijf takken en 27 regels; met alleen if en else word
je 32 regels lang en zeven niveaus diep. De compacte voorwaarde groeit van tien regels
naar twaalf, met per regel één wapen. Dát is waar zij voor is: het punt waarop benoemen
niet meer betaalt.
Spock schrijf je met een hoofdletter, in de code en in je invoer. De opgave zegt erbij
dat je mag aannemen dat de gebruiker foutloos typt; spock met een kleine letter komt
er dus niet door.
from random import choice
user = input("Kies een wapen (steen, papier, schaar, Spock of hagedis): ")
comp = choice(["steen", "papier", "schaar", "Spock", "hagedis"])
print("De gebruiker (jij) koos", user)
print("De computer (ik) koos", comp)
if comp == user:
print("Gelijkspel!")
elif (
(comp == "steen" and (user == "schaar" or user == "hagedis"))
or (comp == "papier" and (user == "steen" or user == "Spock"))
or (comp == "schaar" and (user == "papier" or user == "hagedis"))
or (comp == "Spock" and (user == "schaar" or user == "steen"))
or (comp == "hagedis" and (user == "papier" or user == "Spock"))
):
print("Ik win!")
else:
print("Jij wint!")
RPS-25 en RPS-101 werken op precies dezelfde manier, maar de voorwaarde groeit mee: bij
RPS-25 verslaat elk wapen er twaalf, en dat zijn driehonderd combinaties waarin de
computer wint. Die schrijf je niet meer in een if. Je wilt de regels dan náást het
programma zetten, in een datastructuur, en daarvoor heb je technieken nodig die verderop
in de cursus komen.
De uitbreiding Blijven spelen vraagt een lus (while), en die komt in week 4. Het
practicum laat daar zelf twee patronen zien; deze uitwerking stopt bij het spel zelf.