Mi a Wordle, és hogyan kell játszani?
A Wordle egy szókitalálós játék, amelynek leírását megtaláljuk a neten, sőt online ki is próbálhatjuk akár az angol akár a magyar változatot. Ettől függetlenül a program megírásához összefoglaljuk most a szabályokat.
A játék lényege, hogy egy 5 betűből álló rejtett szót kell kitalálni adott lépésszámból. Az eredeti angol nyelvű verzióban ez 6 lépést jelent. Mivel a magyar ábécé több betűből áll, mint az angol, így nehezebb a megfejtés, ezért 8 tippelési lehetőség áll rendelkezésre.
A játékosnak be kell írni a tippelt szó betűit öt mezőbe. Ha a tippelt szó valamely betűje
- benne van a rejtett szóban és jó helyen is van, akkor e pozícióban levő tippelt betű zöld háttérszínű lesz.
- ugyan benne van a rejtett szóban, de nem jó pozícióban, akkor e tippelt betű sárga színű lesz.
- nem szerepel a rejtett szóban, akkor e betű szürke háttérszínnel jelenik meg.
A játékprogram két fő része a rejtett szó generálása, valamint a tipp-kiértékelő algoritmus. Ezeket fogjuk ebben a bejegyzésben lekódolni. Az ezután következőben pedig megírjuk a teljes GUI alkalmazást.
Rejtett szót tesztelés céljából rögzíthetünk a forráskódban. Azonban ahhoz, hogy élesben lehessen játszani – amikor magunk sem tudjuk, hogy mi a rejtett szó – kell a magyar szavak listája. Némi kereséssel az interneten találunk letölthető .txt szövegfájlokat. Ezek nem biztos, hogy minden magyar szót tartalmaznak, de kezdetben ez nem is lényeges, mert e fájlt később tetszés szerint bővíthetjük. A lényeg, hogy legyen egy ilyen fájlunk lementve egy mappába.
Az 5-betűs szavak listájának előállításához először be kell olvasni a fájlból a szavakat. Ezt most nem a hagyományos módon, az open() függvénnyel hajtjuk végre, hanem a szabványos könyvtár pathlib modulja Path objektumát használjuk. Tesszük ezt azért, mert röviden, egyetlen sorban, de mégis áttekinthetően lehet a beolvasást végezni, másrészt a pathlib modul egy korszerű, a fájlkezeléshez jól használható, széles szolgáltatásválasztékot nyújtó modul, amivel érdemes megismerkedni, ha még nem tettük. / A Python tudásépítés lépésről lépésre című e-könyvben erről nagyon részletesen, a „Mentsük, ami menthető! – fájlok és mappák” fejezetének „Könyvtár és fájl kezelés” alfejezetében olvashatunk/
A Path argumentumaként megadjuk a fájl útvonalát, majd a read_text() metódussal egy karaktersorba beolvassuk a szavakat. Mivel a szavak a fájlban sortöréssel vannak elválasztva, ezért az egyes szavakat a split() metódussal különítjük el egy listába.
Ezt követően a szólistából leválogatjuk az ötbetűs szavakat.
Végül az ötbetűs szavak listájából egy kitalálandó, rejtett szót véletlenszerűen kiválasztunk. Ehhez most a random modul randint() függvényét használjuk. /Erről az e-könyvben a „Matematikai számítások támogatása” alfejezet „A véletlen használatba vétele” cím alatt van szó/
Az eddig felsorolt műveleteket láthatjuk alább:
|
1 2 3 4 5 6 7 8 9 10 11 |
from pathlib import Path from random import randint # Beolvassuk a magyar szavak listáját és leválogatjuk az ötbetűseket. szavak = Path(r'D:\magyar_szavak_wordle.txt').read_text('utf8').split('\n') szavak5 = [szó.lower() for szó in szavak if len(szó) == 5] # Véletlenszerűen kiválasztunk egy szót az ötbetűsekből. rejtett = szavak5[randint(0, len(szavak5))].lower() |
Térjünk most rá a tippkiértékelő algoritmus leírására. Ez a következő lépésekből áll:
- Meghatározzuk és eltároljuk a rejtett és tippelt szóban közös betűket.
- Meghatározzuk és eltároljuk, hogy a rejtett szóban az egyes közös betűk milyen indexpozíciókban vannak.
- Meghatározzuk és eltároljuk, hogy a tippelt szóban az egyes közös betűk milyen indexpozíciókban vannak.
- Egy ötelemű listát hozunk létre, amely azt fogja tárolni, hogy a tippelt szó egyes indexpozícióihoz milyen háttérszín tartozik minden kiértékelés után. E lista minden eleme szürke értéket kap létrehozáskor. Ha van találat, akkor az adott pozícióban felülírjuk az értéket sárga vagy zöld színnel.
- Egymás után sorban végigvesszük a közös betűket, és
- Meghatározzuk és eltároljuk egy adott közös betű pozíciói (indexi) közül az azonosakat. Ezek jelentik azon betűk pozícióit, amelyek szerepelnek mind a rejtett, mind a tippelt szóban és jó helyen is vannak. Ezért a színlistánkban ezen átfedő indexpozícióknál az értéket zöldre állítjuk be.
- Miután lekezeltük a jó pozícióban levő tippelt betűket, ezeket kivesszük mind a rejtett, mind a tippelt szó adott közös betűhöz tartozó indexei közül. Az így fennmaradó két index-nyilvántartás azt mondja meg, hogy az adott közös betű mely pozícióban van a rejtett szóban és mely pozícióban a tippelt szóban. Ezekben most már nem lesz egyezés, hiszen az azonos indexeket kivettük. A számosságukban is eltérhetnek, hiszen lehet, hogy a tippelt szóban az adott közös betű egyszer szerepel, míg a rejtett szóban többször, vagy fordítva.
- Az előző pontban kapott két indexhalmazból a kisebb számosságú elemszámát vesszük, és ennyiszer kiveszünk a tippelt szó adott közös betűjének indexnyilvántartásából egyet. A színlistánkban ezen indexpozíció(k) értékét sárgára állítjuk.
- Az így kialakult színlista képezi az algoritmus végeredményét, amely tehát azt mutatja meg színekkel, hogy az öt betűpozícióban mely betű(k) van(nak) a helyén/helyükön (zöld), melyek szerepelnek a rejtett szóban, de nem jó a helyük (sárga), és melyek azok, amelyek nincsenek a rejtett szóban (szürke).
A fenti megfontolások szerint megalkotott függvények a következők:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
def találati_indexek(szó: str, betű: str) -> set: """Egy olyan halmazzal tér vissza, amely azon indexértékeket tartalmazza, ahol az adott szóban a megadott betű előfordul""" return {i for i in range(len(szó)) if szó[i] == betű} def tippelés_kiértékelése(rejtett_szó: str, tippelt_szó: str): # Meghatározzuk és eltároljuk a rejtett és tippelt szóban közös betűket. közös_betűk = set(rejtett_szó) & set(tippelt_szó) # Meghatározzuk és eltároljuk, hogy a rejtett szóban az egyes közös betűk milyen indexpozíciókban vannak. d_rejtett = {b: találati_indexek(rejtett_szó, b) for b in közös_betűk} # Meghatározzuk és eltároljuk, hogy a tippelt szóban az egyes közös betűk milyen indexpozíciókban vannak. d_tipp = {b: találati_indexek(tippelt_szó, b) for b in közös_betűk} # Alapban a tippelt szó minden pozíciójához a szürke színt rendeljük, amit utána módosítunk, ha # van zöld vagy sárga pozíció. tipp_színek = ['grey'] * 5 # A tippelt szóban a közös betűk zöld és sárga poziciók meghatározása. for közös_betű in közös_betűk: # A tippel szóban az adott közös betű zöld indexpozícióinak meghatározása. egyező_indexek_rejtett_tipp = d_tipp.get(közös_betű) & d_rejtett.get(közös_betű) for zöld_index in egyező_indexek_rejtett_tipp: tipp_színek[zöld_index] = 'light green' # Az egyező, zöld indexeket kivesszük az adott közös betűhöz tartozó indexhalmazokból. maradó_indexek_rejtett = d_rejtett.get(közös_betű) - egyező_indexek_rejtett_tipp maradó_indexek_tipp = d_tipp.get(közös_betű) - egyező_indexek_rejtett_tipp # A tippel szóban az adott közös betű sárga indexpozícióinak meghatározása. for _ in zip(maradó_indexek_rejtett, maradó_indexek_tipp): sárga_index = d_tipp.get(közös_betű).pop() tipp_színek[sárga_index] = 'yellow' return tipp_színek |
A következő bejegyzésben a grafikus interfészt és a működő alkalmazás kódjának elkészítésével folytatjuk.