Diskuze: Hra Hankgman v céčku

C++ C a C++ Hra Hankgman v céčku

Avatar
Libor Šimo (libcosenior):

Ak si chce niekto preveriť svoje znalosti jazyka C, dávam sem školské zadanie hry Hangman v jazyku c.
http://it4kt.cnl.sk/…set-two.html
Pretože je už po deadline a každý rok sa zadáva iné zadanie(informáciu mám z vídeo lekcie), môžme sem dávať kódy a konzultovať ich.

Odpovědět 28.4.2014 6:57
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Libor Šimo (libcosenior):

Dám sem svoje funkčné riešenie. Ak to bude niekoho zaujímať, kľudne napíšte čo je špatne, budem len rád. Takýmito zadaniami sa učím.

Nahoru Odpovědět 28.4.2014 12:01
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Libor Šimo (libcosenior):

Neviem ako sem dať ten kód, možno takto: http://www.itnetwork.cz/dev-lighter/368

Editováno 28.4.2014 12:34
Nahoru Odpovědět  -1 28.4.2014 12:32
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Redaktor
Avatar
Odpovídá na Libor Šimo (libcosenior)
coells:

Je tam velká spousta chyb, za všechny se můžeme podívat na funkci getAvailableLet­ters():

void getAvailableLetters(char lettersGuessed[], char availableLetters[])
{
    int i, j = 0;
    // to ma byt konstantni staticka promenna mimo funkci
    char *najdi, abcd[] = "abcdefghijklmnopqrstuvwxyz";

    // proc??
    // dynamicka alokace je zbytecna a navic to je memleak
    najdi = (char *) malloc(15);
    // strlen() se bude vyhodnocovat pro kazde pismeno znovu
    for (i = 0; i < strlen(abcd); i++){
        najdi = strchr(lettersGuessed, abcd[i]);
        // a) kdyz otocis podminku, nemusis mit vubec else vetev
        // b) v C staci napsat if (!najdi) nebo if (najdi)
        if (najdi != NULL)
            continue;
        else {
            availableLetters[j++] = abcd[i];
        }
    }
    availableLetters[j] = '\0';
    // funkce getX() urcite nema nic vypisovat!
    printf("%s", availableLetters);
}

V C platí, že co je malé, to je hezké. Pracuj s pointry a snaž se zkrátit kód. Když tvoje řešení přepracuju, měl by v C-čkový zdroják vypadat takhle:

static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz";

void getAvailableLetters(char lettersGuessed[], char availableLetters[])
{
    const char *pa = alphabet;

    do {
        if (!*pa || !strchr(lettersGuessed, *pa))
            *availableLetters++ = *pa;
    } while (*pa++);
}

A také se snaž držet jednoho jazyka a nemíchej C s angličtinou a slovenštinou.

 
Nahoru Odpovědět  +2 28.4.2014 13:50
Avatar
Odpovídá na coells
Libor Šimo (libcosenior):

Viem, že práca s pointermi je základ, ale ešte nie som tak ďaleko, aby som to zvládal na tvojej úrovni.
Aj napriek tomu mám nejaké otázky.
Toto

static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz";

je globálna premenná? Ak áno, nie je splnená podmienka úlohy (každá globálna premenná znamená minus v hodnotení).
Navyše vypisovat sa má aj položka: Available letters takto obr.1, ale po použití tvojho (ináč veľmi pekného) kódu to tam chýba obr.2.

Editováno 28.4.2014 14:57
Nahoru Odpovědět 28.4.2014 14:57
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Libor Šimo (libcosenior):

Druhý obrázok mi to nevzalo do prvého príspevku.

Nahoru Odpovědět 28.4.2014 14:58
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Redaktor
Avatar
Odpovídá na Libor Šimo (libcosenior)
coells:

"alphabet" není globální proměnná, je to lokální konstanta a ve smyslu řešení úlohy zcela korektní postup.

AvailableLetters bys měl vypisovat, ale určitě ne v metodě getAvailableLet­ters(), tam printf() být nemá.

 
Nahoru Odpovědět 28.4.2014 15:04
Avatar
Odpovídá na coells
Libor Šimo (libcosenior):

Díky, skúsim sa s tým ešte pohrať. Potom to sem znovu pastnem na kontrolu.

Nahoru Odpovědět 28.4.2014 15:12
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Redaktor
Avatar
Odpovídá na Libor Šimo (libcosenior)
coells:

Mimochodem, já bych kód psal spíš takhle

void getAvailableLetters(char lettersGuessed[], char availableLetters[])
{
    for (int i = 'a'; i <= 'z'; i++)
        if (!strchr(lettersGuessed, i))
            *availableLetters++ = i;
    *availableLetters = 0;
}
 
Nahoru Odpovědět 28.4.2014 15:18
Avatar
Odpovídá na coells
Libor Šimo (libcosenior):

Po ukončení funkcie ostanú dáta v pamäti?

