Klondike Solitaire

Pojďme vytvořit karetní hru Klondike Solitaire, kterou možná znáš v nějaké počítačové verzi.

Jedna z grafických podob hry

Naše hra bude ze začátku jednodušší – nebudeme se zabývat grafikou, ale logikou hry. „Grafiku“ zatím zajistí textová konzole:

   U     V          W     X     Y     Z
 [???] [   ]      [   ] [   ] [   ] [   ]

   A     B     C     D     E     F     G
 [3♣ ] [???] [???] [???] [???] [???] [???]
       [5 ♥] [???] [???] [???] [???] [???]
             [6♣ ] [???] [???] [???] [???]
                   [5♠ ] [???] [???] [???]
                         [Q ♥] [???] [???]
                               [4♠ ] [???]
                                     [3 ♦]

Schéma hry

Hra funguje takto:

  • Rozdej balíček a sloupečky karet
  • Dokud hráč nevyhrál:
    • Zobraz stav hry
    • Zeptej se hráče, odkud a kam chce hrát
    • Je-li to možné:
      • Proveď tah
    • Jinak:
      • Vynadej hráči, že daný tah nedává smysl
  • Pogratuluj hráči

Karta

Karta bude trojice (hodnota, barva, je_licem_nahoru) – viz sraz. Následující funkce (v souboru karty.py) nám zjednoduší práci:

def popis_kartu(karta):
    """Vrátí popis karty, např. [Q ♥] nebo [6♣ ] nebo [???]

    Trojice čísla (2-13), krátkého řetězce ('Sr', 'Ka', 'Kr' nebo 'Pi')
    a logické hodnoty (True - lícem nahoru; False - rubem) se jednoduše
    zpracovává v Pythonu, ale pro "uživatele" není nic moc.
    Proto je tu tahle funkce, která kartu hezky "popíše".

    Aby byly všechny karty jedno číslo nebo písmeno, se desítka
    se vypisuje jako "X".

    Aby se dalo rychle odlišit červené (♥♦) karty od černých (♣♠),
    mají červené mezeru před symbolem a černé za ním.
    """
def otoc_kartu(karta, pozadovane_otoceni):
    """Vrátí kartu otočenou lícem nahoru (True) nebo rubem nahoru (False)

    Nemění původní trojici; vytvoří a vrátí novou.
    (Ani by to jinak nešlo – n-tice se, podobně jako řetězce čísla, měnit
    nedají.)
    """

Funkce najdeš v souboru karty.py. Projdi si je; rozumíš jim?

Testy k nim jsou v test_karty.py – ty procházet nemusíš, jestli nechceš.

Testy a úkoly

Stáhni si soubor s testy, test_klondike.py, a dej ho do adresáře, kde budeš tvořit hru a kde máš karty.py.

Na ulehčení testování si nainstaluj modul pytest-level. Ten umožňuje pouštět jen určité testy – podle toho, jak jsi daleko.

python -m pip install pytest pytest-level

Zkus pustit všechny testy. Asi ti neprojdou:

python -m pytest -v

Pak zkus pustit testy pro úroveň 0:

python -m pytest -v --level 0

Teď se nepustí žádné testy – všechny se přeskočí. Výpis by měl končit nějak takto:

collected N items / N deselected
=== N deselected in 0.01 seconds ===

Zadáš-li v posledním příkazu --level 1, aktivuje se první z testů. Pravděpodobně neprojde – v dalším úkolu ho spravíš!

Popis balíčku

Jako první věc ve hře potřebujeme rozdat balíček karet. Co je to ale takový balíček? Jak se dá balíček karet reprezentovat pomocí řetězců, čísel, seznamů, n-tic a podobně?

Způsobů, jak takový balíček karet reprezentovat, je více. Abychom měli projekt všichni stejný (a aby k němu mohly být testy), je v těchto materiálech tento úkol už vyřešený.

Balíček karet bude seznam karet – tedy seznam trojic. To dává smysl – karet v balíčku může být různý počet (klidně 0), kar se z něj dají brát nebo do něj přidávat, balíček se dá zamíchat nebo seřadit.

Balíček bude například:

balicek = [(4, 'Pi', True), (4, 'Sr', True), (4, 'Ka', False), (4, 'Kr', True)]
prazdny_balicek = []

Napiš následující funkci, která balíček popíše:

def popis_balicku(balicek):
    """Vrátí popis daného balíčku karet -- tedy vrchní karty, která je vidět"""
  • level 10: Funkce existuje
  • level 11: Funkce vrátí popis poslední karty. (Bude se hodit funkce popis_kartu z modulu karty.)
  • level 12: Funkce popíše prázdný balíček jako [ ] (3 mezery v hranatých závorkách).

Vytvoření balíčku

Napiš následující funkci:

def vytvor_balicek():
    """Vrátí balíček 52 karet – od esa (1) po krále (13) ve čtyřech barvách

    Karty jsou otočené rubem nahoru (nejsou vidět).
    """
  • level 20: Funkce existuje
  • level 21: V balíčku je 52 karet, žádné se neopakují.
  • level 22: V balíčku jsou všechny požadované karty.
  • level 23: Balíček je zamíchaný.

Rozepsání balíčku

Když výsledek funkce vytvor_balicek vypíšeš, je docela nepřehledný. Funkce popis_balicku tomu příliš nepomáhá, protože popisuje jen vrchní kartu. Aby se ti s balíčkem lépe pracovalo, vytvoř následující funkci:

def popis_seznam_karet(karty):
    """Vrátí popis všech karet v balíčku. Jednotlivé karty odděluje mezerami.
    """

Nezapomeň využít funkci popis_kartu!

Například:

>>> karty = [
        (13, 'Pi', True),
        (12, 'Sr', True),
        (11, 'Ka', True),
        (10, 'Kr', False),
    ]

>>> popis_seznam_karet(karty)
[A♠ ] [2 ♥] [3 ♦] [???]
  • level 25: Funkce existuje
  • level 26: Funkce správně popisuje balíček
  • level 27: Funkce umí popsat i prázdný balíček

Rozdání sloupečků

Teď zkus rozdat 7 sloupečků karet, tedy konečně první krok hry.

N-tém sloupečku (počítáno od nuly) je N karet rubem nahoru plus jedna karta lícem nahoru. Karty do sloupečků se z balíčku rozdávají postupně: vždy se lízne vrchní (poslední) karta z balíčku a dá se na konec sloupečku.

Ukázka sloupečků

Napiš následující funkci:

def rozdej_sloupecky(balicek):
    """Rozdá z daného balíčku 7 "sloupečků" -- seznamů karet

    Karty ve sloupečcích jsou odstraněny z balíčku.
    Vrátí všechny sloupečky -- tedy seznam sedmi seznamů.
    """

Například:

>>> balicek = priprav_balicek()
>>> sloupecky = rozdej_sloupecky(balicek)
24
>>> popis_seznam_karet(sloupecky[0])
[3♣ ]
>>> popis_seznam_karet(sloupecky[1])
[???] [5 ♥]
>>> popis_seznam_karet(sloupecky[2])
[???] [???] [6♣ ]
>>> popis_seznam_karet(sloupecky[6])
[???] [???] [???] [???] [???] [???] [3 ♦]
>>> len(balicek)    # Z balíčku zmizely karty, které jsou ve sloupečcích

Jak tahle funkce funguje?

  • Vytvoří prázdný seznam sloupečků
  • Sedmkrat (pro N od 0 do 6):
    • Vytvoří prázdný sloupeček (seznam)
    • N-krát za sebou:
      • „Lízne“ (pop) kartu zvrchu balíčku
      • Dá líznutou kartu na vršek sloupečku (append)
    • „Lízne“ (pop) kartu zvrchu balíčku
    • Líznutou kartu otočí lícem nahoru (otoc_kartu) a dá vršek sloupečku (append)
    • Hotový sloupeček přidá do seznamu sloupečků
  • Výsledné sloupečky vrátí

Testy:

  • level 30: Funkce existuje
  • level 31: Funkce vrací seznam sedmi seznamů
  • level 32:
    • V každém sloupečku je aspoň jedna karta
    • Poslední karta je lícem nahoru
  • level 33: V každém sloupečku je správný počet karet rubem nahoru

Vypsání sloupečků

Vzpomínáš si na základní schéma hry?

  • Rozdej balíček a sloupečky karet
  • Dokud hráč nevyhrál:
    • Zobraz stav hry
    • Zeptej se hráče, kam chce hrát
    • Je-li to možné:
      • Proveď tah
    • Jinak:
      • Vynadej hráči, že daný tah nedává smysl
  • Pogratuluj hráči

Rozdání balíčku a sloupečků už víceméně máš! Pro teď přeskoč zjišťování, jestli hráč vyhrál, a podívej se na vypsání stavu hry.

Například, pokud jsou sloupečky tyto:

