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.maze_multitarget import MazeMultitargetJob
|
||||
from jobs.flush import FlushJob
|
||||
from jobs.word_search import WordSearchJob
|
||||
|
||||
# ==========================================
|
||||
# CONFIGURATION
|
||||
@ -64,6 +65,7 @@ JOBS = [
|
||||
DecimalDivisionJob(),
|
||||
JokeJob(),
|
||||
MazeMultitargetJob(),
|
||||
WordSearchJob(),
|
||||
# keep this last:
|
||||
FlushJob()
|
||||
]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user