← RU Pythoncursus

Galgje

In deze opdracht gaan we het galgje-spel bouwen. We zullen het stapje voor stapje opbouwen, maar je kunt zoiets natuurlijk zo uitgebreid maken als je zelf wilt. Als je merkt dat de opdracht toch nog wat lastig is kan je ervoor kiezen om de laatste delen voor nu achter wegen te laten. Probeer het steeds zo te programmeren dat je tussendoor zo veel mogelijk stukjes kunt testen zonder dat het spel helemaal af hoeft te zijn.

Voordat we gaan beginnen met het eigenlijke galgje-spel gaan we eerst even een hulpfunctie maken die je straks nodig gaat hebben. Zoals je in de huiswerkopdrachten gezien hebt kun je strings (stukjes tekst) niet eenvoudig bewerken. Toch is het voor galgje handig als we in een string een puntje zouden kunnen vervangen door een letter.

  1. Maak nu de functie vervang(woord, n, c) die de letter op de n-de plek van het woord vervangt door de letter in de variabele c. Dit kan je bijvoorbeeld opdelen in een paar stappen: knip het woord in de stukken die je nodig hebt, plak ze weer aan elkaar en lever het resultaat als uitvoer op. Let op: we beginnen altijd bij 0 te tellen. vervang(‘abcd’, 1, ‘e’) levert dus aecd op.

Als je ervan overtuigd bent dat je functie goed werkt gaan we aan het spel zelf beginnen. We beginnen met een paar variabelen waar we de toestand van het spel in opslaan.

  1. Maak een paar variabelen aan met duidelijke namen om bij te houden wat het te raden woord is, hoeveel kansen de gebruiker nog heeft en wat het huidige geraden woord is. Kies logische beginwaarden; in eerste instantie een vast woord (bijvoorbeeld "radboud"). Voor ongeraden letters is het handig om puntjes te gebruiken.

Gedurende het spel zal de variabele die het huidige geraden woord bevat steeds meer gaan lijken op het te raden woord. We gaan natuurlijk de functie die je bij 1. hebt gemaakt gebruiken om steeds een letter te vervangen.

Het spel zelf komt eigenlijk neer op één grote loop. Bij elke iteratie van de loop is de gebruiker één keer aan de beurt.

  1. Heb je hier een while-loop of een for-loop nodig? Aan welke condities moet zijn voldaan voordat de gebruiker nog een keer aan de beurt mag komen? Hoe bepaal je of 'ie niet al verloren heeft? En hoe bepaal je of 'ie gewonnen heeft? Combineer dit, en schrijf in één regel de 'kop' van de loop op -- de inhoud komt zometeen.

Nu gaan we stapje voor stapje de loop invullen.

  1. Toon de huidige speltoestand (aantal pogingen, geraden woord tot nu toe) aan de gebruiker, en vraag om een nieuwe letter. Je hoeft geen rekening te houden met foutieve input (getallen, hele zinnen), maar dat mag je natuurlijk wel proberen.

Aan de hand van de letter die de gebruiker heeft ingevuld kunnen we twee gevallen onderscheiden: de letter zit in het woord, of de letter zit niet in het woord. In Python kan je in een if-statement met de operator in controleren of een letter in een string voorkomt (en algemener: of een element in een lijst of verzameling voorkomt). Zo zal if ‘a’ in ‘abc’ als resultaat True opleveren, terwijl if ‘z’ in ‘abc’ juist False oplevert. Je kunt dit overigens ook gebruiken voor deelwoorden: ‘bc’ in ‘abc’ is waar, maar ‘ac’ in ‘abc’ of ‘ba’ in ‘abc’ niet.

  1. Onderscheid deze twee gevallen, en vul alvast in wat er moet gebeuren wanneer de gebruiker een letter raadt die niet in het woord voorkomt.

Wanneer een letter wel in het woord voorkomt moeten we uitzoeken waar de letter precies staat, en de letter op die plek(ken) invullen in het 'tot nu toe geraden woord'. Voor dat laatste hebben we gelukkig al een functie gemaakt..

  1. Ga nu één voor één na welke letters overeen komen met de letter die de gebruiker heeft ingevuld. Bedenk je wat de functie die je bij 1. hebt gemaakt precies nodig heeft, en pas 'm toe om de letter op de juiste plaats(en) in te vullen in het geraden woord.

Hint: in plaats van over een range() te lopen in een loop kun je ook het statement enumerate() gebruiken. Voer de volgende code eens uit en kijk wat er gebeurt:

for i,j in enumerate('hoi'):
    print(i,j)

Waarschijnlijk kun je dit soort constructies ook nuttig gebruiken in je code.

Dit is het einde van de loop. Als je je conditie bij $3.$ goed hebt gekozen zou het spel nu door moeten gaan als de gebruiker nog een beurt heeft, en moeten stoppen wanneer hij wint of verliest.

  1. Zorg voor een net bericht aan het einde wanneer de gebruiker heeft gewonnen of verloren. Waar kan je aan zien of de gebruiker won of verloor? Onderscheid deze twee gevallen. Laat ook nog even zien wat het te raden woord was.

Het zou goed kunnen dat je er al rekening mee hebt gehouden, maar de kans is aanwezig dat je code nu alleen werkt voor woorden van een bepaalde vaste lengte.

  1. Indien je dit nog niet gedaan hebt, pas je code zo aan dat het werkt voor een woord van elke willekeurige lengte. Gebruik hiervoor de functie len(woord) in plaats van een constante waarde.

  2. Wanneer de gebruiker een bepaalde letter al geraden heeft, is het een beetje zonde als het nog een gok kost wanneer hij of zij die letter per ongeluk herhaalt. Hoe kan je handig bijhouden welke letters al geraden zijn? Bedenk wanneer je een letter toe moet voegen, en voorkom dat een letter twee keer fout gerekend wordt.

  3. Allemaal leuk en aardig, maar je wist het woord aan het begin natuurlijk al omdat je het zelf in hebt gevuld. In plaats daarvan kan je ook een willekeurig woord uit een file lezen. Omdat dat nog niet behandeld is, geven we die code hieronder voor. Kan je verklaren wat er hier gebeurt? Je vind hier een woordenlijst die je zou kunnen gebruiken, maar je kan natuurlijk ook zelf wat woorden in een tekstbestand zetten. Zorg ervoor dat er steeds maar één woord per regel staat.

import random
bestand = open('woordenlijst.txt')
woorden = bestand.read().splitlines()
woord = random.choice(woorden)
  1. Je kunt ook de gebruiker vragen om een woord in te vullen. Zo kan je het spel met twee mensen spelen. Zorg er wel voor dat je het scherm even leeg maakt, zodat de ander niet ziet wat je hebt ingevuld. Dat kan natuurlijk met een aantal prints, maar dat kan ook netter. Met de juiste zoektermen in Google moet je het juiste commando wel kunnen vinden.