Předvánoční slevová akce PHP týden
Pouze tento týden sleva až 80 % na PHP e-learning!
Využij předvánočních slev a získej od nás 20 % bodů zdarma! Více zde

Diskuze: Domácí úkol FIT ČVUT (progtest 5.1/2019)

Aktivity (2)
Avatar
David Gerner
Člen
Avatar
David Gerner:29. listopadu 19:16

Ahoj, máme zadaný domácí úkol na hledání min, program dostane po řádcích pole s minami a má vytvořit vyřešené pole s minami, tedy to na konci, když se vám všude zobrazí správná čísla s počty min v okolí. Zadání přiložím.
Zdůrazňuji že rozhodně nechci aby to někdo vypracoval za mě, potřebuju spíš nakopnout do zadku(hlavy) protože jsem úplně ztracen a nevím vůbec co s tím.

Díky za jakékoli nápady či připomínky ;)

Zkusil jsem: Tady je nějaký můj pokus, rozhodně to není funkční program, spíš jen takové myšlenkové črty, ale jsou všechny špatně, tak spíš abyste věděli jakým směrem se ubíraly mé dosavadní úvahy.

void fillArray(char ** array, int n, int m);
char ** solveMines (char ** array);

int main (void){
        int n = 100, m = 100;
        char ** mineField = (char **) malloc (sizeof(char)*n);
        for(int i=0; i<100; i++)
                mineField[i] = (char *) malloc(sizeof(char)*m);
        printf("Zadejte hraci plochu:\n")
        fillArray(mineField, n, m);

}

void fillArray(char ** array, int n){   //takhle funkce má vyplnit pole těmi zadanými hodnotami, ale nevím jak na to protože nevím předem jak jsou řádky dlouhé ani kolik jich bude
        char buffer[101];
        for (int i=0; i<n; i++){
                scanf("%100[^\n]", buffer);
                strcpy(array, buffer);
        }
}

char ** solveMines (char ** array){ //tady jsem zas chtěl nějak porovnávat sousední pole, ale nemyslím že to bude moc fungovat, navíc nevím jak pak jít o řádek níž
        int i=0, j=0;
        while(array[i][j]){
                while (array[i][j]){
                        if(array[i][j]=='.'){
                                if(array[i+1][j]=='*'&&array[i][j+1]!='*'&&array[i+1][j+1]!='*')
                                        array[i][j]='1';
                                else if(array[i][j+1]=='*'&&array[i+1][j+1]!='*'&&array[i+1][j]!='*')
                                        array[i][j]='1';
                                else if(array[i+1][j+1]=='*'&&array[i+1][j]!='*'&&array[i][j+1]!='*')
                                        array[i][j]='1';
                                else if(array[i+1][j]=='*'&&array[i][j+1]=='*'&&array[i+1][j+1]!='*')
                                        array[i][j]='2';
                                else if(array[i+1][j]=='*'&&array[i][j+1]!='*'&&array[i+1][j+1]=='*')
                                        array[i][j]='2';
                                else if(array[i+1][j]!='*'&&array[i][j+1]=='*'&&array[i+1][j+1]=='*')
                                        array[i][j]='2';
                                else if (array[i+1][j]=='*'&&array[i][j+1]=='*'&&array[i+1][j+1]=='*')
                                        array[i][j]='3';
                        }
                        i++;
                }
                j++
        }
}

Tohle je komplet všechno co mám, bohužel.

 
Odpovědět
29. listopadu 19:16
Avatar
aXxel
Člen
Avatar
aXxel:29. listopadu 19:42

Tu lavinu podmínek bych nahradil jedním for cyklem, který by v případě, že se jedná o minu, přidal všem pozicím bez miny okolo, tedy začneš v levém horním rohu 3x3 čtverce vůči té pozici s minou a kontroluješ jestli je to validní pozice, +1.

Editováno 29. listopadu 19:44
 
