IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

6. diel - Python - Aréna s bojovníkmi

V minulej lekcii, Bojovník do arény v Pythone , sme si vytvorili triedu bojovníka. Hracie kocku máme hotovú z prvých lekcií objektovo orientovaného programovania. Dnes teda dáme všetko dokopy a vytvoríme funkčné arénu. Tutoriál bude skôr oddychový a pomôže nám zopakovať si prácu s objektmi.

Potrebujeme napísať nejaký kód pre obsluhu bojovníkov a výpis správ užívateľmi. Vytvoríme si objekt Arena, kde sa bude zápas odohrávať. Hlavná časť programu potom len založia objekty ao zvyšok sa bude starať objekt Arena.

Trieda bude viac-menej jednoduchá, ako atribúty bude obsahovať 3 potrebné inštancie: 2 bojovníkmi a hraciu kocku. V konstruktoru sa tieto atribúty naplnia z parametrov. Kód triedy bude teda nasledujúce:

class Arena:

    def __init__(self, bojovnik_1, bojovnik_2, kostka):
        self.__bojovnik_1 = bojovnik_1
        self.__bojovnik_2 = bojovnik_2
        self.__kostka = kostka

Zamyslime sa nad metódami. Z verejných metód bude určite potrebné len tá na simuláciu zápasu. Výstup programu na konzolu urobíme trochu na úrovni a tiež umožníme triede Arena, aby priamo ku konzole pristupovala. Rozhodli sme sa, že výpis bude v kompetencii triedy, keďže sa nám to tu oplatí. Naopak keby výpis vykonávali aj bojovníci, bolo by to na škodu. Potrebujeme teda metódu, ktorá vykreslí obrazovku s aktuálnymi údajmi o bicykli a životy bojovníkov. Správy o útoku a obrane budeme chcieť vypisovať s dramatickou pauzou, aby bol výsledný efekt lepšie, urobíme si pre takýto typ správ ešte pomocnú metódu. Začnime s vykreslením informačnej obrazovky:

def __vykresli(self):
    self.__vycisti_obrazovku()
    print("-------------- Aréna -------------- \n")
    print("Zdraví bojovníků: \n")
    print("{0} {1}".format(self.__bojovnik_1,
                           self.__bojovnik_1.graficky_zivot()))
    print("{0} {1}".format(self.__bojovnik_2,
                           self.__bojovnik_2.graficky_zivot()))

Na začiatku voláme ďalšiu metódu - vycisti_obrazovku (). Metódy sa vnútri objektu volajú touto syntaxou:

self.název_metody

Zvyšok je jasný. Obe metódy sú súkromné, budeme ich používať len vnútri triedy.

Tu je kód privátne metódy vycisti_obrazovku ():

def __vycisti_obrazovku(self):
    import sys as _sys
    import subprocess as _subprocess
    if _sys.platform.startswith("win"):
        _subprocess.call(["cmd.exe", "/C", "cls"])
    else:
        _subprocess.call(["clear"])

Importujeme moduly sys a subprocess potrebné k vymazaniu obrazovky konzole. Podľa OS zavoláme príslušný príkaz na vymazanie obrazovky. Ďalšie privátne metódou bude výpis správy s dramatickou pauzou:

def __vypis_zpravu(self, zprava):
    import time as _time
    print(zprava)
    _time.sleep(0.75)

Kód je zrejmý až funkcii sleep z modulu time, ktorá uspí vlákno programu na daný počet sekúnd. S vláknami budeme pracovať až na konci seriálu.

Obe metódy vlastne len vypisujú na konzolu, pripadá mi zbytočné je skúšať, presunieme sa teda už k samotnému zápasu. Metóda zapas () nebude mať žiadne parametre a nebude ani nič vracať. Vnútri bude cyklus, ktorý bude na striedačku volať útoky bojovníkov navzájom a vypisovať informačnú obrazovku a správy. Metóda by mohla vyzerať takto:

def zapas(self):
    print("Vítejte v aréně!")
    print("Dnes se utkají {0} s {1}!".format(self.__bojovnik_1, self.__bojovnik_2))
    print("Zápas může začít...", end=" ")
    input()
    # cyklus s bojem
    while (self.__bojovnik_1.nazivu and self.__bojovnik_2.nazivu):
        self.__bojovnik_1.utoc(self.__bojovnik_2)
        self.__vykresli()
        self.__vypis_zpravu(self.__bojovnik_1.vrat_posledni_zpravu())
        self.__vypis_zpravu(self.__bojovnik_2.vrat_posledni_zpravu())
        self.__bojovnik_2.utoc(self.__bojovnik_1)
        self.__vykresli()
        self.__vypis_zpravu(self.__bojovnik_2.vrat_posledni_zpravu())
        self.__vypis_zpravu(self.__bojovnik_1.vrat_posledni_zpravu())
        print("")

Kód vypíše jednoduché informácie a po stlačení klávesy prejde do cyklu s bojom. Jedná sa o while cyklus, ktorý sa opakuje, kým sú obaja bojovníci nažive. Prvý bojovník zaútočí na druhého, jeho útok vnútorne zavolá na druhom bojovníkovi obranu. Po útoku vykreslíme obrazovku s informáciami a ďalej správy o útoku a obrane pomocou našej metódy vypis_zpravu (), ktorá po výpise urobí dramatickú pauzu. To isté vykonáme aj pre druhého bojovníka.

