New job: Word search (osmismerka)
This commit is contained in:
parent
0754f82ab6
commit
510ea220cc
33
jobs/czech_words.py
Normal file
33
jobs/czech_words.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
CZECH_WORDS = [
|
||||||
|
"AUTO", "BABIČKA", "BANÁN", "BARVA", "BÁSNIČKA", "BATOH", "BAVLNA", "BAZÉN",
|
||||||
|
"BEDNA", "BERAN", "BLÁTO", "BLESK", "BLOUDIT", "BOBŘÍK", "BODLÁK", "BOTY",
|
||||||
|
"BOUDA", "BOUŘKA", "BRÁNA", "BRATR", "BROUK", "BRUSLE", "BUBEN", "BUNDA",
|
||||||
|
"CESTA", "CIHLA", "CIRKUS", "CITRON", "CUKR", "ČEPICE", "ČERVENÁ", "ČESNEK",
|
||||||
|
"ČÍSLO", "ČLOVĚK", "DÁREK", "DATEL", "DCERA", "DĚDEČEK", "DEŠTNÍK", "DIVADLO",
|
||||||
|
"DOKTOR", "DOMOV", "DOPIS", "DORT", "DRAK", "DUBEN", "DŮM", "DVEŘE",
|
||||||
|
"DŽBÁN", "FARA", "FIALA", "FILM", "FLÉTNA", "FOTBAL", "GUMA", "HAVRAN",
|
||||||
|
"HLAVA", "HLÍNA", "HNÍZDO", "HODINY", "HOLKA", "HOLUB", "HORA", "HOUSKA",
|
||||||
|
"HRAD", "HRÁBĚ", "HRANA", "HRAČKA", "HRNEK", "HRUŠKA", "HUDBA", "CHATA",
|
||||||
|
"CHLÉB", "CHLAP", "CHYBA", "JABLKO", "JAHODA", "JARO", "JAZYK", "JEHLA",
|
||||||
|
"JEZERO", "JÍDLO", "JITRO", "KABÁT", "KAČNA", "KAKAO", "KÁMEN", "KAPSÁŘ",
|
||||||
|
"KARTA", "KÁVA", "KILO", "KLADIVO", "KLÍČ", "KLOBOUK", "KLUK", "KNIHA",
|
||||||
|
"KOČKA", "KOLO", "KOMÁR", "KONEC", "KOPEC", "KOŘEN", "KOST", "KOŠILE",
|
||||||
|
"KOZA", "KRÁL", "KRÁVA", "KRESLIT", "KREV", "KRK", "KRUH", "KUCHYNĚ",
|
||||||
|
"KVĚTINA", "LÁSKA", "LAVICE", "LEDEN", "LES", "LÉTO", "LEV", "LÍSTEK",
|
||||||
|
"LOĎ", "LOUKA", "LŽÍCE", "MÁMA", "MAPA", "MASO", "MĚSTO", "METR",
|
||||||
|
"MLÉKO", "MLÝN", "MODRÁ", "MOŘE", "MOST", "MOTÝL", "MRAK", "MRKEV",
|
||||||
|
"MUŽ", "MYŠ", "NÁDRAŽÍ", "NOHA", "NOC", "NOS", "NOVINY", "NŮŽKY",
|
||||||
|
"OBCHOD", "OBĚD", "OBRAZ", "OCAS", "OKNO", "OKO", "OLEJ", "OPICE",
|
||||||
|
"OREL", "OVOCE", "PÁTEK", "PES", "PÍSEŇ", "PIVO", "PLÁČ", "PLOT",
|
||||||
|
"POLE", "POLÉVKA", "POMOC", "POSTEL", "POTOK", "PRÁCE", "PRAHA", "PRASE",
|
||||||
|
"PRST", "PTÁK", "RÁDIO", "RADOST", "RAKETA", "RÁNO", "RUKA", "RYBA",
|
||||||
|
"ŘEKA", "ŘEPA", "SÁŇKY", "SEDLO", "SESTRA", "SEŠIT", "SKLO", "SLON",
|
||||||
|
"SLUNCE", "SNÍH", "SOVA", "SRDCE", "STROM", "STŮL", "SVĚTLO", "ŠKOLA",
|
||||||
|
"ŠATY", "ŠNEK", "TÁTA", "TELEVIZE", "TETA", "TMA", "TRAVÁ", "TRH",
|
||||||
|
"TUŽKA", "UCHO", "ULICE", "ÚNOR", "ÚSTA", "VAJÍČKO", "VÁNOCE", "VČELA",
|
||||||
|
"VEČEŘE", "VEJCE", "VELRYBA", "VESNICE", "VĚTR", "VODA", "VOJÁK", "VOLANT",
|
||||||
|
"VRÁNA", "VRATA", "VLASY", "VLAK", "VLK", "ZÁHADA", "ZAHRADA", "ZÁMEK",
|
||||||
|
"ZIMA", "ZLATO", "ZUB", "ZVON", "ŽÁBA", "ŽÁROVKA", "ŽENA", "ŽIDLE", "ŽIVOT",
|
||||||
|
# special letters to make sure we have them covered:
|
||||||
|
"WEB", "PIXEL", "TEQUILA", "BRAWL", "BOX", "QÍK"
|
||||||
|
]
|
||||||
143
jobs/word_search.py
Normal file
143
jobs/word_search.py
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
import random
|
||||||
|
import time
|
||||||
|
import textwrap
|
||||||
|
from jobs.czech_words import CZECH_WORDS
|
||||||
|
|
||||||
|
class WordSearchJob:
|
||||||
|
def __init__(self):
|
||||||
|
self.width = 14
|
||||||
|
self.height = 14
|
||||||
|
self.hidden_phrase = "TAJENKA"
|
||||||
|
self.words_to_find = []
|
||||||
|
self.grid = []
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
return "Word Search (Osmismerka)"
|
||||||
|
|
||||||
|
def configure(self):
|
||||||
|
print("\n--- Configure Word Search ---")
|
||||||
|
phrase = input("Enter hidden phrase (default: TAJENKA): ").strip().upper()
|
||||||
|
if phrase:
|
||||||
|
self.hidden_phrase = "".join(c for c in phrase if c.isalnum())
|
||||||
|
else:
|
||||||
|
self.hidden_phrase = "TAJENKA"
|
||||||
|
self.width = len(self.hidden_phrase) + 2
|
||||||
|
self.height = len(self.hidden_phrase) + 2
|
||||||
|
size = int(input(f"Enter size (default: {self.width}): ").strip())
|
||||||
|
if size:
|
||||||
|
self.width = size
|
||||||
|
self.height = size
|
||||||
|
if self.width < 5:
|
||||||
|
self.width = 5
|
||||||
|
self.height = 5
|
||||||
|
if self.width > 40:
|
||||||
|
self.width = 40
|
||||||
|
self.height = 40
|
||||||
|
|
||||||
|
def run(self, printer):
|
||||||
|
# Directions: Right, Down, Diag-Down-Right
|
||||||
|
directions = [(0, 1), (1, 0), (1, 1)]
|
||||||
|
target_empty = len(self.hidden_phrase)
|
||||||
|
|
||||||
|
# Retry loop to ensure perfect fill (no leftover letters)
|
||||||
|
for attempt in range(20):
|
||||||
|
# Initialize grid
|
||||||
|
self.grid = [['' for _ in range(self.width)] for _ in range(self.height)]
|
||||||
|
used_mask = [[False for _ in range(self.width)] for _ in range(self.height)]
|
||||||
|
|
||||||
|
# Filter words that fit in the grid
|
||||||
|
available_words = [w for w in CZECH_WORDS if len(w) <= self.width and len(w) <= self.height]
|
||||||
|
random.shuffle(available_words)
|
||||||
|
|
||||||
|
self.words_to_find = []
|
||||||
|
|
||||||
|
total_cells = self.width * self.height
|
||||||
|
current_empty = total_cells
|
||||||
|
|
||||||
|
# Try to place words until we reach target_empty
|
||||||
|
for word in available_words:
|
||||||
|
if current_empty == target_empty:
|
||||||
|
break
|
||||||
|
|
||||||
|
placed = False
|
||||||
|
attempts = 0
|
||||||
|
while not placed and attempts < 50:
|
||||||
|
attempts += 1
|
||||||
|
direction = random.choice(directions)
|
||||||
|
dr, dc = direction
|
||||||
|
|
||||||
|
# Determine bounds
|
||||||
|
if dr == 0: # Horizontal
|
||||||
|
r = random.randint(0, self.height - 1)
|
||||||
|
c = random.randint(0, self.width - len(word))
|
||||||
|
elif dc == 0: # Vertical
|
||||||
|
r = random.randint(0, self.height - len(word))
|
||||||
|
c = random.randint(0, self.width - 1)
|
||||||
|
else: # Diagonal
|
||||||
|
r = random.randint(0, self.height - len(word))
|
||||||
|
c = random.randint(0, self.width - len(word))
|
||||||
|
|
||||||
|
# Check collision
|
||||||
|
fits = True
|
||||||
|
temp_new_cells = 0
|
||||||
|
for i, char in enumerate(word):
|
||||||
|
nr, nc = r + i*dr, c + i*dc
|
||||||
|
# Cell must be empty OR contain the same letter
|
||||||
|
if self.grid[nr][nc] != '' and self.grid[nr][nc] != char:
|
||||||
|
fits = False
|
||||||
|
break
|
||||||
|
if self.grid[nr][nc] == '':
|
||||||
|
temp_new_cells += 1
|
||||||
|
|
||||||
|
if fits:
|
||||||
|
# Check if this overfills
|
||||||
|
if current_empty - temp_new_cells < target_empty:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Place it
|
||||||
|
for i, char in enumerate(word):
|
||||||
|
nr, nc = r + i*dr, c + i*dc
|
||||||
|
if self.grid[nr][nc] == '':
|
||||||
|
current_empty -= 1
|
||||||
|
self.grid[nr][nc] = char
|
||||||
|
used_mask[nr][nc] = True
|
||||||
|
self.words_to_find.append(word)
|
||||||
|
placed = True
|
||||||
|
|
||||||
|
if current_empty == target_empty:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Fill remaining spots with hidden phrase
|
||||||
|
empty_slots = []
|
||||||
|
for r in range(self.height):
|
||||||
|
for c in range(self.width):
|
||||||
|
if not used_mask[r][c]:
|
||||||
|
empty_slots.append((r, c))
|
||||||
|
|
||||||
|
phrase_idx = 0
|
||||||
|
for r, c in empty_slots:
|
||||||
|
if phrase_idx < len(self.hidden_phrase):
|
||||||
|
self.grid[r][c] = self.hidden_phrase[phrase_idx]
|
||||||
|
phrase_idx += 1
|
||||||
|
else:
|
||||||
|
# Fill with random letters if phrase is done (extra filler)
|
||||||
|
self.grid[r][c] = random.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||||
|
|
||||||
|
# Print Header
|
||||||
|
printer.text("OSMISMĚRKA\n")
|
||||||
|
printer.text("Najdi slova a přečti tajenku!\n")
|
||||||
|
if current_empty != target_empty:
|
||||||
|
printer.text(f"Tajenka má {len(self.hidden_phrase)} písmen.\n")
|
||||||
|
printer.text("\n")
|
||||||
|
|
||||||
|
# Print Grid
|
||||||
|
for r in range(self.height):
|
||||||
|
line = " ".join(self.grid[r])
|
||||||
|
printer.text(line + "\n")
|
||||||
|
time.sleep(0.05)
|
||||||
|
|
||||||
|
printer.text("\nSlova k hledání:\n")
|
||||||
|
words_str = ", ".join(sorted(self.words_to_find))
|
||||||
|
printer.text(textwrap.fill(words_str, width=42) + "\n")
|
||||||
|
printer.text("\n\n")
|
||||||
|
printer.cut()
|
||||||
@ -10,6 +10,7 @@ from jobs.decimal_division import DecimalDivisionJob
|
|||||||
from jobs.joke import JokeJob
|
from jobs.joke import JokeJob
|
||||||
from jobs.maze_multitarget import MazeMultitargetJob
|
from jobs.maze_multitarget import MazeMultitargetJob
|
||||||
from jobs.flush import FlushJob
|
from jobs.flush import FlushJob
|
||||||
|
from jobs.word_search import WordSearchJob
|
||||||
|
|
||||||
# ==========================================
|
# ==========================================
|
||||||
# CONFIGURATION
|
# CONFIGURATION
|
||||||
@ -64,6 +65,7 @@ JOBS = [
|
|||||||
DecimalDivisionJob(),
|
DecimalDivisionJob(),
|
||||||
JokeJob(),
|
JokeJob(),
|
||||||
MazeMultitargetJob(),
|
MazeMultitargetJob(),
|
||||||
|
WordSearchJob(),
|
||||||
# keep this last:
|
# keep this last:
|
||||||
FlushJob()
|
FlushJob()
|
||||||
]
|
]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user