Een spel onthouden
De score van elke zet heeft nu een plek. Na een spel werkt de computer die
scores bij: elke zet van de winnaar een punt erbij, elke zet van de verliezer
een punt eraf. Nieuw is not in, en een spel dat al klaarstaat in verborgen
code onder de editor.
Voorspel
score = {}
for zet in [(10, 1), (9, 2), (10, 1)]:
if zet not in score:
score[zet] = 0
score[zet] = score[zet] + 1
print(score)
Wat print dit programma?
Antwoord
{(10, 1): 2, (9, 2): 1}
De eerste keer staat (10, 1) nog niet in score, dus zet de loop hem eerst
op 0 en telt er dan 1 bij. De derde keer staat hij er al, en wordt hij 2.
Zo werkt het
zet not in score is het omgekeerde van zet in score: het is waar als de
zet nog geen sleutel is. Dan zet de loop hem eerst op 0.
Het spelen staat al klaar, in de verborgen code onder de editor:
speel_tegen_jezelf(score, ontdekken)speelt één spel met 10 lucifers, met twee spelers"a"en"b"die allebei dezelfdescoregebruiken. Hij geeft de zetten van elke speler terug, en wie er verloor.- Bij elke beurt kiest
kiesmeestal de zet met de hoogste score. Maar bij kansontdekkenkiest hij een willekeurige zet, om ook iets nieuws te proberen. Wat dat doet, zie je in ontdekken; hier staat hij op 0.2. beste_zet(score, stapel)geeft het aantal lucifers van de zet met de hoogste score: een getal, zoalsslimdat ook geeft.
zetten is een dictionary met voor elke speler een lijst van zetten, en elke
zet is een tuple (stapel, pak).
Onderzoek
- Draai de code. Hoeveel zetten deed elke speler?
- Reken het spel na vanaf 10 lucifers. Pakte de verliezer de laatste?
- Bij 6 lucifers pakte
"a"er 3, terwijlbeste_zetbij een legescorealtijd 1 kiest. Hoe kan dat? - Verander de seed in 1. Wat valt je op aan de zetten?
Wat zie je?
[(10, 1), (8, 1), (6, 3), (2, 1)]
[(9, 1), (7, 1), (3, 1), (1, 1)]
verliezer: b
Antwoorden
- Allebei vier.
- Ja: 10, 9, 8, 7, 6, 3, 2, 1, en dan pakt
"b"de laatste."b"verliest. - Die zet was ontdekken: met kans 0.2 kiest
kieseen willekeurige zet. - Iedereen pakt steeds 1. De score is nog leeg, dus
beste_zetkiest overal 1, en met deze seed ontdekt niemand iets.
Opdracht: een spel onthouden
Werk na het spel uit de editor de score bij: elke zet van de winnaar een punt
erbij, elke zet van de verliezer een punt eraf. Print daarna score:
{(10, 1): 1, (8, 1): 1, (6, 3): 1, (2, 1): 1, (9, 1): -1, (7, 1): -1, (3, 1): -1, (1, 1): -1}
Begin klein, en breid de code stap voor stap uit:
- Draai de code: je ziet de zetten van
"a"en"b", en wie er verloor. - Loop met
for speler in zettenover de spelers, en daarin overzetten[speler]. Print elke zet. - Zet elke zet in
scoreop 0 als hij er nog niet in staat, en printscorena de loops. - Geef een zet van de verliezer een punt eraf, en een zet van de winnaar een punt erbij.
Tip
Bij stap 4 weet je in de binnenste loop van wie de zet is: dat is speler.
Vergelijk die met verliezer.
Antwoord
Dit komt onder de code van de editor:
for speler in zetten:
for zet in zetten[speler]:
if zet not in score:
score[zet] = 0
if speler == verliezer:
score[zet] = score[zet] - 1
else:
score[zet] = score[zet] + 1
print(score)
{(10, 1): 1, (8, 1): 1, (6, 3): 1, (2, 1): 1, (9, 1): -1, (7, 1): -1, (3, 1): -1, (1, 1): -1}
Elke zet kwam in dit spel één keer voor, dus elke score is 1 of -1. Na meer spellen tellen de punten op.
Er gaat iets mis
KeyError: (10, 1)
Oorzaak: score[zet] + 1 leest de score van een zet die nog niet in de
dictionary staat. Er is nog niets om 1 bij op te tellen.
Oplossing: zet een nieuwe zet eerst op 0.
# FOUT
score = {}
zet = (10, 1)
score[zet] = score[zet] + 1
# GOED
score = {}
zet = (10, 1)
if zet not in score:
score[zet] = 0
score[zet] = score[zet] + 1
Meer uitleg: Zo werkt het.
Door naar leren uit duizend spellen.