Zadanie 1

Zadanie 1

Nezabudnite zadanie nahrať do AIS do príslušného miesta odovzdania (odovzdajte len zdrojový .c súbor).

Dôležité informácie

Krátky popis

Cieľom zadania je naprogramovať v jazyku C jednoduchú interaktívnu konzolovú hru simulujúcu súboj 2 tankov. Jeden z tankov je ovládaný hráčom z klávesnice a súper je riadený umelou inteligenciou (PC protihráč). Hráč zvolí uhol výstrelu a počiatočnú rýchlosť (silu), dôjde k výstrelu a vypočíta sa dostrel (t.j. X-ová súradnica, kde projektil dopadne). Ak projektil zasiahne PC protihráča, hra končí. V opačnom prípade je na ťahu PC protihráč, ktorý náhodne generuje uhol a silu výstrelu (snažte sa predovšetkým o vytvorenie umelej inteligencie). A týmto spôsobom sa strieda hráč a PC protihráč až pokiaľ nedôjde k zničeniu niektorého z tankov.

Na začiatku hry sa tanky náhodne umiestnia na hernej plošine (vygeneruje sa ich X-ová súradnica). Herná plošina má dĺžku určenú tak, aby sa jej vykreslenie zmestilo do konzolového okna (ideálne určená globálnou konštantou pomocou #define, napr. #define ARENA_LENGTH 80). Tanky je potrebné vhodne vizualizovať, napr. pomocou vhodne zvolených symbolov 1 - hráč a 2 - PC protihráč. Rovnako je vyžadovaná vizualizácia dopadu projektilu, t.j. nakreslenie symbolu v mieste dopadu/výbuchu.

V zadaní sa bude kontrolovať jednak požadovaná funkcionalita, ale aj kvalita návrhu, t.j. prehľadnosť hlavnej funkcie main, rozčlenenie zdrojového kódu do funkcií (napr. oddelenie hernej logiky od kreslenia konzolovej grafiky), jednoduchosť (keep it simple stupid), efektívnosť, prehľadnosť kódu a komentovanie kľúčových častí kódu.

Ukážka (video)

Hlavné aspekty hry

Inicializácia

Hra začína rozmiestnením tankov na hernej plošine. Rozmiestnenie je náhodné. Na tento účel je potrebné si napísať vlastnú funkciu na generovanie náhodného čísla vo zvolenom intervale (napr. šírka intervalu bude zodpovedať šírke konzolového okna). Funkcia na generovanie náhodného čísla sa dá použiť aj v neskorších fázach zadania, napr. pri generovaní parametrov strely PC protihráčom. Treba si dávať pozor, aby nevznikla situácia, že vygenerovaná X-ová súradnica tanku bude presahovať rozmer hernej plošiny a taktiež treba zabrániť tomu, aby neboli obidva tanky vygenerované na rovnakom mieste (t.j. rovnaká X-ová súradnica). Pri každom spustení programu sa musia tanky vygenerovať na inej náhodnej pozícii (treba použiť funkciu srand, zavolať ju na začiatku programu vo funkcii main).

Obr. Náhodné umiestnenie tankov na začiatku hry (1je hráč, 2 je PC protihráč). Tank ovládaný hráčom sa môže vyskytnúť vľavo/vpravo od PC protihráča.

Interakcia s hráčom

Tanky sa budú v streľbe striedať. Ako prvý začne hráč. Manuálne z klávesnice zadá parametre streľby: uhol a počiatočnú rýchlosť (silu) výstrelu. Zvoľte si jednotky, ktoré sa budú používať pri zadávaní vstupu (oznámte to hráčovi výpisom na obrazovku). Netreba ošetrovať neplatné vstupy. Na zadávanie vstupov z klávesnice použite funkciu scanf.

Obr. Zadávanie parametrov strely z klávesnice (platí pre hráčov tank).

Výpočet dostrelu

Na výpočet dostrelu \(d\) použite matematický vzťah:

\[ d = \frac{v_{0}^{2}}{g}sin(2\alpha )\]

  • \(v_{0}\) je počiatočná rýchlosť výstrelu (alebo aj sila) udávaná v \(m/s\) (pozor treba previesť rýchlosť ak ste ju zadávali v \(km/h\))
  • \(g\) je tiažové zrýchlenie (počítame s hodnotou \(9,81\space m/s^{2}\))
  • \(\alpha\) je uhol výstrelu vyjadrený v stupňoch (pozor matematická funkcia sin z hlavičkového súboru math.h očakáva uhol vyjadrený v radiánoch)

Obr. Dráha projektilu (prevzaté z hyperphysics.phy-astr.gsu.edu)

Výpočet dostrelu musí byť podľa vyššie uvedeného vzťahu implementovaný v samostatnej funkcii. Nezabudnite si napísať aj vlastné funkcie na prevod jednotiek (km/h na m/s, stupne na radiány).

Umelá inteligencia PC protihráča

PC protihráč by mal vykazovať istú úroveň inteligencie, t.j. jeho tank by mal mieriť kanónom na hráčov tank (uhol výstrelu) a pri výstrele použiť adekvátnu silu (aby nebola napríklad prestrelená šírka hracej plochy). Inými slovami, PC protihráč sa musí snažiť trafiť váš tank. Body za túto časť zadania budú odzrkadľovať kvalitu vášho návrhu.

Kreslenie hry

Dôležitou časťou tohto zadania je kreslenie hernej grafiky do konzolového okna. Dbajte na prehľadnosť a vizuálnu prívetivosť vašej grafiky. Kreslenie konzolovej grafiky musí byť oddelené od zvyšku hernej logiky, t.j. musíte na to vytvoriť samostatnú funkciu (napr. printGame). Túto kresliacu funkciu budete v priebehu hry opakovane volať na prekresľovanie aktuálneho stavu hry.

Minimálne požiadavky na kreslenie hernej grafiky:

  • zobrazenie terénu (napríklad rovná čiara, ak používate rovný terén, stačí použiť znak -).
  • zobrazenie pozícií tankov (zvoľte vhodné symboly, napr. 1 pre hráčov tank a 2 pre PC protihráča)
  • zobrazenie dopadu projektilu (po výstrele sa v konzole zobrazí bod dopadu/výbuchu v správnej vzdialenosti prepočítanej na rozmery vašej hernej grafiky)

Obr. Vizualizácia dopadu projektilu v konzole (s pomocnou infografikou). Červené šípky znázorňujú X-ové pozície počiatku súradnicovej sústavy a bodu dopadu. Zelenou farbou je vyznačený dostrel.

Vymazanie obsahu konzoly

Multiplatformová funkcia clearScreen na vymazanie obsahu konzoly. Môžete ju použiť na aktualizáciu hernej grafiky.

void clearScreen() {
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
    system("cls");
#elif defined(__APPLE__)
    system("clear");
#elif defined(__linux__)
    system("clear");
#else
#error "Unknown OS"
#endif 
}

Ukončenie hry

Hra končí v momente, keď vystrelený projektil zasiahne súperov tank. Na to, aby ste tank zničili nemusíte trafiť presnú súradnicu tanku - môžete si určiť určitý interval/zónu, do ktorej keď projektil dopadne, tak tank bude zničený, napr. deštrukčná zóna v okruhu +/- 1 km od miesta dopadu projektilu.

Kostra riešenia a potrebné funkcie

Vzorová kostra riešenia (jedna z možných inšpirácií). Tento kód nie je kompilovateľný, slúži len ako hrubý náčrt riešenia.

#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#define ARENA_LENGTH 80 // sirka hry
#define G 9.81 // tiazove zrychlenie
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

// Funkcia na generovanie nahodneho cisla v intervale <a,b>
// pozn. v pripade potreby mozete upravit na typ 'double'
int randomNumber(int a, int b) {
    // todo
}

// Funkcia na kreslenie hernej grafiky
// vstupy:
//      * t1 - pozicia tanku 1 (hrac)
//      * t2 - pozicia tanku 2 (PC)
//      * hit - pozicia dopadu projektilu
//      * arena_length - sirka hracej plochy
// pozn. volba parametrov funkcie je na vas
void printGame(int t1, int t2, int hit, int arena_length) {
    // todo
}

// Funkcia na prevod km/h na m/s
double kmh2ms(double kmh) {
    // todo
}

// Funkcia na prevod stupnov na radiany
double deg2rad(double deg) {
    // todo
}

// Funkcia na vypocet dostrelu (v metroch)
// vstupy:
//      * alpha - uhol vystrelu (radiany)
//      * v0 - pociatocna rychlost vystrelu (m/s)
double shotDistance(double alpha, double v0) {
    // todo
}

// Funkcia na realizaciu tahu hraca
// pozn. volba parametrov funkcie/urcenie navratoveho typu je na vas
double humanTurn() {
    // todo
    // vo funkcii hrac zada parametre strely (uhol a rychlost)
    // funkcia vrati X-ovu suradnicu dostrelu (vzhladom na pouzity suradnicovy system)
}

// Funkcia na realizaciu tahu PC protihraca
// pozn. volba parametrov funkcie/urcenie navratoveho typu je na vas
double pcTurn() {
    // todo
    // vo funkcii sa vygeneruju parametre strely (uhol a rychlost)
    // funkcia vrati X-ovu suradnicu dostrelu (vzhladom na pouzity suradnicovy system)
}

// Hlavna herna funkcia
// vstupy:
//      * t1 - pozicia tanku 1 (hrac)
//      * t2 - pozicia tanku 2 (PC)
// vystup:
//      funkcia navratovou hodnotou signalizuje, ktory hrac vyhral
int game(int t1, int t2) {
    printGame(...); // prve vykreslenie hry bez dopadu projektilu
    while (...) { // hra prebieha pokial su obidva tanky neznicene
        humanTurn(...); // tah hraca
        printGame(...); // kresba aktualneho stavu hry
        pcTurn(...); // tah PC
        printGame(...);  // kresba aktualneho stavu hry
    }
    return ...; // vrati sa ID hraca, ktory vyhral
}

int main()
{
    int t1, t2; // pozicie tankov
    srand((unsigned int)time(NULL));
    t1 = randomNumber(...); // nahodna pozicia tanku 1
    t2 = randomNumber(...); // nahodna pozicia tanku 2
    int winner = game(...); // start hry
    // vypisanie kto vyhral
    return 0;
}

Vašou úlohou je rozdeliť si kód celého zadania do vhodných logických celkov, t.j. vlastných funkcií. Kvalita architektúry vašej implementácie (návrh a používanie vlastných funkcií) bude zohľadnená počas bodovania.

Bodovanie

Body sú rozdelené nasledovne:

  • [1b] Jednoduchosť/prehľadnosť funkcie main. Funkcia main by mala byť krátka a úsporná (minimum) kódu. V main funkcii postačí vytvoriť premenné reprezentujúce X-súradnice tankov, inicializovať ich na náhodné platné hodnoty (zavolaním funkcie na generovanie náhodného čísla vo zvolenom intervale) a zavolať hlavnú hernú funkciu (čítaj ďalej).
  • [2b] Hlavná herná funkcia (s názvom napr. game, runGame, atď.). Táto funkcia bude zavolaná z funkcie main. Hlavná herná funkcia bude riadiť priebeh celej hry a volať ďalšie pomocné funkcie. Bude obsahovať herný cyklus, v ktorom sa budú striedať na ťahu hráč a PC a taktiež vyhodnotenie konca hry/víťaza.
  • [2b] Funkcia na výpočet dostrelu projektilu (napr. s názvom shotDistance). Kľúčová funkcia pre celé zadanie. Vstupom do funkcie bude uhol a počiatočná rýchlosť strely. Funkcia podľa známeho vzťahu (pozri vyššie) vypočíta dostrel projektilu a vráti ho.
  • [1b] Funkcia na vygenerovanie náhodného čísla vo zvolenom intervale. Túto funkciu využijete pri generovaní počiatočných súradníc tankov na začiatku hry a taktiež pri generovaní parametrov strely PC protihráča.
  • [2b] Funkcia na kreslenie hernej grafiky do konzoly (napr. s názvom printGame). Táto funkcia bude zodpovedná za formátované a vizuálne prívetivé vykreslenie aktuálneho herného stavu (t.j. pozície tankov, terén a miesto dopadu projektilu).

Extra body

Za extra snahu a námahu môžu byť udelené extra body po zvážení cvičiacim. Extra funkcionalita môže byť napr.:

  • nerovnosť terénu, na ktorom sú umiestnené tanky

  • pohyb tankov (napr. riadený z klávesnice)
  • pokročilá vizualizácia v konzole (výbuchy, realistická dráha projektilu, naklonenie kanónu tanku)
  • ostatné:
    • zdravie tankov
    • damage rôznych typov projektilov
    • rádius poškodenia tanku
    • rôzne atribúty tankov ako napr. štít, dočasné zosilnenie zbrane, možnosť strieľať viackrát za sebou
    • rôzne predmety predmety rozmiestnené na hernej ploche so špecifickým významom pre hru

Zdroje

Veľa úspechov pri programovaní zadania.