Nahoru Odpovědět
29. listopadu 19:42
Avatar
David Gerner
Člen
Avatar
Odpovídá na aXxel
David Gerner:29. listopadu 19:46

Aaa, díky, to mě vúůbec nenapadlo jít po minách ;)
akorát ono je to žejo pole charů a všude kolem je tečka, takže bych musel mít nějaký tmp proměnný abych tam mohl ukládat ty čísla a až bych zkontroloval celé okolí bodu tak bych to teprv mohl zapsat, ne...?

 
Nahoru Odpovědět
29. listopadu 19:46
Avatar
aXxel
Člen
Avatar
aXxel:29. listopadu 19:50

Nemusíš jít čistě jen po minách, bylo by to sice efektivnější, ale musel by sis pamatovat v dalším poli jejich pozice, stačí do tech 2 while cyklu který ti procházej celý pole přidat if: pokud se jedná o minu zavolej nad tohle pozici funkci, která děla to co jsem popsal výše. Protože jsou to všechno znaky, tak tečku budeš brát jako 0 a pokud tam bude něco jiného než tečka a hvězdička, přetypuješ to na číslo, přičteš jedničku a uložíš zpátky jako char.

Editováno 29. listopadu 19:51
 
Nahoru Odpovědět
29. listopadu 19:50
Avatar
aXxel
Člen
Avatar
aXxel:29. listopadu 20:02

A ohledně toho načítání, když předem nevíš kolik toho bude, tak ve while cyklu budeš načítat po znacích např přes getchar() a v případě, že ti dojde místo v poli, zdvojnásobíš kapacitu a zavoláš realloc().

 
Nahoru Odpovědět
29. listopadu 20:02
Avatar
DarkCoder
Člen
Avatar
Odpovídá na David Gerner
DarkCoder:30. listopadu 13:42

program dostane po řádcích pole s minami…

Toto je dosti neúplná informace. Je třeba blíže specifikovat z jakého vstupu ta data program obdrží popř. jaký je ukázkový vstup, neboť způsob komunikace mezi vstupem a programem se značně liší. Jsem si téměř jist, že ta data budou posílána ze souboru a to z následujícího důvodu:

Vždy potřebuješ znát ukončovací signál

V předchozím příspěvku aXxel správně zmínil, jakým způsobem se přistupuje ke vstupu, jehož velikost není známa. getchar() pro konzolu, lépe však pomocí fgetc() s konkrétním streamem. Pro manipulaci s načteným znakem pak můžeš používat dynamickou alokaci paměti nebo souborový systém.

Pokud je vstupem soubor, je situace jednoduchá. Souborový systém posílá informaci, zda-li došlo k chybě nebo na konec souboru (EOF). Tuto informaci lze otestovat. To je signál k tomu, že už na vstupu nic dalšího není (platí v případě, že EOF představuje konec souboru nikoli chybu).

Úryvek kódu pro načítání ze souboru neznámého počtu dat bez ošetření na chybu

do {
        c = fgetc(fp);
        if (feof(fp)) break;
        putchar(c);
} while (1);

Avšak pokud je vstupem klávesnice, je situace naopak neřešitelná. Když Ti začnu na klávesnici postupně házet řádky dat:

Např.
001000100010'\n'
100011000011'\n'
110110011100'\n'
….

Tak nevíš, jestli poslední zadaný řádek ukončený znakem '\n' byl skutečně tím posledním nebo bude další řádek následovat. Při načítání dat Ti celý načítací cyklus zůstane v blokovacím režimu na čtecí funkci očekávající nový řádek. Ten já mohu poslat ale nemusím. Signál (EOF), který byl u načítání dat ze souboru, se zde neposílá. Nelze použít signál v podobě znaku '\n'´pro ukončení cyklu, neboť tento znak je součástí procedury načítání řádku.

Následující úryvek kódu nebude pracovat správně pro načtení vstupu po řádcích