Presuňme sa na koniec programu, vytvorme patričné inštancie a zavolajte na aréne metódu zapas ():

# vytvoření objektů
kostka = Kostka(10)
zalgoren = Bojovnik("Zalgoren", 100, 20, 10, kostka)
shadow = Bojovnik("Shadow", 60, 18, 15, kostka)
arena = Arena(zalgoren, shadow, kostka)
# zápas
arena.zapas()
input()

Charakteristiky hrdinov si môžete upraviť podľa ľubovôle. Program spustíme:

Objektová aréna v Pythone – simulácia zápasu v stolnej hre - Objektovo orientované programovanie v Pythone

Výsledok je docela pôsobivý. Objekty spolu komunikujú, grafický život ubúda ako má, zážitok umocňuje dramatická pauza. Aréna má však 2 nedostatky.

  • V cykle s bojom útočí prvý bojovník na druhého. Potom však vždy útočia aj druhý bojovník, nehľadiac na to, či ho prvý nezabil. Môže teda útočiť už ako mŕtvy. Pozrite sa na screenshot vyššie, Shadow útočil ako posledný aj keď bol mŕtvy. Až potom sa vystúpilo z while cyklu. U prvého bojovníka tento problém nie je, u druhého musíme pred útokom kontrolovať, či je nažive.
  • Druhým nedostatkom je, že bojovníci vždy bojujú v rovnakom poradí, čiže tu "Zalgoren" má vždy výhodu. Poďme vniesť ďalší prvok náhody a pomocou kocky rozhodnime, ktorý z bojovníkov bude začínať. Keďže sú bojovníci vždy dvaja, stačí hodiť kockou a pozrieť sa, či padlo číslo menšie alebo rovné polovici počtu stien kocky. Teda napr. Ak padne na desetistěnné kocke číslo do 5tich, začína druhý bojovník, inak začína prvý. Zostáva zamyslieť sa nad tým, ako do kódu zaniesť prehadzovania bojovníkov. Iste by bolo veľmi neprehľadné opodmínkovat príkazy vo while cyklu. Keďže už vieme, že v Pythone fungujú referencie, nie je to pre nás problém. Navyše Python podporuje súbežné priraďovanie, takže si ani nemusíme tvoriť zástupné premenné. Jednoducho prehodíme inštancie bojovníkov.

Zmenená verzie vrátane podmienky, aby nemohol útočiť mŕtvy bojovník, by mohla vyzerať nejako takto:

def zapas(self):
    import random as _random
    print("Vítejte v aréně!")
    print("Dnes se utkají {0} s {1}!".format(self.__bojovnik_1,
                                             self.__bojovnik_2))
    print("Zápas může začít...", end=" ")
    input()
    # prohození bojovníků
    if _random.randint(0, 1):
        (self.__bojovnik_1, self.__bojovnik_2) = (self.__bojovnik_2,
          self.__bojovnik_1)
    # cyklus s bojem
    while (self.__bojovnik_1.nazivu and self.__bojovnik_2.nazivu):
        self.__bojovnik_1.utoc(self.__bojovnik_2)
        self.__vykresli()
        self.__vypis_zpravu(self.__bojovnik_1.vrat_posledni_zpravu())
        self.__vypis_zpravu(self.__bojovnik_2.vrat_posledni_zpravu())
        if self.__bojovnik_2.nazivu:
            self.__bojovnik_2.utoc(self.__bojovnik_1)
            self.__vykresli()
            self.__vypis_zpravu(self.__bojovnik_2.vrat_posledni_zpravu())
            self.__vypis_zpravu(self.__bojovnik_1.vrat_posledni_zpravu())
        print("")

Bojovníkmi prehodíme pomocou výrazu sa zátvorkami vyššie. Ak by tam neboli, tak by Python vyhodil chybu. Kód sme na tomto mieste odřádkovali, aby sa nám program toľko neroztahoval do šírky. Odporúčaná dĺžka riadku je totiž 80 znakov.

Program vyskúšajme:

Objektová aréna v Pythone – simulácia zápasu v stolnej hre - Objektovo orientované programovanie v Pythone

Vidíme, že je všetko už v poriadku. Gratulujem vám, ak ste sa dostali až sem a tutoriály naozaj čítali a pochopili, máte základy objektového programovania v Pythone a dokážete tvoriť rozumné aplikácie :)

V budúcej lekcii, Dedičnosť a polymorfizmus v Pythone , sa pozrieme na objektovo orientované programovanie podrobnejšie. V úvode sme si hovorili, že OOP stojí na pilieroch: zapuzdrenie, dedičnosť a polymorfizmus. Prvý vieme už veľmi dobre a rozumieme reči podčiarkovníkov. Takže tie ďalšie dve zručnosti nás čakajú nabudúce.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 968x (4.38 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Python

 

Predchádzajúci článok
Bojovník do arény v Pythone
Všetky články v sekcii
Objektovo orientované programovanie v Pythone
Preskočiť článok
(neodporúčame)
Dedičnosť a polymorfizmus v Pythone
Článok pre vás napísal gcx11
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
(^_^)
Aktivity