sloupecky = [
    [(1, 'Pi', True), (7, 'Sr', True)],
    [(2, 'Sr', True), (6, 'Ka', True)],
    [(3, 'Ka', True), (5, 'Kr', False)],
    [(4, 'Kr', False), (4, 'Pi', True)],
    [(5, 'Pi', False), (3, 'Sr', True)],
    [(6, 'Sr', True), (2, 'Ka', True)],
    [(7, 'Ka', True), (1, 'Kr', True), (10, 'Ka', True)],
]

… můžeš je vypsat jednotlivě:

>>> for sloupecek in sloupecky:
>>>     print(popis_seznam_karet(sloupecek))
[A♠ ] [7 ♥]
[2 ♥] [6 ♦]
[3 ♦] [???]
[???] [4♠ ]
[???] [3 ♥]
[6 ♥] [2 ♦]
[7 ♦] [A♣ ] [X ♦]

To ale není to, co chceme vypsat ve hře: tam se karty v jednom sloupečku ukazují pod sebou.

Budeš potřebovat na prvním řádku ukázat první karty ze všech sloupečků, na druhém řádku druhé karty ze všech sloupečků, na třetím třetí, atd. Pro příklad výše by tedy mělo vyjít:

[A♠ ] [2 ♥] [3 ♦] [???] [???] [6 ♥] [7 ♦]
[7 ♥] [6 ♦] [???] [4♠ ] [3 ♥] [2 ♦] [A♣ ]
                                    [X ♦]

Znáš funkci, která vezme několik seznamů, a dá ti k dispozici napřed první prvky těch seznamů, potom druhé, a tak dál? Zkus ji použít!

def vypis_sloupecky(sloupecky):
    """Vypíše sloupečky textově.

    Tato funkce je jen pro zobrazení, používá proto přímo funkci print()
    a nic nevrací.
    """
  • level 40: Funkce existuje
  • level 41: Funkce vypisuje karty ze věch sloupečků
  • level 42: Funkce funguje, když jsou sloupečky nestejně dlouhé. (Na prázdné místo patří 5 mezer.)

Práce se sloupečky

Aby sis v budoucnu ušetřila práci, a aby sis procvičila seznamy, zkus teď napsat dvě funkce, které přesunují karty mezi balíčky:

def presun_kartu(sloupec_odkud, sloupec_kam, pozadovane_otoceni):
    """Přesune vrchní kartu ze sloupce "odkud" do sloupce "kam".
    Karta bude otocena lícem nebo rubem nahoru podle "pozadovane_otoceni".
    """

def presun_nekolik_karet(sloupec_odkud, sloupec_kam, pocet):
    """Přesune "pocet" vrchních karet ze sloupce "odkud" do sloupce "kam".
    Karty se přitom neotáčí.
    """
  • level 50: Funkce presun_kartu existuje
  • level 51: Funkce presun_kartu funguje dle zadání
  • level 60: Funkce presun_nekolik_karet existuje
  • level 61: Funkce presun_nekolik_karet funguje dle zadání

Hra

Vzpomínáš si na schéma hry?

  • Rozdej balíček a sloupečky karet
  • Dokud hráč nevyhrál:
    • Zobraz stav hry
    • Zeptej se hráče, odkud a kam chce hrát
    • Je-li to možné:
      • Proveď tah
    • Jinak:
      • Vynadej hráči, že daný tah nedává smysl
  • Pogratuluj hráči

V Pythonu to bude vypadat následovně. Program si ulož do modulu hra.py:

hra = udelej_hru()

while not hrac_vyhral(hra):
    vypis_hru(hra)
    odkud, kam = nacti_tah()
    try:
        udelej_tah(hra, odkud, kam)
    except ValueError as e:
        print('Něco je špatně:', e)

vypis_hru(hra)
print('Gratuluji!')

K tomu, abys doplnila funkce do této hry, budeš potřebovat namodelovat onu hru. Ta se skládá z několika balíčků/sloupečků, tedy seznamů karet. Ve výpisu butou pojmenované A-Z:

   U     V          W     X     Y     Z
 [???] [   ]      [   ] [   ] [   ] [   ]

   A     B     C     D     E     F     G
 [3♣ ] [???] [???] [???] [???] [???] [???]
       [5 ♥] [???] [???] [???] [???] [???]
             [6♣ ] [???] [???] [???] [???]
                   [5♠ ] [???] [???] [???]
                         [Q ♥] [???] [???]
                               [4♠ ] [???]
                                     [3 ♦]
  • U je dobírací balíček, ze kterého se doplňuje V.
  • V je balíček, ze kterého můžeš brát karty
  • W-Z jsou cílové hromádky. Cílem hry je na ně přemístit všechny karty.
  • A-G jsou sloupečky, kde se karty dají přeskládávat.

Těchto 13 pojmenovaných seznamů reprezentuje celý stav rozehrané hry. Hru proto budeme reprezentovat slovníkem, kde klíče budou písmenka a hodloty pak jednotlivé seznamy.

Následující funkce takovou hru vytvoří:

def udelej_hru():
    """Vrátí slovník reprezentující novou hru.
    """
    balicek = vytvor_balicek()

    hra = {
        'U': balicek,
    }
    # V-Z začínají jako prázdné seznamy
    for pismenko in 'VWXYZ':
        hra[pismenko] = []

    # A-G jsou sloupečky
    for pismenko, sloupec in zip('ABCDEFG', rozdej_sloupecky(balicek)):
        hra[pismenko] = sloupec

    return hra

A takhle se hra dá vypsat:

def vypis_hru(hra):
    """Vypíše hru textově.

    Tato funkce je jen pro zobrazení, používá proto přímo funkci print()
    a nic nevrací.
    """
    print()
    print('  U     V           W     X     Y     Z')
    print('{} {}       {} {} {} {}'.format(
        popis_balicku(hra['U']),
        popis_balicku(hra['V']),
        popis_balicku(hra['W']),
        popis_balicku(hra['X']),
        popis_balicku(hra['Y']),
        popis_balicku(hra['Z']),
    ))
    print()
    print('  A     B     C     D     E     F     G')
    vypis_sloupecky([hra['A'], hra['B'], hra['C'], hra['D'],
                     hra['E'], hra['F'], hra['G']])
    print()

Pro kontrolu můžeš pustit testy:

  • Level 70: Funkce udelej_hru existuje
  • Level 71: Funkce udelej_hru funguje dle zadání
  • Level 80: Funkce vypis_hru existuje
  • Level 81: Funkce vypis_hru funguje dle zadání

Načtení tahu

Hra se bude ovládat zadáním dvou jmen balíčku: odkud a kam hráč chce kartu přesunout.

Tahle funkce není součást logiky hry. Dej ji do hra.py.

def nacti_tah():
    while True:
        tah = input('Tah? ')
        try:
            jmeno_zdroje, jmeno_cile = tah.upper()
        except ValueError:
            print('Tah zadávej jako dvě písmenka, např. UV')
        else:
            return jmeno_zdroje, jmeno_cile

Zástupné funkce

K úplné hře nám chybí ještě samotná logika hry: hrac_vyhral a udelej_tah.

Aby nám hra aspoň trochu fungovala, vytvoř si zástupné funkce, které nic nekontrolují a nenechají tě vyhrát:

def hrac_vyhral(hra):
    """Vrací True, pokud je hra vyhraná.
    """
    return False

def udelej_tah(hra, jmeno_odkud, jmeno_kam):
    presun_kartu(hra[jmeno_odkud], hra[jmeno_kam], True)

Obě bude ještě potřeba upravit, ale teď už si můžeš hru víceméně zahrát! Zkus si to!

Jiné rozhraní

Celý tento projekt píšeš ve funkcích s daným jménem a s daným počtem a významem argumentů. To má dvě výhody.

První z nich je testování: připravené testy importují tvé funkce a zkouší je, takže si můžeš být jista, že fungují.

Druhá je zajímavější: máš-li logiku hry, funkce udelej_hru udelej_tah a hrac_vyhral, napsané podle specifikací, může je použít i jakýkoli jiný program – ne jen ten, který jsi napsala ty.

Jeden takový si můžeš vyzkoušet:

  • Nainstaluj si do virtuálního prostředí knihovnu pyglet:

    (venv)$ python -m pip install pyglet
    
  • Stáhni si do aktuálního adresáře soubory ui.py a cards.png.

  • Hru spusť pomocí:

    (venv)$ python ui.py
    

Obrázky karet jsou z Board Game Pack studia kenney.nl.

Logika hry

Zbývá doplnit „pravidla hry“ do dvou funkcí, hrac_vyhral a udelej_tah. To už bude na tobě.

hrac_vyhral

Hráč vyhrál, pokud jsou všechny karty na cílových hromádkách W-Z.

udelej_tah

Když tah není podle pravidel, funkce udelej_tah vyhodí ValueError.