Nahoru Odpovědět 28.4.2014 22:01
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na coells
Libor Šimo (libcosenior):

Asi tomu nerozumiem, ale som naučený používať funkcie s návratovou hodnotou void na to, že niečo vypíšu. V tomto prípade nevypíšu nič. Ako môžem tú funkciu použiť, keď nič nevráti? Možno ostanú v pamäti dáta, ktoré môžem použiť.

Nahoru Odpovědět 28.4.2014 22:08
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Redaktor
Avatar
Odpovídá na Libor Šimo (libcosenior)
coells:

availableLetters je výstupní parametr, do funkce se předá reference na (char*), takže po opuštění funkce budou data uložena tam.

 
Nahoru Odpovědět 28.4.2014 22:19
Avatar
Odpovídá na coells
Libor Šimo (libcosenior):

Výborne, toto mi nebolo jasné. Díky.

Nahoru Odpovědět 29.4.2014 4:38
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na Libor Šimo (libcosenior)
Libor Šimo (libcosenior):

Ten kód je úplne perfektný, len jedna maličkosť, aby to niekoho nepomýlilo.
Toto

for (int i = 'a'; i <= 'z'; i++)

v čistom céčku nebude fungovať. Premenná sa musí deklarovať mimo parametrov funkcie for().

int i;
for (i = 'a'; i <= 'z'; i++)
Nahoru Odpovědět 29.4.2014 7:41
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na coells
Libor Šimo (libcosenior):

Predsa len mám jednu otázku k tvojmu kódu:

void getAvailableLetters(char lettersGuessed[], char availableLetters[])
{
    int i;
    for (i = 'a'; i <= 'z'; i++)
        if (!strchr(lettersGuessed, i))
            *availableLetters++ = i;
    *availableLetters = 0;
}

Pracujeme tam s reťazcom a ten by sa mal (vždy) ukončiť znakom '\0', ale ty tam máš

*availableLetters = 0;

Je zaujímavé, že keď dám po vykonaní funkcie vypísať reťazec availableLetters, vypíše sa v poriadku, teda ako by bol správne ukončený.

Môžeš mi to prosím vysvetliť?

Editováno 29.4.2014 8:05
Nahoru Odpovědět 29.4.2014 8:05
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
vitamin
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
vitamin:

Normy z roku 1999+ (c99, c11) povoluju deklaraciu v inicializacnej casti for cyklu.
for nie je funkcia.

'\0' == 0;

 
Nahoru Odpovědět 29.4.2014 8:16
Avatar
Odpovídá na vitamin
Libor Šimo (libcosenior):

Díky.
\0' == 0; => toto som nevedel
To druhé (povolenie)znamená, že keď budem kód písať napr. vo vim v linuxe, budem to môcť použit? Pretože v Code:blocks, ktorý používam, mi to vypisuje chybu.
Ale keď v Code:blocks píšem kód v c++, tam to funguje bez problémov.

Editováno 29.4.2014 9:05
Nahoru Odpovědět 29.4.2014 9:04
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Redaktor
Avatar
Odpovídá na Libor Šimo (libcosenior)
coells:

norma AnsiC požaduje deklarace proměnných na začátku fce
norma C99 povoluje deklaraci kdekoliv

Záleží na nastavení kompilátoru, dnes většina umí obě normy, mělo by stačit přepnou kompilátor do režimu C99

 
Nahoru Odpovědět 29.4.2014 9:45
Avatar
Odpovídá na coells
Libor Šimo (libcosenior):

Pred pár dňami som to upravil, ale podľa tvojej rady som si najprv napísal testy. Len test na funkciu void hangman(char secret[]) som nedokázal napísať ani po jej napísaní.

Nahoru Odpovědět 4.5.2014 22:08
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Redaktor
Avatar
Odpovídá na Libor Šimo (libcosenior)
coells:

Kvůli uživatelskému vstupu?

Udělej to následujícím způsobem. Funkce v C, která má 10-15 řádek začíná být podezřelá, funkce, která má 50 řádek je zaručeně napsaná špatně. Rozděl si hangman() na řadu menších statických funkcí a napiš si testy na ně. hangman() pak bude obsahovat jednoduchý cyklus, ze kterého pouze volá ostatní funkce. Tím snížíš pravděpodobnost chyby. Navíc díky tomu, že i hangman() bude dlouhá nejvýš 10 řádků, půjde snadno odhalit chyba už od pohledu.

 
Nahoru Odpovědět 4.5.2014 22:22
Avatar
Odpovídá na coells
Libor Šimo (libcosenior):

Díky, máš pravdu. Ja som sa striktne držal zadania a to je tá moja chyba.;)

Nahoru Odpovědět 5.5.2014 6:21
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
vitamin
Člen
Avatar
Odpovídá na coells
vitamin:

Suhlasim, ale ak funkcia obsahuje vecsi switch, tak moze byt dost velka a zaroven stale prehladna.

 
Nahoru Odpovědět 5.5.2014 8:49
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 23 zpráv z 23.