Sekvence a soubory  19. dubna 2021

Materiály

Nejste účastníkem kurzu
Pro zápis do kurzu se nejprve přihlašte a následně použijte tlačítko v přehledu kurzu.

Domácí projekty

V těchto úkolech si zopakujete práci se soubory.

0.

Napište program, který vypíše básničku ze souboru basnicka.txt VELKÝMI PÍSMENY.

Zpracovávejte ji po jednotlivých řádcích. (Nebudete tak načítat celou dlouhou báseň jako řetězec do paměti počítače; váš program bude vždycky potřebovat místo jen na jeden řádek.)

Následující úkol kombinuje soubory a sekvence.

1.

Stáhněte si soubor index.dic se všemi českými slovy.

(Seznam slov vytvořil Petr Kolář a další a je poskytován pod licencí GNU GPL 2.)

Soubor není úplně „čistý“. Vytvořte seznam, kde budou opravdu jen slova:

  • Vytvořte prázdný seznam.
  • Projděte index.dic po řádcích a postupně přidávejte slova do seznamu.

Na začátku souboru (řádek 0) je údaj s počtem řádků, ten neberte jako slovo. (Jak při průchodu souborem – sekvencí – zjistíte číslo prvku?)

Některá slova obsahují další informace za znakem /. Tyto informace (i s lomítkem) ze slov odstraňte. Bude se hodit umět slovo rozdělit podle /, viz tahák na seznamy.

Můžete se rozhodnout odstranit i slova začínající velkým písmenem. (Většinou jde o vlastní jména a zkratky).

22. 4. 2021 upřesněno zadání: slova s lomítkem neodstraňujte

2.

Slova ze seznamu vytvořeného výše uložte do souboru slova.txt, kde bude na každém řádku jedno slovo.

3.

Ve hře Šibenice vybírejte slovo ze souboru slova.txt.

Můžete odevzdat jen kód, který načte soubor a náhodné slovo uloží do proměnné slovo. Zbytek Šibenice se nemění.

Další úkoly procvičují práci se seznamy a n-ticemi.

Naprogramujete si karetní „hru“ Válka, ve které jde pouze o štěstí: hráči v ní nedělají žádná rozhodnutí. (Jestli tuhle „hru“ neznáte, přečtěte si pravidla na internetu.)

4.

Karta pro nás v tomto projektu bude dvojice (hodnota, barva). Aby se karty dobře porovnávaly, hodnota bude vždy číslo: 2-10 budou karty s čísly, 11 kluk, 12 dáma, 13 král, 1 eso. Barva pak bude jeden z řetězců 'Sr', 'Pi', 'Ka', 'Kr'.

Následující funkce umí vytvořit balíček a popsat kartu trochu hezčím způsobem. Zkopírujte si je a prostudujte.

def vytvor_balicek():
    """Vrátí nový zamíchaný balíček karet."""
    karty = []
    for barva in 'Sr', 'Pi', 'Ka', 'Kr':
        for hodnota in range(1, 14):
            karta = hodnota, barva
            karty.append(karta)
    random.shuffle(karty)
    return karty


def popis_kartu(karta):
    """Popíše danou kartu; vrací řetězec jako "7♣", "A♠" nebo "Q♥"."""
    hodnota, barva = karta
    if hodnota == 11:
        popis_hodnoty = 'J'
    elif hodnota == 12:
        popis_hodnoty = 'Q'
    elif hodnota == 13:
        popis_hodnoty = 'K'
    elif hodnota == 1:
        popis_hodnoty = 'A'
    elif hodnota == 10:
        # Aby byly všechny hodnoty jednopísmenné,
        # a líp se to pak vypisovalo,
        # desítku označíme římským číslem.
        popis_hodnoty = 'X'
    else:
        popis_hodnoty = str(hodnota)

    if barva == 'Sr':
        popis_barvy = '♥'
    elif barva == 'Pi':
        popis_barvy = '♠'
    elif barva == 'Ka':
        popis_barvy = '♦'
    else:
        popis_barvy = '♣'

    return popis_hodnoty + popis_barvy

Napište proceduru, která vytvoří balíček a „hezky“ vypíše všechny karty v něm, každou na jeden řádek. Například:

9♠
K♣
9♣
J♥
Q♠
K♠
... atd.

