Místo toho, aby byl všude stejný kousek hada, budeme chtít vybrat vždycky ten správný.
Jak na to? Podle čeho ho vybrat?
Obrázky s kousky hada jsou pojmenovány
odkud-kam.png
.
To není náhoda – ukazuje to, co potřebuješ vědět, abys mohla ten správný
kousek vybrat.
Když máš hada podle následujícího obrázku, na políčko (3, 2) patří
kousek, na kterém had „leze“ zleva nahoru – tedy left-top.png
Na koncích hada je ve jménech obrázků místo směru end
.
Pro každé z políček budeš potřebovat zjistit, odkud a kam na něm had leze – tedy směr k předchozí a následující souřadnici:
Souřadnice | Předchozí | Směr k předchozí | Následující | Směr k následující | |
---|---|---|---|---|---|
(1, 2) | není | end |
(2, 2) | right |
|
(2, 2) | (1, 2) | left |
(3, 2) | right |
|
(3, 2) | (2, 2) | left |
(3, 3) | top |
|
(3, 3) | (3, 2) | bottom |
(3, 4) | top |
|
(3, 4) | (3, 3) | bottom |
(3, 5) | top |
|
(3, 5) | (3, 4) | bottom |
(4, 5) | right |
|
(4, 5) | (3, 5) | left |
není | end |
Toto je těžký úkol. I když všechny potřebné informace a nástroje k tomu teď teoreticky znáš, je potřeba je správným způsobem poskládat dohromady. Tohle skládání dohromady, návrh algoritmů, je nejsložitější programátorská disciplína.
Zkus nad tím ale přemýšlet, nech si to rozležet v hlavě třeba přes noc, vrať se k materiálům k předchozím lekcím (hlavně k úvodu do Pythonu), zkoušej a objevuj… A časem na to přijdeš.
Jestli nemáš čas, koukněme se na to, jak se dá zařídit.
Popisuju tady jedno možné řešení. Existuje spousta jiných správných způsobů, jak vybírat políčka hada. Možná ti dokonce jiné řešení přijde jednodušší – a možná to bude dokonce tvoje řešení!
Složité problémy programátoři většinou vhodně rozdělí na více jednodušších problémů. Každý pak vyřeší zvlášť a pak spojí dohromady.
Jaké jednodušší úkoly by se daly najít tady?
Řešením prvního z nich v tabulce výše „vyplníš“ sloupečky se souřadnicemi. Řešením druhého pak z těchto informací dostaneš směry, části jména obrázku.
Budeš potřebovat vyřešit oba dva problémy. Ten druhý je ale jednodušší, tak se pojďme zaměřit na něj.
Potřebuješ počítači říct, jak ze souřadnic dvou políček, které jsou vedle sebe, zjistit směr od jednoho ke druhému.
Například směr od (3, 2) k (2, 2) je doleva. Směr od (3, 2) k (3, 3) je nahoru. (Viz obrázek, nebo třetí řádek tabulky výše.)
V Pythonu to napíšeš jako funkci, která bere dva argumenty (souřadnice) a vrátí anglické jméno směru – řetězec, který se dá použít ve jméně souboru s obrázkem.
Až bude tahle funkce hotová, měla by se dát použít následovně:
>>> direction((3, 2), (2, 2))
'left'
>>> direction((3, 3), (3, 2))
'bottom'
>>> direction((3, 3), 'end')
'end'
Na koncích hada bude potřeba jako druhou souřadnici použít místo dvojice čísel
něco jiného.
Řetězec 'end'
funguje dobře, ale stejně tak by se dalo použít cokoli jiného,
co není souřadnice: False
, -1
, nebo třeba []
.
(Zkušený Pythonista by použil hodnotu None
.)
Jak takovou funkci napsat? Když si pořádně prohlédneš první tři sloupce tabulky výše, možná přijdeš na to, jak se od sebe liší souřadnice, které jsou nalevo od sebe. Nebo nahoru.
'end'
'left'
'right'
'bottom'
'top'
Zkušený programátor v tento moment zbystří a zeptá se: „ale co když neplatí
ani jedna z těch podmínek“?
Taková situace ve hře nemůže nastat (nebo ano?), ale přesto je dobré ji
podchytit a na konec postupu přidat třeba „Jinak je výsledek 'end'
”.
To je složitější část řešení našeho problému. Zbytek je jen téměř doslovný překlad z češtiny do Pythonu:
def direction(a, b):
if b == 'end':
return 'end'
# Rozložení souřadnic na čísla (x, y) – to je v češtině "samozřejmé"
x_a, y_a = a
x_b, y_b = b
# ... a logika pokračuje
if x_a == x_b + 1:
return 'left'
elif x_a == x_b - 1:
return 'right'
elif y_a == y_b + 1:
return 'bottom'
elif y_a == y_b - 1:
return 'top'
else:
return 'end'
# Vyzkoušení
print('tohle by mělo být "left":', direction((3, 2), (2, 2)))
print('tohle by mělo být "bottom":', direction((3, 3), (3, 2)))
print('tohle by mělo být "top":', direction((3, 2), (3, 3)))
print('tohle by mělo být "right":', direction((1, 1), (2, 1)))
print('tohle by mělo být "end":', direction((3, 3), 'end'))
print('tohle by mělo být "end":', direction((3, 3), (80, 80)))
Teď se vraťme k prvnímu problému: jak projít všechny políčka hada, a u každého vědět předchozí a následující?
Protože rozdíl mezi souřadnicemi jako (1, 2) a (2, 2) není na první pohled moc čitelný, kousky hada si označím písmenky. Budu psát A místo (1, 2); B místo (2, 2); atd.:
Takového hada nakreslím následovně:
K vykreslení | A | B | C | D | E | F | G |
---|---|---|---|---|---|---|---|
Předchozí | × | A | B | C | D | E | F |
Následující | B | C | D | E | F | G | × |
Jak na to?
První řádek tabulky, seznam [A, B, C, D, E, F, G] už máš – to jsou souřadnice
hada, snake
.
Kdyz se ti k tomu podaří připravit seznamy s druhým řádkem,
[×, A, B, C, D, E, F], a třetím, [B, C, D, E, F, G, ×], můžeš je pak spojit
pomocí funkce zip
.
Vzpomínáš na ni?
Prochází několik „opovídajících si“ seznamů a dá n-tici
prvních prvků, pak n-tici druhých prvků, pak třetích…
Náš příklad byl:
veci = ['tráva', 'slunce', 'mrkev', 'řeka']
barvy = ['zelená', 'žluté', 'oranžová', 'modrá']
mista = ['na zemi', 'nahoře', 'na talíři', 'za zídkou']
for vec, barva, misto in zip(veci, barvy, mista):
print(barva, vec, 'je', misto)
Ale stejně tak můžeš použít:
snake = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
prevs = ['x', 'A', 'B', 'C', 'D', 'E', 'F']
nexts = ['B', 'C', 'D', 'E', 'F', 'G', 'x']
for coords, prev, next in zip(snake, prevs, nexts):
print('na políčku', coords, 'had leze z', prev, 'do', next)
Ty dva další seznamy je ale potřeba „vyrobit“ z prvního: vybrat správný kousek a na správnou stranu doplnit „chybějící“ prvek:
snake = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
prevs = ['end'] + snake[:-1]
nexts = snake[1:] + ['end']
for coords, prev, next in zip(snake, prevs, nexts):
print('na políčku', coords, 'had leze z', prev, 'do', next)
Anebo, s „opravdovými“ souřadnicemi a funkcí direction
:
snake = [(1, 2), (2, 2), (3, 2), (3, 3), (3, 4), (3, 5), (4, 5)]
for coords, prev, next in zip(snake, ['end'] + snake[:-1], snake[1:] + ['end']):
before = direction(coords, prev) # směr z aktuálního políčka na předchozí
after = direction(coords, next) # směr z aktuálního políčka na následující
print('na', coords, 'vykreslit:', before + '-' + after)
Jestli jsi došla až sem, doufám, že nebudeš mít příliš velké problmy s „transplantací“ tohoto kódu do tvojí hry.