Možné tahy:

  • UV:
    • V balíčku U musí něco být
    • Přesouvá se jedna karta; otočí se lícem nahoru
  • VU:
    • V balíčku U nesmí být nic
    • Přesouvají se všechny karty, seřazené v opačném pořadí; otočí se rubem nahoru (tj. volej dokola presun_kartu(hra['V'], hra['U'], False) dokud ve V něco je)
  • Balíček V nebo sloupeček A-G (zdroj) → cíl W-Z:
    • Přesouvá se jedna karta
    • Je-li cíl prázdný:
      • Musí to být eso
    • Jinak:
      • Přesouvaná karta musí mít stejnou barvu jako vrchní karta cíle
      • Přesouvaná karta musí být o 1 vyšší než vrchní karta cíle
    • Je-li zdroj po přesunu neprázdný, jeho vrchní karta se otočí lícem nahoru
  • Balíček V → „cílový“ sloupeček A-G
    • Přesouvá se jedna karta
    • Přesouvaná karta musí pasovat*⁾ na cílový sloupeček
  • „Zdrojový“ sloupeček A-G → „cílový“ sloupeček A-G
    • Přesouvá se několik karet
      • (zkontroluj všechny možnosti: 1 až počet karet ve zdrojovém sloupečku; vždy je max. jedna správná možnost)
    • Všechny přesouvané karty musí být otočené lícem nahoru
    • První z přesouvaných karet musí pasovat*) na cílový sloupeček
  • Cíl W-Z → sloupeček A-G (nepovinné – jen v některých variantách hry)
    • Přesouvá se jedna karta
    • Přesouvaná karta musí pasovat*) na cílový sloupeček

