This is an old revision of the document!
Wordle
Das Ziel ist es, ein kleines Wordle-Spiel zu programmieren.
Dazu werden wir einzelne Programmteile erstellen, die dann am Schluss zu einem Ganzen zusammengefügt werden können.
Tests
Wir werden für unsere Funktionen immer gleich auch Tests schreiben, so haben wir eine Chance, logische Fehler früh zu erkennen.
Bewertungsfunktion(en)
Richtig Platzierte
Die Funktion richtig(a,b)
liefert ein Array mit Einträgen True
oder False
, je nachdem ob der Buchstabe in den Strings a
und b
an der entsprechenden Stelle übereinstimmt.
- Input: Zwei Strings, (in den Variablen
solution
undguess
). - Programmabbruch mit Fehlermeldung, wenn die Länge von
solution
undguess
nicht übereinstimmt. - Output: Array mit Einträgen
True
oderFalse
def richtig(solution,guess): if len(solution)!=len(guess): raise ValueError("Länge der beiden Wörter '%s' und '%s' stimmen nicht überein." % (solution,guess)) # Resultat Array bauen und in der Variablen res speichern res = [] # # ... # return res # Resultat zurückgeben und Funktion beenden def tests(): cases = [["HABER", "RABEN", [False, True, True, True, False]],\ ["TAGEN", "RABEN", [False, True, False, True, True]],\ ] for test in cases: res = richtig(test[0], test[1]) if res!=test[2]: raise ValueError("richtig(%s, %s) sollte %s liefern, liefert aber %s" % (test[0], test[1], str(test[2]), str(res))) print("Alle Tests erfolgreich!"); tests()
- Vervollständigen Sie die Funktion
richtig
- Fügen Sie weitere Tests hinzu.
Falsch platzierte
Wie oben, schreiben Sie eine Funktion falscherplatz(solution, guess)
, die wieder ein Array mit True
und False
zurückgibt.
Schreiben sie ebenfalls Tests dafür. Testen Sie auch Wortpaare wie “BBAAA”, “ABCDE”.
Wortliste
- Variante «easy»: Wortliste aus dem JavaScript-Code eines online Wordle kopieren.
- Variante «suchen und finden»: Wortliste auf dem Web suchen.
- Variante «selber bauen»: Wikipedia-Artikel herunterladen, Wörter extrahieren, nach Häufigkeit sortieren.
Wikipedia «downloaden»
Folgender Code funktioniert mehr schlecht als recht. Besser wäre es wohl, eine Library oder externes Programm wie 'curl' zu verwenden, das würde das ganze viel stabiler machen. Man könnte wohl auch wget verwenden und gleich die ganzen Webseiten speichern und dann diese offline bearbeiten.
Der Vorteil dieses Programm ist, dass man die Wörter gleich mit der Häufigkeit hat. So kann man nur die häufigsten Wörter als zu erratende Wörter zulassen, aber alle als gültige Eingabewörter. <hidden Code>
- crawler.py
import socket import ssl import urllib import re import os import sys # Or simply set this to True in TigerJython tigerJython = (sys.executable.find("jython")>=0) # Download einer Wikipedia-Seite # URL ist z.B. /wiki/Burg_Liechtenstein def download(url): host = "de.wikipedia.org" port = 443 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(0.5) s.connect((host , port)) s = ssl.wrap_socket(s) request = "GET " + url + " HTTP/1.1\r\nHost: " + host + "\r\n\r\n" if (tigerJython): s.sendall(request) else: s.sendall(bytes(request, 'utf-8')) try: reply = s.recv(4096) except socket.timeout: s.close() return "" start = reply.decode('utf-8').find("Content-Length: "); if (start==-1): start = reply.decode('utf-8').find("content-length: "); if (start>=0): end = reply.decode('utf-8').find("\r\n",start) #while reply[end]>='0' and reply[end]<='9': # end+=1 # print("Length: ->"+reply[(start+16):end]+"<-") numbytes = int(reply[(start+16):end]) print("About to get %d bytes" % numbytes); while reply.decode('utf-8').find("\r\n\r\n")<0: # print("About to get next chunk...") more = s.recv(4096) # print("Got %d more bytes" % len(more)) reply += more reply = reply[(reply.decode('utf-8').find("\r\n\r\n")+4):] # print("Reply so far: "+reply) while len(reply)<numbytes: # print("About to get next chunk...") more = s.recv(4096) reply += more # print("Len reply = %d, len more = %d" % (len(reply), len(more))) else: # print("Could not find Content-Length in ") # print(reply) try: while True: # print(".") more = s.recv(4096) reply += more except socket.timeout: pass s.close() return reply.decode('utf-8', 'ignore') todo = ["/wiki/Neoklassische_Synthese"] words = {} linksdone = {} # Load existing data, if any for l in range(4,11): datafile = "wortliste%02d.txt" % l if os.path.isfile(datafile): with open(datafile, "r") as file: for line in file.readlines(): entries = line.split(" ") words[entries[0]] = int(entries[1]) for i in range(200): url = todo.pop(0) linksdone[url] = True print("Downloading "+url) html = download(url) links = re.findall(r'<a href="(/wiki/.*?)"', html) links = [l for l in links if re.search('[%:#]', l)==None and (not l in linksdone)] for l in links: if not l in linksdone: linksdone[l]=True #print(l) todo.append(l) text = re.sub('<script>.*?</script>', "", html) text = re.sub('<.*?>', "", text) ww = [w.upper() for w in text.split() if re.match('^[A-Z]{4,10}$',w.upper())] # print("Have %d words" % len(ww)) newwords = 0 for w in ww: if w in words: words[w]+=1 else: newwords+=1 words[w] = 1 print("Have %d new words" % newwords) print("Open pages:") print(todo[0:10]) alle = words.keys() # print("\n".join(alle)) for l in range(4,11): wl = [w for w in alle if len(w)==l] wl.sort() # print("\n".join(wl)) with open("wortliste%02d.txt" % l, "w") as file: for w in wl: file.write("%s %d\n" % (w, words[w]))
JavaScript
Rudimentäre Vorlage: https://ofi.tech-lab.ch/2022/teach/d0571f1e/