Chyby a moduly  18. října 2022

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

0.

Uprav program z Lekce 2, který postupně načte od uživatele dvě čísla a operaci ('+', '-', '*' nebo '/') a provede na číslech příslušnou operaci.

Program uprav tak, aby:

  • při špatném vstupu napověděl co očekává a zeptal se znovu a
  • při dělení nulou vypsal hlášku Nulou nelze dělit.

Použij na to ošetření příslušné chyby (tj. ne if delitel == 0:).

Příklad použití:

První číslo: třistatřiatřicet
Zadávej jen čísla
První číslo: 333
Druhé číslo: 0
Operace: /
Nulou nelze dělit.

Dnešním úkolem je naprogramovat hru 1D Piškvorky. Nakonec bude fungovat následovně:

1-D piškvorky se hrají na řádku s dvaceti políčky. Hráči střídavě přidávají kolečka (`o`) a křížky (`x`), třeba:
1. kolo: -------x------------
2. kolo: -------x--o---------
3. kolo: -------xx-o---------
4. kolo: -------xxoo---------
5. kolo: ------xxxoo---------
Hráč, která dá tři své symboly vedle sebe, vyhrál.

Hru budeš skládat postupně z malých částí. Napřed tedy musíš vytvořit malé části; ty pak poskládáš dohromady.

Úkoly dělej postupně.

Odevzdávej prosím celé soubory se všemi potřebnými importy a pomocnými funkcemi.

1.

Napiš funkci vyhodnot, která dostane řetězec s herním polem 1-D piškvorek a vrátí jednoznakový řetězec podle stavu hry:

  • "x" – Vyhrál hráč s křížky (pole obsahuje "xxx")
  • "o" – Vyhrál hráč s kolečky (pole obsahuje "ooo")
  • "!" – Remíza (pole neobsahuje "-", a nikdo nevyhrál)
  • "-" – Ani jedna ze situací výše (t.j. hra ještě neskončila)

Například:

  • vyhodnot('--------------------') vrátí '-'
  • vyhodnot('--o--xxx---o--o-----') vrátí 'x'
  • vyhodnot('xoxoxoxoxoxoxoxoxoxo') vrátí '!'
2.

Napiš funkci tah, která dostane řetězec s herním polem, číslo políčka (0-19), a symbol (x nebo o), a vrátí herní pole (t.j. řetězec) s daným symbolem umístěným na danou pozici.

Hlavička funkce by tedy měla vypadat nějak takhle:

def tah(pole, pozice, symbol):
    """Vrátí herní pole s daným symbolem umístěným na danou pozici

    `pole` je herní pole, na které se hraje.
    `pozice` je číslo políčka. Čísluje se od nuly.
    `symbol` může být 'x' nebo 'o', podle toho jestli je tah za křížky
    nebo za kolečka.
    """
    ...

Například:

  • tah('--------------------', 0, 'x') vrátí 'x-------------------'
  • tah('--------------------', 19, 'o') vrátí '-------------------o'
  • tah('x-o-x-o-x-o-x-o-x-o-', 5, 'x') vrátí 'x-o-xxo-x-o-x-o-x-o-'

Můžeš využít nějakou funkci, kterou už máš napsanou?

3.

Přepiš funkci tah, aby skončila s chybou ValueError v těchto případech:

  • Hra na pozici, která není v poli, např. tah('--------------------', -1, 'x')

  • Hra na obsazené políčko, např. tah('x-------------------', 0, 'o')

  • Hra jiným symbolem než 'x' nebo 'o', např. tah('--------------------', 0, 'řeřicha')

Odevzdané řešení předchozího úkolu můžeš nechat tak, jak je.

4.

Napiš funkci tah_hrace(pole, symbol), která dostane řetězec s herním polem a symbol (x nebo o) a:

  • zeptá se hráče, na kterou pozici chce hrát,
  • pomocí funkce tah zjistí, jak vypadá herní pole se zaznamenaným tahem hráče
  • vrátí toto herní pole se zaznamenaným tahem hráče.