*⁾ Kdy přesouvaná karta pasuje na sloupeček?

  • Je-li sloupeček prázdný:
    • Karta musí být král
  • Jinak:
    • Barva přesouvané karty musí být opačná než barva vrchní karty sloupečku, tedy:
      • Červená (♥ nebo ♦) jde dát jen na černou (♠ nebo ♣)
      • Černá (♠ nebo ♣) jde dát jen na červenou (♥ nebo ♦)
    • Hodnota přesouvané karty musí být o 1 nižší než hodnota vrchní karty sloupečku
{
  "data": {
    "sessionMaterial": {
      "id": "session-material:2019/brno-jaro-2019-pondeli:solitaire:2",
      "title": "Klondike Solitaire (viz nledující lekce; došli jsme do „Vytvoření balíčku“)",
      "html": "\n          \n    \n\n    <h1>Klondike Solitaire</h1>\n<p>Poj&#x10F;me vytvo&#x159;it karetn&#xED; hru <em>Klondike Solitaire</em>, kterou mo&#x17E;n&#xE1; zn&#xE1;&#x161; v&#xA0;n&#x11B;jak&#xE9;\npo&#x10D;&#xED;ta&#x10D;ov&#xE9; verzi.</p>\n<p><span class=\"figure\"><a href=\"/2019/brno-jaro-2019-pondeli/projects/klondike/static/klondike.png\"><img src=\"/2019/brno-jaro-2019-pondeli/projects/klondike/static/klondike.png\" alt=\"Jedna z grafick&#xFD;ch podob hry\"></a></span></p>\n<p>Na&#x161;e hra bude ze za&#x10D;&#xE1;tku jednodu&#x161;&#x161;&#xED; &#x2013; nebudeme se zab&#xFD;vat grafikou,\nale logikou hry.\n&#x201E;Grafiku&#x201C; zat&#xED;m zajist&#xED; textov&#xE1; konzole:</p>\n<div class=\"highlight\"><pre><code>   U     V          W     X     Y     Z\n [???] [   ]      [   ] [   ] [   ] [   ]\n\n   A     B     C     D     E     F     G\n [3&#x2663; ] [???] [???] [???] [???] [???] [???]\n       [5 &#x2665;] [???] [???] [???] [???] [???]\n             [6&#x2663; ] [???] [???] [???] [???]\n                   [5&#x2660; ] [???] [???] [???]\n                         [Q &#x2665;] [???] [???]\n                               [4&#x2660; ] [???]\n                                     [3 &#x2666;]</code></pre></div><h2>Sch&#xE9;ma hry</h2>\n<p>Hra funguje takto:</p>\n<ul>\n<li>Rozdej bal&#xED;&#x10D;ek a sloupe&#x10D;ky karet</li>\n<li>Dokud hr&#xE1;&#x10D; nevyhr&#xE1;l:<ul>\n<li>Zobraz stav hry</li>\n<li>Zeptej se hr&#xE1;&#x10D;e, odkud a kam chce hr&#xE1;t</li>\n<li>Je-li to mo&#x17E;n&#xE9;:<ul>\n<li>Prove&#x10F; tah</li>\n</ul>\n</li>\n<li>Jinak:<ul>\n<li>Vynadej hr&#xE1;&#x10D;i, &#x17E;e dan&#xFD; tah ned&#xE1;v&#xE1; smysl</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>Pogratuluj hr&#xE1;&#x10D;i</li>\n</ul>\n<h2>Karta</h2>\n<p>Karta bude trojice (hodnota, barva, je_licem_nahoru) &#x2013; viz sraz.\nN&#xE1;sleduj&#xED;c&#xED; funkce (v&#xA0;souboru <a href=\"/2019/brno-jaro-2019-pondeli/projects/klondike/static/karty.py\"><code>karty.py</code></a>) n&#xE1;m zjednodu&#x161;&#xED; pr&#xE1;ci:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">popis_kartu</span><span class=\"p\">(</span><span class=\"n\">karta</span><span class=\"p\">):</span>\n    <span class=\"sd\">&quot;&quot;&quot;Vr&#xE1;t&#xED; popis karty, nap&#x159;. [Q &#x2665;] nebo [6&#x2663; ] nebo [???]</span>\n\n<span class=\"sd\">    Trojice &#x10D;&#xED;sla (2-13), kr&#xE1;tk&#xE9;ho &#x159;et&#x11B;zce (&apos;Sr&apos;, &apos;Ka&apos;, &apos;Kr&apos; nebo &apos;Pi&apos;)</span>\n<span class=\"sd\">    a logick&#xE9; hodnoty (True - l&#xED;cem nahoru; False - rubem) se jednodu&#x161;e</span>\n<span class=\"sd\">    zpracov&#xE1;v&#xE1; v Pythonu, ale pro &quot;u&#x17E;ivatele&quot; nen&#xED; nic moc.</span>\n<span class=\"sd\">    Proto je tu tahle funkce, kter&#xE1; kartu hezky &quot;pop&#xED;&#x161;e&quot;.</span>\n\n<span class=\"sd\">    Aby byly v&#x161;echny karty jedno &#x10D;&#xED;slo nebo p&#xED;smeno, se des&#xED;tka</span>\n<span class=\"sd\">    se vypisuje jako &quot;X&quot;.</span>\n\n<span class=\"sd\">    Aby se dalo rychle odli&#x161;it &#x10D;erven&#xE9; (&#x2665;&#x2666;) karty od &#x10D;ern&#xFD;ch (&#x2663;&#x2660;),</span>\n<span class=\"sd\">    maj&#xED; &#x10D;erven&#xE9; mezeru p&#x159;ed symbolem a &#x10D;ern&#xE9; za n&#xED;m.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n</pre></div><div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">otoc_kartu</span><span class=\"p\">(</span><span class=\"n\">karta</span><span class=\"p\">,</span> <span class=\"n\">pozadovane_otoceni</span><span class=\"p\">):</span>\n    <span class=\"sd\">&quot;&quot;&quot;Vr&#xE1;t&#xED; kartu oto&#x10D;enou l&#xED;cem nahoru (True) nebo rubem nahoru (False)</span>\n\n<span class=\"sd\">    Nem&#x11B;n&#xED; p&#x16F;vodn&#xED; trojici; vytvo&#x159;&#xED; a vr&#xE1;t&#xED; novou.</span>\n<span class=\"sd\">    (Ani by to jinak ne&#x161;lo &#x2013; n-tice se, podobn&#x11B; jako &#x159;et&#x11B;zce &#x10D;&#xED;sla, m&#x11B;nit</span>\n<span class=\"sd\">    nedaj&#xED;.)</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n</pre></div><p>Funkce najde&#x161; v souboru <a href=\"/2019/brno-jaro-2019-pondeli/projects/klondike/static/karty.py\"><code>karty.py</code></a>. Projdi si je; rozum&#xED;&#x161; jim?</p>\n<p>Testy k nim jsou v&#xA0;<a href=\"/2019/brno-jaro-2019-pondeli/projects/klondike/static/test_karty.py\"><code>test_karty.py</code></a> &#x2013; ty proch&#xE1;zet nemus&#xED;&#x161;, jestli nechce&#x161;.</p>\n<h2>Testy a &#xFA;koly</h2>\n<p>St&#xE1;hni si soubor s testy, <a href=\"/2019/brno-jaro-2019-pondeli/projects/klondike/static/test_klondike.py\">test_klondike.py</a>, a dej ho do adres&#xE1;&#x159;e,\nkde bude&#x161; tvo&#x159;it hru a kde m&#xE1;&#x161; <code>karty.py</code>.</p>\n<p>Na uleh&#x10D;en&#xED; testov&#xE1;n&#xED; si nainstaluj modul <code>pytest-level</code>.\nTen umo&#x17E;&#x148;uje pou&#x161;t&#x11B;t jen ur&#x10D;it&#xE9; testy &#x2013; podle toho, jak jsi daleko.</p>\n<div class=\"highlight\"><pre><code>python -m pip install pytest pytest-level\n\n</code></pre></div><p>Zkus pustit v&#x161;echny testy. Asi ti neprojdou:</p>\n<div class=\"highlight\"><pre><code>python -m pytest -v\n\n</code></pre></div><p>Pak zkus pustit testy pro &#xFA;rove&#x148; 0:</p>\n<div class=\"highlight\"><pre><code>python -m pytest -v --level 0\n\n</code></pre></div><p>Te&#x10F; se nepust&#xED; &#x17E;&#xE1;dn&#xE9; testy &#x2013; v&#x161;echny se p&#x159;esko&#x10D;&#xED;. V&#xFD;pis by m&#x11B;l kon&#x10D;it n&#x11B;jak takto:</p>\n<div class=\"highlight\"><pre><code>collected N items / N deselected\n=== N deselected in 0.01 seconds ===\n\n</code></pre></div><p>Zad&#xE1;&#x161;-li v posledn&#xED;m p&#x159;&#xED;kazu --level 1, aktivuje se prvn&#xED; z test&#x16F;. Pravd&#x11B;podobn&#x11B; neprojde &#x2013; v dal&#x161;&#xED;m &#xFA;kolu ho sprav&#xED;&#x161;!</p>\n<h2>Popis bal&#xED;&#x10D;ku</h2>\n<p>Jako prvn&#xED; v&#x11B;c ve h&#x159;e pot&#x159;ebujeme rozdat <em>bal&#xED;&#x10D;ek</em> karet.\nCo je to ale takov&#xFD; bal&#xED;&#x10D;ek?\nJak se d&#xE1; bal&#xED;&#x10D;ek karet reprezentovat pomoc&#xED; &#x159;et&#x11B;zc&#x16F;, &#x10D;&#xED;sel, seznam&#x16F;,\n<var>n</var>-tic a podobn&#x11B;?</p>\n<p>Zp&#x16F;sob&#x16F;, jak takov&#xFD; bal&#xED;&#x10D;ek karet reprezentovat, je v&#xED;ce.\nAbychom m&#x11B;li projekt v&#x161;ichni stejn&#xFD; (a aby k&#xA0;n&#x11B;mu mohly b&#xFD;t testy),\nje v&#xA0;t&#x11B;chto materi&#xE1;lech tento &#xFA;kol u&#x17E; vy&#x159;e&#x161;en&#xFD;.</p>\n<p>Bal&#xED;&#x10D;ek karet bude <em>seznam</em> karet &#x2013; tedy seznam trojic.\nTo d&#xE1;v&#xE1; smysl &#x2013; karet v bal&#xED;&#x10D;ku m&#x16F;&#x17E;e b&#xFD;t r&#x16F;zn&#xFD; po&#x10D;et (klidn&#x11B; 0),\nkar se z n&#x11B;j daj&#xED; br&#xE1;t nebo do n&#x11B;j p&#x159;id&#xE1;vat, bal&#xED;&#x10D;ek se d&#xE1; zam&#xED;chat nebo\nse&#x159;adit.</p>\n<p>Bal&#xED;&#x10D;ek bude nap&#x159;&#xED;klad:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">balicek</span> <span class=\"o\">=</span> <span class=\"p\">[(</span><span class=\"mi\">4</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Pi&apos;</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">4</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Sr&apos;</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">4</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Ka&apos;</span><span class=\"p\">,</span> <span class=\"bp\">False</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">4</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Kr&apos;</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">)]</span>\n<span class=\"n\">prazdny_balicek</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n</pre></div><p>Napi&#x161; n&#xE1;sleduj&#xED;c&#xED; funkci, kter&#xE1; bal&#xED;&#x10D;ek pop&#xED;&#x161;e:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">popis_balicku</span><span class=\"p\">(</span><span class=\"n\">balicek</span><span class=\"p\">):</span>\n    <span class=\"sd\">&quot;&quot;&quot;Vr&#xE1;t&#xED; popis dan&#xE9;ho bal&#xED;&#x10D;ku karet -- tedy vrchn&#xED; karty, kter&#xE1; je vid&#x11B;t&quot;&quot;&quot;</span>\n</pre></div><ul>\n<li>level 10: Funkce existuje</li>\n<li>level 11: Funkce vr&#xE1;t&#xED; popis posledn&#xED; karty. (Bude se hodit funkce <code>popis_kartu</code> z modulu <code>karty</code>.)</li>\n<li>level 12: Funkce pop&#xED;&#x161;e pr&#xE1;zdn&#xFD; bal&#xED;&#x10D;ek jako <code>[   ]</code> (3 mezery v hranat&#xFD;ch z&#xE1;vork&#xE1;ch).</li>\n</ul>\n<h2>Vytvo&#x159;en&#xED; bal&#xED;&#x10D;ku</h2>\n<p>Napi&#x161; n&#xE1;sleduj&#xED;c&#xED; funkci:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">vytvor_balicek</span><span class=\"p\">():</span>\n    <span class=\"sd\">&quot;&quot;&quot;Vr&#xE1;t&#xED; bal&#xED;&#x10D;ek 52 karet &#x2013; od esa (1) po kr&#xE1;le (13) ve &#x10D;ty&#x159;ech barv&#xE1;ch</span>\n\n<span class=\"sd\">    Karty jsou oto&#x10D;en&#xE9; rubem nahoru (nejsou vid&#x11B;t).</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n</pre></div><ul>\n<li>level 20: Funkce existuje</li>\n<li>level 21: V&#xA0;bal&#xED;&#x10D;ku je 52 karet, &#x17E;&#xE1;dn&#xE9; se neopakuj&#xED;.</li>\n<li>level 22: V&#xA0;bal&#xED;&#x10D;ku jsou v&#x161;echny po&#x17E;adovan&#xE9; karty.</li>\n<li>level 23: Bal&#xED;&#x10D;ek je zam&#xED;chan&#xFD;.</li>\n</ul>\n<h2>Rozeps&#xE1;n&#xED; bal&#xED;&#x10D;ku</h2>\n<p>Kdy&#x17E; v&#xFD;sledek funkce <code>vytvor_balicek</code>  vyp&#xED;&#x161;e&#x161;, je docela nep&#x159;ehledn&#xFD;.\nFunkce <code>popis_balicku</code> tomu p&#x159;&#xED;li&#x161; nepom&#xE1;h&#xE1;, proto&#x17E;e popisuje jen vrchn&#xED; kartu.\nAby se ti s&#xA0;bal&#xED;&#x10D;kem l&#xE9;pe pracovalo, vytvo&#x159; n&#xE1;sleduj&#xED;c&#xED; funkci:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">popis_seznam_karet</span><span class=\"p\">(</span><span class=\"n\">karty</span><span class=\"p\">):</span>\n    <span class=\"sd\">&quot;&quot;&quot;Vr&#xE1;t&#xED; popis v&#x161;ech karet v bal&#xED;&#x10D;ku. Jednotliv&#xE9; karty odd&#x11B;luje mezerami.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n</pre></div><p>Nezapome&#x148; vyu&#x17E;&#xED;t funkci <code>popis_kartu</code>!</p>\n<p>Nap&#x159;&#xED;klad:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">karty</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n<span class=\"go\">        (13, &apos;Pi&apos;, True),</span>\n<span class=\"go\">        (12, &apos;Sr&apos;, True),</span>\n<span class=\"go\">        (11, &apos;Ka&apos;, True),</span>\n<span class=\"go\">        (10, &apos;Kr&apos;, False),</span>\n<span class=\"go\">    ]</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">popis_seznam_karet</span><span class=\"p\">(</span><span class=\"n\">karty</span><span class=\"p\">)</span>\n<span class=\"go\">[A&#x2660; ] [2 &#x2665;] [3 &#x2666;] [???]</span>\n</pre></div><ul>\n<li>level 25: Funkce existuje</li>\n<li>level 26: Funkce spr&#xE1;vn&#x11B; popisuje bal&#xED;&#x10D;ek</li>\n<li>level 27: Funkce um&#xED; popsat i pr&#xE1;zdn&#xFD; bal&#xED;&#x10D;ek</li>\n</ul>\n<h2>Rozd&#xE1;n&#xED; sloupe&#x10D;k&#x16F;</h2>\n<p>Te&#x10F; zkus rozdat 7 sloupe&#x10D;k&#x16F; karet, tedy kone&#x10D;n&#x11B; prvn&#xED; krok hry.</p>\n<p>V&#xA0;<var>N</var>-t&#xE9;m sloupe&#x10D;ku (po&#x10D;&#xED;t&#xE1;no od nuly) je <var>N</var>\nkaret rubem nahoru plus jedna karta l&#xED;cem nahoru.\nKarty do sloupe&#x10D;k&#x16F; se z&#xA0;bal&#xED;&#x10D;ku rozd&#xE1;vaj&#xED; postupn&#x11B;: v&#x17E;dy se l&#xED;zne\nvrchn&#xED; (posledn&#xED;) karta z&#xA0;bal&#xED;&#x10D;ku a d&#xE1; se na konec sloupe&#x10D;ku.</p>\n<p><span class=\"figure\"><a href=\"/2019/brno-jaro-2019-pondeli/projects/klondike/static/klondike.png\"><img src=\"/2019/brno-jaro-2019-pondeli/projects/klondike/static/klondike.png\" alt=\"Uk&#xE1;zka sloupe&#x10D;k&#x16F;\"></a></span></p>\n<p>Napi&#x161; n&#xE1;sleduj&#xED;c&#xED; funkci:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">rozdej_sloupecky</span><span class=\"p\">(</span><span class=\"n\">balicek</span><span class=\"p\">):</span>\n    <span class=\"sd\">&quot;&quot;&quot;Rozd&#xE1; z dan&#xE9;ho bal&#xED;&#x10D;ku 7 &quot;sloupe&#x10D;k&#x16F;&quot; -- seznam&#x16F; karet</span>\n\n<span class=\"sd\">    Karty ve sloupe&#x10D;c&#xED;ch jsou odstran&#x11B;ny z bal&#xED;&#x10D;ku.</span>\n<span class=\"sd\">    Vr&#xE1;t&#xED; v&#x161;echny sloupe&#x10D;ky -- tedy seznam sedmi seznam&#x16F;.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n</pre></div><p>Nap&#x159;&#xED;klad:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">balicek</span> <span class=\"o\">=</span> <span class=\"n\">priprav_balicek</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">sloupecky</span> <span class=\"o\">=</span> <span class=\"n\">rozdej_sloupecky</span><span class=\"p\">(</span><span class=\"n\">balicek</span><span class=\"p\">)</span>\n<span class=\"go\">24</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">popis_seznam_karet</span><span class=\"p\">(</span><span class=\"n\">sloupecky</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">])</span>\n<span class=\"go\">[3&#x2663; ]</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">popis_seznam_karet</span><span class=\"p\">(</span><span class=\"n\">sloupecky</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">])</span>\n<span class=\"go\">[???] [5 &#x2665;]</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">popis_seznam_karet</span><span class=\"p\">(</span><span class=\"n\">sloupecky</span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"p\">])</span>\n<span class=\"go\">[???] [???] [6&#x2663; ]</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">popis_seznam_karet</span><span class=\"p\">(</span><span class=\"n\">sloupecky</span><span class=\"p\">[</span><span class=\"mi\">6</span><span class=\"p\">])</span>\n<span class=\"go\">[???] [???] [???] [???] [???] [???] [3 &#x2666;]</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">balicek</span><span class=\"p\">)</span>    <span class=\"c1\"># Z bal&#xED;&#x10D;ku zmizely karty, kter&#xE9; jsou ve sloupe&#x10D;c&#xED;ch</span>\n</pre></div><p>Jak tahle funkce funguje?</p>\n<ul>\n<li>Vytvo&#x159;&#xED; pr&#xE1;zdn&#xFD; seznam sloupe&#x10D;k&#x16F;</li>\n<li>Sedmkrat (pro <var>N</var> od 0 do 6):<ul>\n<li>Vytvo&#x159;&#xED; pr&#xE1;zdn&#xFD; sloupe&#x10D;ek (seznam)</li>\n<li><var>N</var>-kr&#xE1;t za sebou:<ul>\n<li>&#x201E;L&#xED;zne&#x201C; (<code>pop</code>) kartu zvrchu bal&#xED;&#x10D;ku</li>\n<li>D&#xE1; l&#xED;znutou kartu na vr&#x161;ek sloupe&#x10D;ku (<code>append</code>)</li>\n</ul>\n</li>\n<li>&#x201E;L&#xED;zne&#x201C; (<code>pop</code>) kartu zvrchu bal&#xED;&#x10D;ku</li>\n<li>L&#xED;znutou kartu oto&#x10D;&#xED; l&#xED;cem nahoru (<code>otoc_kartu</code>)\na d&#xE1; vr&#x161;ek sloupe&#x10D;ku (<code>append</code>)</li>\n<li>Hotov&#xFD; sloupe&#x10D;ek p&#x159;id&#xE1; do seznamu sloupe&#x10D;k&#x16F;</li>\n</ul>\n</li>\n<li>V&#xFD;sledn&#xE9; sloupe&#x10D;ky vr&#xE1;t&#xED;</li>\n</ul>\n<p>Testy:</p>\n<ul>\n<li>level 30: Funkce existuje</li>\n<li>level 31: Funkce vrac&#xED; seznam sedmi seznam&#x16F;</li>\n<li>level 32:<ul>\n<li>V ka&#x17E;d&#xE9;m sloupe&#x10D;ku je aspo&#x148; jedna karta</li>\n<li>Posledn&#xED; karta je l&#xED;cem nahoru</li>\n</ul>\n</li>\n<li>level 33: V ka&#x17E;d&#xE9;m sloupe&#x10D;ku je spr&#xE1;vn&#xFD; po&#x10D;et karet rubem nahoru</li>\n</ul>\n<h2>Vyps&#xE1;n&#xED; sloupe&#x10D;k&#x16F;</h2>\n<p>Vzpom&#xED;n&#xE1;&#x161; si na z&#xE1;kladn&#xED; sch&#xE9;ma hry?</p>\n<ul>\n<li>Rozdej bal&#xED;&#x10D;ek a sloupe&#x10D;ky karet</li>\n<li>Dokud hr&#xE1;&#x10D; nevyhr&#xE1;l:<ul>\n<li>Zobraz stav hry</li>\n<li>Zeptej se hr&#xE1;&#x10D;e, kam chce hr&#xE1;t</li>\n<li>Je-li to mo&#x17E;n&#xE9;:<ul>\n<li>Prove&#x10F; tah</li>\n</ul>\n</li>\n<li>Jinak:<ul>\n<li>Vynadej hr&#xE1;&#x10D;i, &#x17E;e dan&#xFD; tah ned&#xE1;v&#xE1; smysl</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>Pogratuluj hr&#xE1;&#x10D;i</li>\n</ul>\n<p>Rozd&#xE1;n&#xED; bal&#xED;&#x10D;ku a sloupe&#x10D;k&#x16F; u&#x17E; v&#xED;cem&#xE9;n&#x11B; m&#xE1;&#x161;!\nPro te&#x10F; p&#x159;esko&#x10D; zji&#x161;&#x165;ov&#xE1;n&#xED;, jestli hr&#xE1;&#x10D; vyhr&#xE1;l, a pod&#xED;vej se na vyps&#xE1;n&#xED;\nstavu hry.</p>\n<p>Nap&#x159;&#xED;klad, pokud jsou sloupe&#x10D;ky tyto:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">sloupecky</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"p\">[(</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Pi&apos;</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">7</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Sr&apos;</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">)],</span>\n    <span class=\"p\">[(</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Sr&apos;</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">6</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Ka&apos;</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">)],</span>\n    <span class=\"p\">[(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Ka&apos;</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">5</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Kr&apos;</span><span class=\"p\">,</span> <span class=\"bp\">False</span><span class=\"p\">)],</span>\n    <span class=\"p\">[(</span><span class=\"mi\">4</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Kr&apos;</span><span class=\"p\">,</span> <span class=\"bp\">False</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">4</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Pi&apos;</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">)],</span>\n    <span class=\"p\">[(</span><span class=\"mi\">5</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Pi&apos;</span><span class=\"p\">,</span> <span class=\"bp\">False</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Sr&apos;</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">)],</span>\n    <span class=\"p\">[(</span><span class=\"mi\">6</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Sr&apos;</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Ka&apos;</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">)],</span>\n    <span class=\"p\">[(</span><span class=\"mi\">7</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Ka&apos;</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Kr&apos;</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">),</span> <span class=\"p\">(</span><span class=\"mi\">10</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Ka&apos;</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">)],</span>\n<span class=\"p\">]</span>\n</pre></div><p>&#x2026; m&#x16F;&#x17E;e&#x161; je vypsat jednotliv&#x11B;:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"k\">for</span> <span class=\"n\">sloupecek</span> <span class=\"ow\">in</span> <span class=\"n\">sloupecky</span><span class=\"p\">:</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>    <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">popis_seznam_karet</span><span class=\"p\">(</span><span class=\"n\">sloupecek</span><span class=\"p\">))</span>\n<span class=\"go\">[A&#x2660; ] [7 &#x2665;]</span>\n<span class=\"go\">[2 &#x2665;] [6 &#x2666;]</span>\n<span class=\"go\">[3 &#x2666;] [???]</span>\n<span class=\"go\">[???] [4&#x2660; ]</span>\n<span class=\"go\">[???] [3 &#x2665;]</span>\n<span class=\"go\">[6 &#x2665;] [2 &#x2666;]</span>\n<span class=\"go\">[7 &#x2666;] [A&#x2663; ] [X &#x2666;]</span>\n</pre></div><p>To ale nen&#xED; to, co chceme vypsat ve h&#x159;e: tam se karty v&#xA0;jednom sloupe&#x10D;ku\nukazuj&#xED; pod sebou.</p>\n<p>Bude&#x161; pot&#x159;ebovat na prvn&#xED;m &#x159;&#xE1;dku uk&#xE1;zat prvn&#xED; karty ze v&#x161;ech sloupe&#x10D;k&#x16F;,\nna druh&#xE9;m &#x159;&#xE1;dku druh&#xE9; karty ze v&#x161;ech sloupe&#x10D;k&#x16F;, na t&#x159;et&#xED;m t&#x159;et&#xED;, atd.\nPro p&#x159;&#xED;klad v&#xFD;&#x161;e by tedy m&#x11B;lo vyj&#xED;t:</p>\n<div class=\"highlight\"><pre><code>[A&#x2660; ] [2 &#x2665;] [3 &#x2666;] [???] [???] [6 &#x2665;] [7 &#x2666;]\n[7 &#x2665;] [6 &#x2666;] [???] [4&#x2660; ] [3 &#x2665;] [2 &#x2666;] [A&#x2663; ]\n                                    [X &#x2666;]</code></pre></div><p>Zn&#xE1;&#x161; funkci, kter&#xE1; vezme n&#x11B;kolik seznam&#x16F;, a d&#xE1; ti k dispozici nap&#x159;ed prvn&#xED;\nprvky t&#x11B;ch seznam&#x16F;, potom druh&#xE9;, a tak d&#xE1;l?\nZkus ji pou&#x17E;&#xED;t!</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">vypis_sloupecky</span><span class=\"p\">(</span><span class=\"n\">sloupecky</span><span class=\"p\">):</span>\n    <span class=\"sd\">&quot;&quot;&quot;Vyp&#xED;&#x161;e sloupe&#x10D;ky textov&#x11B;.</span>\n\n<span class=\"sd\">    Tato funkce je jen pro zobrazen&#xED;, pou&#x17E;&#xED;v&#xE1; proto p&#x159;&#xED;mo funkci print()</span>\n<span class=\"sd\">    a nic nevrac&#xED;.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n</pre></div><ul>\n<li>level 40: Funkce existuje</li>\n<li>level 41: Funkce vypisuje karty ze v&#x11B;ch sloupe&#x10D;k&#x16F;</li>\n<li>level 42: Funkce funguje, kdy&#x17E; jsou sloupe&#x10D;ky nestejn&#x11B; dlouh&#xE9;. (Na pr&#xE1;zdn&#xE9; m&#xED;sto pat&#x159;&#xED; 5 mezer.)</li>\n</ul>\n<h2>Pr&#xE1;ce se sloupe&#x10D;ky</h2>\n<p>Aby sis v&#xA0;budoucnu u&#x161;et&#x159;ila pr&#xE1;ci, a aby sis procvi&#x10D;ila seznamy,\nzkus te&#x10F; napsat dv&#x11B; funkce, kter&#xE9; p&#x159;esunuj&#xED; karty mezi bal&#xED;&#x10D;ky:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">presun_kartu</span><span class=\"p\">(</span><span class=\"n\">sloupec_odkud</span><span class=\"p\">,</span> <span class=\"n\">sloupec_kam</span><span class=\"p\">,</span> <span class=\"n\">pozadovane_otoceni</span><span class=\"p\">):</span>\n    <span class=\"sd\">&quot;&quot;&quot;P&#x159;esune vrchn&#xED; kartu ze sloupce &quot;odkud&quot; do sloupce &quot;kam&quot;.</span>\n<span class=\"sd\">    Karta bude otocena l&#xED;cem nebo rubem nahoru podle &quot;pozadovane_otoceni&quot;.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">presun_nekolik_karet</span><span class=\"p\">(</span><span class=\"n\">sloupec_odkud</span><span class=\"p\">,</span> <span class=\"n\">sloupec_kam</span><span class=\"p\">,</span> <span class=\"n\">pocet</span><span class=\"p\">):</span>\n    <span class=\"sd\">&quot;&quot;&quot;P&#x159;esune &quot;pocet&quot; vrchn&#xED;ch karet ze sloupce &quot;odkud&quot; do sloupce &quot;kam&quot;.</span>\n<span class=\"sd\">    Karty se p&#x159;itom neot&#xE1;&#x10D;&#xED;.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n</pre></div><ul>\n<li>level 50: Funkce <code>presun_kartu</code> existuje</li>\n<li>level 51: Funkce <code>presun_kartu</code> funguje dle zad&#xE1;n&#xED;</li>\n<li>level 60: Funkce <code>presun_nekolik_karet</code> existuje</li>\n<li>level 61: Funkce <code>presun_nekolik_karet</code> funguje dle zad&#xE1;n&#xED;</li>\n</ul>\n<h2>Hra</h2>\n<p>Vzpom&#xED;n&#xE1;&#x161; si na sch&#xE9;ma hry?</p>\n<ul>\n<li>Rozdej bal&#xED;&#x10D;ek a sloupe&#x10D;ky karet</li>\n<li>Dokud hr&#xE1;&#x10D; nevyhr&#xE1;l:<ul>\n<li>Zobraz stav hry</li>\n<li>Zeptej se hr&#xE1;&#x10D;e, odkud a kam chce hr&#xE1;t</li>\n<li>Je-li to mo&#x17E;n&#xE9;:<ul>\n<li>Prove&#x10F; tah</li>\n</ul>\n</li>\n<li>Jinak:<ul>\n<li>Vynadej hr&#xE1;&#x10D;i, &#x17E;e dan&#xFD; tah ned&#xE1;v&#xE1; smysl</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>Pogratuluj hr&#xE1;&#x10D;i</li>\n</ul>\n<p>V&#xA0;Pythonu to bude vypadat n&#xE1;sledovn&#x11B;.\nProgram si ulo&#x17E; do modulu <code>hra.py</code>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">hra</span> <span class=\"o\">=</span> <span class=\"n\">udelej_hru</span><span class=\"p\">()</span>\n\n<span class=\"k\">while</span> <span class=\"ow\">not</span> <span class=\"n\">hrac_vyhral</span><span class=\"p\">(</span><span class=\"n\">hra</span><span class=\"p\">):</span>\n    <span class=\"n\">vypis_hru</span><span class=\"p\">(</span><span class=\"n\">hra</span><span class=\"p\">)</span>\n    <span class=\"n\">odkud</span><span class=\"p\">,</span> <span class=\"n\">kam</span> <span class=\"o\">=</span> <span class=\"n\">nacti_tah</span><span class=\"p\">()</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"n\">udelej_tah</span><span class=\"p\">(</span><span class=\"n\">hra</span><span class=\"p\">,</span> <span class=\"n\">odkud</span><span class=\"p\">,</span> <span class=\"n\">kam</span><span class=\"p\">)</span>\n    <span class=\"k\">except</span> <span class=\"ne\">ValueError</span> <span class=\"k\">as</span> <span class=\"n\">e</span><span class=\"p\">:</span>\n        <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">&apos;N&#x11B;co je &#x161;patn&#x11B;:&apos;</span><span class=\"p\">,</span> <span class=\"n\">e</span><span class=\"p\">)</span>\n\n<span class=\"n\">vypis_hru</span><span class=\"p\">(</span><span class=\"n\">hra</span><span class=\"p\">)</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">&apos;Gratuluji!&apos;</span><span class=\"p\">)</span>\n</pre></div><p>K&#xA0;tomu, abys doplnila funkce do t&#xE9;to hry, bude&#x161; pot&#x159;ebovat namodelovat\nonu <code>hru</code>.\nTa se skl&#xE1;d&#xE1; z&#xA0;n&#x11B;kolika bal&#xED;&#x10D;k&#x16F;/sloupe&#x10D;k&#x16F;, tedy seznam&#x16F; karet.\nVe v&#xFD;pisu butou pojmenovan&#xE9; A-Z:</p>\n<div class=\"highlight\"><pre><code>   U     V          W     X     Y     Z\n [???] [   ]      [   ] [   ] [   ] [   ]\n\n   A     B     C     D     E     F     G\n [3&#x2663; ] [???] [???] [???] [???] [???] [???]\n       [5 &#x2665;] [???] [???] [???] [???] [???]\n             [6&#x2663; ] [???] [???] [???] [???]\n                   [5&#x2660; ] [???] [???] [???]\n                         [Q &#x2665;] [???] [???]\n                               [4&#x2660; ] [???]\n                                     [3 &#x2666;]</code></pre></div><ul>\n<li><code>U</code> je dob&#xED;rac&#xED; bal&#xED;&#x10D;ek, ze kter&#xE9;ho se dopl&#x148;uje <code>V</code>.</li>\n<li><code>V</code> je bal&#xED;&#x10D;ek, ze kter&#xE9;ho m&#x16F;&#x17E;e&#x161; br&#xE1;t karty</li>\n<li><code>W-Z</code> jsou c&#xED;lov&#xE9; hrom&#xE1;dky. C&#xED;lem hry je na n&#x11B; p&#x159;em&#xED;stit v&#x161;echny\nkarty.</li>\n<li><code>A-G</code> jsou sloupe&#x10D;ky, kde se karty daj&#xED; p&#x159;eskl&#xE1;d&#xE1;vat.</li>\n</ul>\n<p>T&#x11B;chto 13 pojmenovan&#xFD;ch seznam&#x16F; reprezentuje cel&#xFD; stav rozehran&#xE9; hry.\nHru proto budeme reprezentovat slovn&#xED;kem, kde kl&#xED;&#x10D;e budou p&#xED;smenka\na hodloty pak jednotliv&#xE9; seznamy.</p>\n<p>N&#xE1;sleduj&#xED;c&#xED; funkce takovou hru vytvo&#x159;&#xED;:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">udelej_hru</span><span class=\"p\">():</span>\n    <span class=\"sd\">&quot;&quot;&quot;Vr&#xE1;t&#xED; slovn&#xED;k reprezentuj&#xED;c&#xED; novou hru.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n    <span class=\"n\">balicek</span> <span class=\"o\">=</span> <span class=\"n\">vytvor_balicek</span><span class=\"p\">()</span>\n\n    <span class=\"n\">hra</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&apos;U&apos;</span><span class=\"p\">:</span> <span class=\"n\">balicek</span><span class=\"p\">,</span>\n    <span class=\"p\">}</span>\n    <span class=\"c1\"># V-Z za&#x10D;&#xED;naj&#xED; jako pr&#xE1;zdn&#xE9; seznamy</span>\n    <span class=\"k\">for</span> <span class=\"n\">pismenko</span> <span class=\"ow\">in</span> <span class=\"s1\">&apos;VWXYZ&apos;</span><span class=\"p\">:</span>\n        <span class=\"n\">hra</span><span class=\"p\">[</span><span class=\"n\">pismenko</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n\n    <span class=\"c1\"># A-G jsou sloupe&#x10D;ky</span>\n    <span class=\"k\">for</span> <span class=\"n\">pismenko</span><span class=\"p\">,</span> <span class=\"n\">sloupec</span> <span class=\"ow\">in</span> <span class=\"nb\">zip</span><span class=\"p\">(</span><span class=\"s1\">&apos;ABCDEFG&apos;</span><span class=\"p\">,</span> <span class=\"n\">rozdej_sloupecky</span><span class=\"p\">(</span><span class=\"n\">balicek</span><span class=\"p\">)):</span>\n        <span class=\"n\">hra</span><span class=\"p\">[</span><span class=\"n\">pismenko</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">sloupec</span>\n\n    <span class=\"k\">return</span> <span class=\"n\">hra</span>\n</pre></div><p>A takhle se hra d&#xE1; vypsat:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">vypis_hru</span><span class=\"p\">(</span><span class=\"n\">hra</span><span class=\"p\">):</span>\n    <span class=\"sd\">&quot;&quot;&quot;Vyp&#xED;&#x161;e hru textov&#x11B;.</span>\n\n<span class=\"sd\">    Tato funkce je jen pro zobrazen&#xED;, pou&#x17E;&#xED;v&#xE1; proto p&#x159;&#xED;mo funkci print()</span>\n<span class=\"sd\">    a nic nevrac&#xED;.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n    <span class=\"k\">print</span><span class=\"p\">()</span>\n    <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">&apos;  U     V           W     X     Y     Z&apos;</span><span class=\"p\">)</span>\n    <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">&apos;{} {}       {} {} {} {}&apos;</span><span class=\"o\">.</span><span class=\"n\">format</span><span class=\"p\">(</span>\n        <span class=\"n\">popis_balicku</span><span class=\"p\">(</span><span class=\"n\">hra</span><span class=\"p\">[</span><span class=\"s1\">&apos;U&apos;</span><span class=\"p\">]),</span>\n        <span class=\"n\">popis_balicku</span><span class=\"p\">(</span><span class=\"n\">hra</span><span class=\"p\">[</span><span class=\"s1\">&apos;V&apos;</span><span class=\"p\">]),</span>\n        <span class=\"n\">popis_balicku</span><span class=\"p\">(</span><span class=\"n\">hra</span><span class=\"p\">[</span><span class=\"s1\">&apos;W&apos;</span><span class=\"p\">]),</span>\n        <span class=\"n\">popis_balicku</span><span class=\"p\">(</span><span class=\"n\">hra</span><span class=\"p\">[</span><span class=\"s1\">&apos;X&apos;</span><span class=\"p\">]),</span>\n        <span class=\"n\">popis_balicku</span><span class=\"p\">(</span><span class=\"n\">hra</span><span class=\"p\">[</span><span class=\"s1\">&apos;Y&apos;</span><span class=\"p\">]),</span>\n        <span class=\"n\">popis_balicku</span><span class=\"p\">(</span><span class=\"n\">hra</span><span class=\"p\">[</span><span class=\"s1\">&apos;Z&apos;</span><span class=\"p\">]),</span>\n    <span class=\"p\">))</span>\n    <span class=\"k\">print</span><span class=\"p\">()</span>\n    <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">&apos;  A     B     C     D     E     F     G&apos;</span><span class=\"p\">)</span>\n    <span class=\"n\">vypis_sloupecky</span><span class=\"p\">([</span><span class=\"n\">hra</span><span class=\"p\">[</span><span class=\"s1\">&apos;A&apos;</span><span class=\"p\">],</span> <span class=\"n\">hra</span><span class=\"p\">[</span><span class=\"s1\">&apos;B&apos;</span><span class=\"p\">],</span> <span class=\"n\">hra</span><span class=\"p\">[</span><span class=\"s1\">&apos;C&apos;</span><span class=\"p\">],</span> <span class=\"n\">hra</span><span class=\"p\">[</span><span class=\"s1\">&apos;D&apos;</span><span class=\"p\">],</span>\n                     <span class=\"n\">hra</span><span class=\"p\">[</span><span class=\"s1\">&apos;E&apos;</span><span class=\"p\">],</span> <span class=\"n\">hra</span><span class=\"p\">[</span><span class=\"s1\">&apos;F&apos;</span><span class=\"p\">],</span> <span class=\"n\">hra</span><span class=\"p\">[</span><span class=\"s1\">&apos;G&apos;</span><span class=\"p\">]])</span>\n    <span class=\"k\">print</span><span class=\"p\">()</span>\n</pre></div><p>Pro kontrolu m&#x16F;&#x17E;e&#x161; pustit testy:</p>\n<ul>\n<li>Level 70: Funkce <code>udelej_hru</code> existuje</li>\n<li>Level 71: Funkce <code>udelej_hru</code> funguje dle zad&#xE1;n&#xED;</li>\n<li>Level 80: Funkce <code>vypis_hru</code> existuje</li>\n<li>Level 81: Funkce <code>vypis_hru</code> funguje dle zad&#xE1;n&#xED;</li>\n</ul>\n<h2>Na&#x10D;ten&#xED; tahu</h2>\n<p>Hra se bude ovl&#xE1;dat zad&#xE1;n&#xED;m dvou jmen bal&#xED;&#x10D;ku: odkud a kam hr&#xE1;&#x10D; chce kartu\np&#x159;esunout.</p>\n<p>Tahle funkce nen&#xED; sou&#x10D;&#xE1;st logiky hry. Dej ji do <code>hra.py</code>.</p>\n<div class=\"highlight\"><pre><code>def nacti_tah():\n    while True:\n        tah = input(&apos;Tah? &apos;)\n        try:\n            jmeno_zdroje, jmeno_cile = tah.upper()\n        except ValueError:\n            print(&apos;Tah zad&#xE1;vej jako dv&#x11B; p&#xED;smenka, nap&#x159;. UV&apos;)\n        else:\n            return jmeno_zdroje, jmeno_cile</code></pre></div><h2>Z&#xE1;stupn&#xE9; funkce</h2>\n<p>K&#xA0;&#xFA;pln&#xE9; h&#x159;e n&#xE1;m chyb&#xED; je&#x161;t&#x11B; samotn&#xE1; logika hry: <code>hrac_vyhral</code> a <code>udelej_tah</code>.</p>\n<p>Aby n&#xE1;m hra aspo&#x148; trochu fungovala, vytvo&#x159; si z&#xE1;stupn&#xE9; funkce,\nkter&#xE9; nic nekontroluj&#xED; a nenechaj&#xED; t&#x11B; vyhr&#xE1;t:</p>\n<div class=\"highlight\"><pre><code>def hrac_vyhral(hra):\n    &quot;&quot;&quot;Vrac&#xED; True, pokud je hra vyhran&#xE1;.\n    &quot;&quot;&quot;\n    return False\n\ndef udelej_tah(hra, jmeno_odkud, jmeno_kam):\n    presun_kartu(hra[jmeno_odkud], hra[jmeno_kam], True)</code></pre></div><p>Ob&#x11B; bude je&#x161;t&#x11B; pot&#x159;eba upravit, ale te&#x10F; u&#x17E; si m&#x16F;&#x17E;e&#x161; hru v&#xED;cem&#xE9;n&#x11B; zahr&#xE1;t!\nZkus si to!</p>\n<h2>Jin&#xE9; rozhran&#xED;</h2>\n<p>Cel&#xFD; tento projekt p&#xED;&#x161;e&#x161; ve funkc&#xED;ch s&#xA0;dan&#xFD;m jm&#xE9;nem a s&#xA0;dan&#xFD;m po&#x10D;tem a v&#xFD;znamem\nargument&#x16F;.\nTo m&#xE1; dv&#x11B; v&#xFD;hody.</p>\n<p>Prvn&#xED; z nich je testov&#xE1;n&#xED;: p&#x159;ipraven&#xE9; testy importuj&#xED; tv&#xE9; funkce a zkou&#x161;&#xED; je,\ntak&#x17E;e si m&#x16F;&#x17E;e&#x161; b&#xFD;t jista, &#x17E;e funguj&#xED;.</p>\n<p>Druh&#xE1; je zaj&#xED;mav&#x11B;j&#x161;&#xED;: m&#xE1;&#x161;-li logiku hry, funkce <code>udelej_hru</code> <code>udelej_tah</code>\na <code>hrac_vyhral</code>, napsan&#xE9; podle specifikac&#xED;, m&#x16F;&#x17E;e je pou&#x17E;&#xED;t i jak&#xFD;koli jin&#xFD;\nprogram &#x2013; ne jen ten, kter&#xFD; jsi napsala ty.</p>\n<p>Jeden takov&#xFD; si m&#x16F;&#x17E;e&#x161; vyzkou&#x161;et:</p>\n<ul>\n<li><p>Nainstaluj si do virtu&#xE1;ln&#xED;ho prost&#x159;ed&#xED; knihovnu <code>pyglet</code>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">(venv)$ </span>python -m pip install pyglet\n</pre></div></li>\n<li><p>St&#xE1;hni si do aktu&#xE1;ln&#xED;ho adres&#xE1;&#x159;e soubory <a href=\"/2019/brno-jaro-2019-pondeli/projects/klondike/static/ui.py\">ui.py</a> a <a href=\"/2019/brno-jaro-2019-pondeli/projects/klondike/static/cards.png\">cards.png</a>.</p>\n</li>\n</ul>\n<ul>\n<li><p>Hru spus&#x165; pomoc&#xED;:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">(venv)$ </span>python ui.py\n</pre></div></li>\n</ul>\n<p><em>Obr&#xE1;zky karet jsou z&#xA0;<a href=\"https://kenney.nl/assets/boardgame-pack\">Board Game Pack</a>\nstudia <a href=\"https://kenney.nl\">kenney.nl</a>.</em></p>\n<h2>Logika hry</h2>\n<p>Zb&#xFD;v&#xE1; doplnit &#x201E;pravidla hry&#x201C; do dvou funkc&#xED;, <code>hrac_vyhral</code> a <code>udelej_tah</code>.\nTo u&#x17E; bude na tob&#x11B;.</p>\n<h3>hrac_vyhral</h3>\n<p>Hr&#xE1;&#x10D; vyhr&#xE1;l, pokud jsou v&#x161;echny karty na c&#xED;lov&#xFD;ch hrom&#xE1;dk&#xE1;ch <code>W</code>-<code>Z</code>.</p>\n<h3>udelej_tah</h3>\n<p>Kdy&#x17E; tah nen&#xED; podle pravidel, funkce <code>udelej_tah</code> vyhod&#xED; <code>ValueError</code>.</p>\n<p>Mo&#x17E;n&#xE9; tahy:</p>\n<ul>\n<li><code>U</code>&#x2192;<code>V</code>:<ul>\n<li>V bal&#xED;&#x10D;ku <code>U</code> mus&#xED; n&#x11B;co b&#xFD;t</li>\n<li>P&#x159;esouv&#xE1; se jedna karta; oto&#x10D;&#xED; se l&#xED;cem nahoru</li>\n</ul>\n</li>\n<li><code>V</code>&#x2192;<code>U</code>:<ul>\n<li>V bal&#xED;&#x10D;ku U nesm&#xED; b&#xFD;t nic</li>\n<li>P&#x159;esouvaj&#xED; se v&#x161;echny karty, se&#x159;azen&#xE9; v opa&#x10D;n&#xE9;m po&#x159;ad&#xED;;\noto&#x10D;&#xED; se rubem nahoru (tj. volej dokola\n<code>presun_kartu(hra[&apos;V&apos;], hra[&apos;U&apos;], False)</code> dokud ve V n&#x11B;co je)</li>\n</ul>\n</li>\n<li>Bal&#xED;&#x10D;ek <code>V</code> nebo sloupe&#x10D;ek <code>A</code>-<code>G</code> (zdroj) &#x2192; c&#xED;l <code>W</code>-<code>Z</code>: <ul>\n<li>P&#x159;esouv&#xE1; se jedna karta</li>\n<li>Je-li c&#xED;l pr&#xE1;zdn&#xFD;:<ul>\n<li>Mus&#xED; to b&#xFD;t eso</li>\n</ul>\n</li>\n<li>Jinak:<ul>\n<li>P&#x159;esouvan&#xE1; karta mus&#xED; m&#xED;t stejnou barvu jako vrchn&#xED; karta c&#xED;le</li>\n<li>P&#x159;esouvan&#xE1; karta mus&#xED; b&#xFD;t o 1 vy&#x161;&#x161;&#xED; ne&#x17E; vrchn&#xED; karta c&#xED;le</li>\n</ul>\n</li>\n<li>Je-li zdroj po p&#x159;esunu nepr&#xE1;zdn&#xFD;, jeho vrchn&#xED; karta se oto&#x10D;&#xED; l&#xED;cem nahoru</li>\n</ul>\n</li>\n<li>Bal&#xED;&#x10D;ek <code>V</code> &#x2192; &#x201E;c&#xED;lov&#xFD;&#x201C; sloupe&#x10D;ek <code>A</code>-<code>G</code><ul>\n<li>P&#x159;esouv&#xE1; se jedna karta</li>\n<li>P&#x159;esouvan&#xE1; karta mus&#xED; pasovat*&#x207E; na c&#xED;lov&#xFD; sloupe&#x10D;ek</li>\n</ul>\n</li>\n<li>&#x201E;Zdrojov&#xFD;&#x201C; sloupe&#x10D;ek <code>A</code>-<code>G</code> &#x2192; &#x201E;c&#xED;lov&#xFD;&#x201C; sloupe&#x10D;ek <code>A</code>-<code>G</code><ul>\n<li>P&#x159;esouv&#xE1; se n&#x11B;kolik karet<ul>\n<li>(zkontroluj v&#x161;echny mo&#x17E;nosti: 1 a&#x17E; po&#x10D;et karet ve zdrojov&#xE9;m sloupe&#x10D;ku;\nv&#x17E;dy je max. jedna spr&#xE1;vn&#xE1; mo&#x17E;nost) </li>\n</ul>\n</li>\n<li>V&#x161;echny p&#x159;esouvan&#xE9; karty mus&#xED; b&#xFD;t oto&#x10D;en&#xE9; l&#xED;cem nahoru</li>\n<li>Prvn&#xED; z p&#x159;esouvan&#xFD;ch karet mus&#xED; pasovat*) na c&#xED;lov&#xFD; sloupe&#x10D;ek</li>\n</ul>\n</li>\n<li>C&#xED;l <code>W</code>-<code>Z</code> &#x2192; sloupe&#x10D;ek <code>A</code>-<code>G</code> (nepovinn&#xE9; &#x2013; jen v n&#x11B;kter&#xFD;ch variant&#xE1;ch hry)<ul>\n<li>P&#x159;esouv&#xE1; se jedna karta</li>\n<li>P&#x159;esouvan&#xE1; karta mus&#xED; pasovat*) na c&#xED;lov&#xFD; sloupe&#x10D;ek</li>\n</ul>\n</li>\n</ul>\n<p>*&#x207E; Kdy p&#x159;esouvan&#xE1; karta pasuje na sloupe&#x10D;ek?</p>\n<ul>\n<li>Je-li sloupe&#x10D;ek pr&#xE1;zdn&#xFD;:<ul>\n<li>Karta mus&#xED; b&#xFD;t kr&#xE1;l</li>\n</ul>\n</li>\n<li>Jinak:<ul>\n<li>Barva p&#x159;esouvan&#xE9; karty mus&#xED; b&#xFD;t opa&#x10D;n&#xE1; ne&#x17E; barva vrchn&#xED; karty sloupe&#x10D;ku, tedy:<ul>\n<li>&#x10C;erven&#xE1; (&#x2665; nebo &#x2666;) jde d&#xE1;t jen na &#x10D;ernou (&#x2660; nebo &#x2663;)</li>\n<li>&#x10C;ern&#xE1; (&#x2660; nebo &#x2663;) jde d&#xE1;t jen na &#x10D;ervenou (&#x2665; nebo &#x2666;)</li>\n</ul>\n</li>\n<li>Hodnota p&#x159;esouvan&#xE9; karty mus&#xED; b&#xFD;t o 1 ni&#x17E;&#x161;&#xED; ne&#x17E; hodnota vrchn&#xED; karty sloupe&#x10D;ku</li>\n</ul>\n</li>\n</ul>\n\n\n        "
    }
  }
}