do {
        c = getchar();
        if (c == '\n') break;
        putchar(c);
} while (1);

Proto nejlepší bude, pokud sem pošleš přesné znění zadání. (Pozn. Není za účelem zpracování úlohy za tebe)

Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
Nahoru Odpovědět
30. listopadu 13:42
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Patrik Valkovič
Šéfredaktor
Avatar
Odpovídá na DarkCoder
Patrik Valkovič:30. listopadu 14:51

To není úplně pravda, i z konzole lze vyvolat EOF. Data jdou ze standardního vstupu.

Nahoru Odpovědět
30. listopadu 14:51
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Patrik Valkovič
DarkCoder:30. listopadu 15:32

V případě příkladu vstupu, který jsem uvedl (varianta čtení nespecifikovaného počtu řádků z klávesnice), se EOF neposílá. To ale neznamená, že EOF nelze explicitně vyvolat i ze standardního vstupu. To ano, to máš pravdu. Kombinace CTRL+D popř. CTRL-Z (dle OS) tento signál vyvolá. Ukončovat vstup tímto způsobem je absolutně zcestné. Na to slouží příkazově orientované rozhraní v podobě klíčového slova.

Nahoru Odpovědět
30. listopadu 15:32
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
David Gerner
Člen
Avatar
Odpovídá na DarkCoder
David Gerner:6. prosince 10:44

Celé zadání je zasláno ve screenshotech. Z toho co jsem tam přečetl jsem pochopil že bude zadáváno po řádcích a že na konec stejně bude EoF. Ale jistej si tím nejsem.
Každopádně vzhledem k tomu že už je po odevzdávacím datu, tak klidně nic nedělej, já to někomu fajfknu a já si s tím budu hrát až někdy až se budu nudit ;)

 
Nahoru Odpovědět
6. prosince 10:44
Avatar
Odpovídá na David Gerner
Erik Šťastný:6. prosince 12:24

Můžu prosím ze zvědavosti o jaký semestr FITu, jde? :)

 
Nahoru Odpovědět
6. prosince 12:24
Avatar
Lu Kiss
Člen
Avatar
Odpovídá na Erik Šťastný
Lu Kiss:7. prosince 10:54

Co jsem tak slyšel, tak slavný Vagnerův Progtest na C je v prvnim semestru

 
Nahoru Odpovědět
7. prosince 10:54
Avatar
Odpovídá na Lu Kiss
Erik Šťastný:9. prosince 10:52

Díky za info, vzhledem k tomu, že se jde na VŠ od nuly, tak mi přišlo, že pro první semestr je to celkem HC pro člověka co se před pár měsíci dozvěděl co je to programování :D

 
Nahoru Odpovědět
9. prosince 10:52
Avatar
Honza Bittner
Šupák
Avatar
Odpovídá na Erik Šťastný
Honza Bittner:9. prosince 13:38

A tos neviděl úkoly na další semestry. :-)))

Nahoru Odpovědět
9. prosince 13:38
Student FIT ČVUT. In love with Dart &...
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Erik Šťastný
DarkCoder:9. prosince 14:04

Teď Ti to možná připadá těžké, protože nevíš co a jak a kdy správně použít. Jakmile se ale dozvíš o jazyku C více, bude Ti to připadat úsměvné a snadné. Postupně budou tvé aplikace elegantnější a efektivnější.

Nahoru Odpovědět
9. prosince 14:04
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Odpovídá na DarkCoder
Erik Šťastný:9. prosince 14:05

Mě to těžké nepřijde, přijde mi to těžké na někoho, kdo se učí programovat 4 měsíce :)

 
Nahoru Odpovědět
9. prosince 14:05
Avatar
Ladislav Vagner:9. prosince 14:16

Dobrý den,
Myslím si že toto asi nebude nejlepší řešení Vašeho problému.
Stavte se na konzultaci po prosemináři.

 
Nahoru Odpovědět
9. prosince 14:16
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 16 zpráv z 16.