(Tuhle proceduru nebudete dál potřebovat, je tu jenom pro pochopení těchto funkcí.)

5.

Napište funkci porovnej_karty podle této hlavičky:

def porovnej_karty(karta_a, karta_b):
    """Porovná hodnoty dvou karet.

    Vrací:
    * 'A', je-li lepší karta_a,
    * 'B', je-li lepší karta_b,
    * None, mají-li stejnou hodnotu.
    """
6.

Stav hry bude trojice seznamů: balíček hráče A, balíček hráče B, a karty co jsou aktuálně na stole.

Následující funkce takový stav hry vytvoří. Zkopírujte si ji a prostudujte.

def rozdej_balicky():
    """Rozdá trojici balíčků: dva pro hráče a jeden pro "stůl"

    Připraví zamíchaný balíček všech karet.
    Balíček pro hráče A bude jeho první polovina; balíček pro hráče B druhá
    """
    balicek = vytvor_balicek()

    # "polovina" musí být celé číslo, protože pak jí číslujeme seznam.
    # Proto celočíselné dělení. Zbytek po dělení ignorujeme.
    polovina = len(balicek) // 2

    balicek_a = balicek[:polovina]
    balicek_b = balicek[polovina:]

    return balicek_a, balicek_b, []

Napište proceduru, která rozdá balíčky a „hezky“ je vypíše, např.

Hráč A  Hráč B
9♠      2♦
K♣      Q♥
9♣      6♦
J♥      3♥
Q♠      Q♣
K♠      A♣
... atd.

Co použijete na procházení dvou seznamů naráz?

(Tuhle proceduru nebudete dál potřebovat, je tu jenom pro vyzkoušení práce s kartami.)

7.

Vytvořte funkci vyloz_karty, která dostane stav hry a simuluje jedno vyložení karet.

def vyloz_karty(balicky):
    """Vyloží karty obou hráčů na stůl.

    "balicky" je trojice: balíček hráče A, balíček hráče B, karty na stole.

    Každý z hráčů vyloží poslední kartu svého balíčku na stůl.
    Nemá-li hráč co vyložit, nastane výjimka `SystemExit`.
    (To zjednodušuje zbytek hry.)

    Funkce vypisuje co dělá pomocí "print".
    (To taky zjednodušuje zbytek hry.)
    """
    balicek_a, balicek_b, na_stole = balicky
    ...
  • Zkus:
    • Lízni poslední kartu balíčku A. To bude karta A.
  • Pokud to nešlo (balíček A byl prázdný):
    • Vyhoď výjimku SystemExit('Hráč B vyhrál')
  • Zkus:
    • Lízni poslední kartu balíčku B. To bude karta B.
  • Pokud to nešlo (balíček B byl prázdný):
    • Vyhoď výjimku SystemExit('Hráč A vyhrál')
  • Vypiš, že Hráč A hraje kartu A
  • Vypiš, že Hráč B hraje kartu B
  • Do karet na stole přidej kartu A
  • Do karet na stole přidej kartu B

(Výjimka SystemExit způsobí skončení proramu bez chybové hlášky. Ta a výpisy pomocí print nejsou ve funkci která něco „počítá“ úplně „košer“, ale zjednoduší vám práci.)

8.

Vytvořte funkci valka, která:

  • Rozdá balíčky
  • Balíčky označí jako balíček A, balíček B, karty na stole.
  • Pořád dokola:
    • Vyloží karty
    • Dokud mají předposlední a poslední karta na stole stejnou hodnotu:
      • Vypíše „Válka!“
      • Vyloží karty
      • Vyloží karty
      • Vyloží karty
    • Jako vítěze tohoto kola označí hráče s vyšší kartou ("A" nebo "B", podle toho jestli je vyšší poslední nebo předposlední karta)
    • Vypíše „Hráč vitez bere N karet!'“, kde N je počet karet na stole
    • Je-li vítěz hráč A:
      • Všechny karty na stole přidá, po jedné, na začátek balíčku A (pozor: metoda append nejde použít, ta přidává na konec!)
    • Je-li vítěz hráč B:
      • Karty na stole přidá na začátek balíčku B, podobně jako výše
    • Seznam karet na stole vyprázdní.

Poznámka (přidána 5. 5. 2021): Podle toho jak jsou karty zamíchané tahle hra nemusí skončit. Nekonečný cyklus tedy není na závadu.