Az előző bejegyzésben néhány függvényt definiáltunk és használtuk egy sudoku játékot megoldó program előállítására. Most e programot kicsit látványosabbá tesszük azzal, hogy a sudoku táblázatot grafikus felülettel jelenítjük meg a tkinter modult használva.
A programunk készítésének elve és fő részei a következők:
- Az eddigi eredményeinket, azaz a függvénydefiníciókat egy modulfájlba elmentjük. Ebből aztán majd a jelen programunkba a megoldó függvényt beimportáljuk.
- Az előzőkhöz hasonlóan a megoldandó sudoku kezdősorainak értékei egy karakterláncban állnak rendelkezésre, amiből előállítjuk a sudokumátrixot.
- A sudokumátrixot egy keret grafikus elemben rajzoljuk ki, ahol az egyes cellákat táblázatos elrendezésben (9×9 grid) egy-egy keret elemben jelenítjük meg.
- A megoldás előhívásához pedig egy nyomógomb elemet helyezünk el e táblázat alatt a főablak alján.
- Egy olyan függvényt definiálunk, amely a kiinduló sudokumátrixot a beimportált megoldófüggvénnyel megoldja, és az eredményül kapott számokat a kirajzolt táblázat üres helyein megjeleníti.
- A nyomógomb elemet úgy konfiguráljuk, hogy e definiált függvény a gomb lenyomásakor a megfelelő módon meg legyen hívva.
A számok cellakeretekben történő kiíratására több lehetőség van. Mivel a programunkat most csak arra tervezzük, hogy a megoldást kiírja, ezért alkalmazhatnánk erre például a címke (Label) grafikus elemet. De gondolunk a továbbfejleszthetőségre, nevezetesen arra, hogy esetleg igény lehet majd, hogy játszani is lehessen vele, azaz manuálisan bevinni a cellákba a számokat. Ezért inkább a beviteli mező (Entry) elemmel fogjuk a sudoku egyes celláiban szereplő számokat megjeleníteni. E grafikus elem szöveges tartalmát a hozzárendelt kontrollváltozóval lehet kiírni és változtatni. Ezért ezeket a program indulásakor létre kell hozni a kezdőtábla értékeivel, majd a megoldás előhívásakor a gomb megnyomásakor lefutó függvényünkben az eddig üres cellákba került értékekre állítani be őket.
A program kódját, valamint az induló és a nyomógomb megnyomása után megjelenő megoldott táblát láthatjuk alább. A program működését a fenti leírás és részletes kommentek alapján lehet követni.
|
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
from itertools import product from sudoku_megoldó import sudoku_megoldás import tkinter as tk # A sudoku mátrix előállítása a sorait meghatározó karaktersorozatból. sudoku_sorok = '203610000580007000400080020802000007000305000600000402040070008000400071000061504' sudoku = [[*map(int, sudoku_sorok[i: i + 9])] for i in range(0, len(sudoku_sorok), 9)] # ---- GUI megvalósítása ---- # A sudoku mátrixot egy keret grafikus elemben jelenítjük meg, ahol az egyes cellákat # táblázatos elrendezésben (grid) egy-egy keret elemben elhelyezett beviteli mező képezi. # A megoldás előhívásához egy nyomógomb elemet is elhelyezünk a táblázat alatt a főablak alján. root = tk.Tk() root.title('SUDOKU') # A főablak címe. root_width, root_height = 600, 600 # Főablak méreteit változókban adjuk meg a későbbi használathoz. root.geometry(f'{root_width}x{root_height}') # A cellákhoz tartozó egyes beviteli mezőkben megjelenítjük a sudokumátrix soraiban meghatározott # számok string megfelelőjét. Ahol "0" van az üres cellát jelent, így ott a cella értéke egy szóköz lesz. # Ennek megvalósításához a beviteli mezőkhöz rendelhető StringVar() kontrollváltozókat hozunk létre az egyes # cellaértékekkel egy szótárban, és amelyeket a sor- és oszlopindexekből képzett tuple kulcsokkal azonosítunk. entry_vars = {(si, oi): tk.StringVar(root, str(n) if (n := sudoku[si][oi]) != 0 else ' ') for si, oi in product(range(9), range(9))} # A megoldást előhívó gomb megnyomására az alábbi függvény fog lefutni, amely argumentumként a sudokumátrixot # és a fenti szótárt kapja. Meghívja a sudoku megoldó függvényt, majd az ennek alapján előálló megoldott # mátrix elemeivel módosítja a kontrollváltozók értékeit a szótárban, amelynek hatására a beviteli mező # tartalma automatikusan ezen értékekre változik. def megoldás(sudoku_mátrix, beviteli_mezők_kontrollváltozói: dict): sudoku_megoldás(sudoku_mátrix) for si, oi in product(range(9), range(9)): beviteli_mezők_kontrollváltozói.get((si, oi)).set(sudoku_mátrix[si][oi]) # A sudoku táblázat keretének létrehozása. táblázat = tk.Frame(root, bg='green', width=500, height=500, padx=3, pady=3) # E kereten belül, rácsos elrendezésben a cellák keretének és beviteli mezőjének létrehozása, és lehelyezése. for si, oi in product(range(9), range(9)): # A cellakeretek létrehozása. cell_fr = tk.Frame(táblázat, bg='light yellow', width=50, height=50, padx=2, pady=2) # Ezzel érjük el, hogy cellakeret beállított mérete maradjon meg és ne a tartalma méretéhez igazodjon: cell_fr.propagate(False) # A cellakeretek rácsos elrendezésben történő lehelyezése. cell_fr.grid(row=si, column=oi, # A 3x3 kis négyzetek vizuális elkülönítéséhez a cellakeretek széleitől mért térközöket növeljük meg # minden harmadik sor, illetve oszlop után, kivéve az utolsót, mert az már a táblázat széle lenne. padx=(1, 3 if oi != 8 and (oi + 1) % 3 == 0 else 1), pady=(1, 3 if si != 8 and (si + 1) % 3 == 0 else 1)) # A számokat megjelenítő beviteli mező grafikus elemek létrehozása és lehelyezése a cellakereteken belül. tk.Entry(cell_fr, width=1, font=('Courier', 24, 'bold'), justify=tk.CENTER, textvariable=entry_vars.get((si, oi))).pack(fill=tk.BOTH, expand=True) # A megoldást megjelenítő nyomógomb elem létrehozása és konfigurálása olyan módon, hogy a fentebb definiált függvény # a gomb lenyomásakor a megfelelő módon meg legyen hívva. btn = tk.Button(root, text='Megoldás', font=('Courier', 18, 'bold'), command=lambda: megoldás(sudoku, entry_vars)) # A sudokut megjelenítő keret, valamint a nyomógomb lehelyezése. táblázat.pack(pady=((root_height - táblázat.cget('height')) / 2, 0)) btn.pack(side=tk.BOTTOM, padx=1, pady=1) root.mainloop() |

A programban alkalmazott grafikus elemek vagy a kontrollváltozók használati részleteiről a Python tudásépítés lépésről lépésre című e-könyv „Grafikus felhasználói felület készítése” fejezetének alábbi alfejezeteiben találunk bővebb kifejtést:
- „Grafikus elemek konfigurálásának módjai”
- „Kontrollváltozók”
- „A grafikus elemek fajtái, létrehozásuk és konfigurálásuk” – „Nyomógomb”, „Beviteli mező” és „Keret” alcímek.