Pokud uživatel zadá špatný vstup (nečíslo, záporné číslo, obsazené políčko apod.), funkce mu vynadá a zeptá se znova. (Není potřeba použít pro každý případ jinou hlášku.)

Hlavička funkce by tedy měla vypadat nějak takhle:

def tah_hrace(pole, symbol):
    """Zeptá se hráče na tah a vrátí nové herní pole

    `pole` je herní pole, na které se hraje.
    `symbol` může být 'x' nebo 'o', podle toho jestli hráč hraje za křížky
    nebo za kolečka.
    """
    ...

Například zavolání print("Nový stav hry je:", tah_hrace('o-------------------', 'x')) by mohlo dopadnout takto:

Kam chceš hrát? nevím
Zadávej čísla!
Kam chceš hrát? 0
Tam nejde hrát!
Kam chceš hrát? -1
Tam nejde hrát!
Kam chceš hrát? 151
Tam nejde hrát!
Kam chceš hrát? 2
Nový stav hry je: o-x-----------------

Pozor: pravděpodobně budeš potřebovat ošetřit různé chyby na různých místech.

5.

Napiš funkci tah_pocitace(pole, symbol), která dostane řetězec s herním polem a symbol, vybere pozici, na kterou hrát, a vrátí herní pole se zaznamenaným tahem počítače.

Použij jednoduchou náhodnou „strategii”:

  1. Vyber číslo od 0 do 19.
  2. Pokud je dané políčko volné, hrej na něj.
  3. Pokud ne, opakuj od bodu 1.

Hlavička funkce by tedy měla vypadat nějak takhle:

def tah_pocitace(pole, symbol):
    """Vrátí herní pole se zaznamenaným tahem počítače

    `pole` je herní pole, na které se hraje.
    `symbol` může být 'x' nebo 'o', podle toho jestli hráč hraje za křížky
    nebo za kolečka.
    """
    ...

Zavolání print(tah_pocitace('o-------------------', 'x')) by mohlo vypsat třeba o---------x---------.

6.

Napiš funkci piskvorky1d, která:

  • Vytvoří řetězec s herním polem, '--------------------'
  • Stále dokola:
    • zavolá volá funkci tah_hrace, a výsledek uloží jako nové pole
    • vypíše herní pole
    • zavolá volá funkci tah_pocitace, a výsledek uloží jako nové pole
    • vypíše herní pole

Zatím neřeš konec hry.

7.

Teď pošéfuj konec hry. Když někdo vyhraje nebo dojde k remíze, cyklus se ukončí a vypíše se výsledek – třeba s gratulací nebo povzbuzující zprávou.

Stav hry kontroluj po každém tahu.

Nezapomeň, že máš k dispozici funkci vyhodnot!

8.

Program rozděl do modulů a uprav importy tak, aby program stále fungoval. Moduly by neměly mít vedlejší efekty.

  • Funkce vyhodnot, tah_hrace a piskvorky1d patří do modulu piskvorky (tj. souboru piskvorky.py).
  • Funkce tah_pocitace patří do modulu ai (tj. souboru ai.py).
  • Funkci tah zařaď podle materiálů o cyklických importech.

Protože samotná hra – vypisování a ptaní na otázky – je vedlejší efekt, tak teď nepůjde spustit. Aby to šlo, vytvoř ještě „spouštěcí“ modul hra (tj. soubor hra.py) s následujícím obsahem:

from piskvorky import piskvorky1d

piskvorky1d()

Odevzdávání a kontrola několika souborů je zatím složité, proto si tento úkol zkontroluj sama:

  • Všechny funkce jsou kde mají být (podle zadání).
  • Příkaz python hra.py v příkazové řádce spustí funkční hru.
  • Příkaz import piskvorky v Pythonu nespustí hru (a nemá ani další vedlejší efekty).