Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Programowanie obiektowe - Aplikacja do sterowania robotem

Ostatnio zmodyfikowano 2014-04-05 10:09
Autor Wiadomość
szaroket
Temat założony przez niniejszego użytkownika
» 2014-03-30 00:23:30
Co do pozycji robota - udało mi się ustawić. Jestem bardzo wdzięczna za kod - patrzę, że nie jest długi, ale sama gdybym miała pisać, to za wiele by nie wyszło. Już jutro zacznę go analizować, aby każdy krok zrozumieć. Poczytam też to o tej klasie.
Czy w razie problemów ze rozumieniem kodu mogłabym się zapytać Ciebie?
P-107460
Monika90
» 2014-03-30 00:26:22
Czy w razie problemów ze rozumieniem kodu mogłabym się zapytać Ciebie?
Czemu nie? Czy wiesz jak działają klasy std::vector i std::string? Jak nie, to zacznij od nich, bo one są tu kluczowe.
Dobranoc.

Trochę u mnie wali się dodawanie planszy, bo dodaje tylko dolna linijkę, ale spróbuję sama do tego dojść :)
To dlatego, że w pliku z planszą masz windowsowe zakończenia linii, tzn. CR LF, a w Linuksie musi być samo LF. Stwórz planszę jeszcze raz edytorem tekstu pod Linuksem.
P-107461
szaroket
Temat założony przez niniejszego użytkownika
» 2014-03-31 09:43:18
Zaczelam czytac o tych bibliotekach i w niektorych miejscach powoli rozumiem kod. Ale wydaje mi sie, ze jest on za madry w przypadku mojej osoby. Znaczy, w C++ programuje moze 3 tygodnie. Wczesniej troche programowalam w C.
Dlatego mam takie pytanie - uwierzylabys komus takiemu, ze napisal podobny program? Mi.naprawde zalezy by zrozumiec to co robie, bo bezmyslne przepisywanie nic mi nie da. Oczywiscie jestem cholernie wdzieczna za pomoc. Tylko chyba osobiscie.jestem za glupia troche.
P-107509
Monika90
» 2014-03-31 10:52:16
Dlatego mam takie pytanie - uwierzylabys komus takiemu, ze napisal podobny program?
Zależy jak ten ktoś był uczony. Dla kogoś, kto zna C++, w tym programie nie ma niczego nadzwyczajnego. Prosty programik rozwiązujący banalny problem. (i nawet nie ma w nim sprawdzania poprawność danych wczytywanych z pliku - to źle)

Ale można go napisać inaczej - bez std::vector i bez std::string. Można zrobić tablicę znaków
char plansza[ max_height ][ max_width ];
 i do niej wczytywać znaki z pliku. To oczywiście oznacza, że wysokość i szerokość łączna planszy nie będzie mogła być większa niż te dwie stałe (max_height i max_width) zdefiniowane w programie. Moim zdaniem tak jest trudniej. Eksperci są tu zgodni (prawdziwi eksperci, nie tacy forumowi): std::vector i std::string to jedne z pierwszych rzeczy, krórych początkujacy powinni się nauczyć.
P-107511
szaroket
Temat założony przez niniejszego użytkownika
» 2014-04-04 18:35:25
Trochę przeanalizowałam program i myślę, że go nawet rozumiem.

C/C++
Board( char * file_name )
{
    add_segment( file_name );
   
    //lewy dolny róg
    robot_x_ = 1;
    robot_y_ = rows_.size() - 2;
}

Rozumiem, że jest to konstruktor, który stwarza obiekt Planszę funkcję "add_segment" oraz przechowuję informację o pozycji robota w planszy.

C/C++
void add_segment( char * file_name )
{
    fstream file( file_name ); //zmienna, która pozwala nam na wszelkie działania na pliku.
    string row;
    int y = 0;
    while( getline( file, row ) )
    {
        if( rows_.size() <= y )
             rows_.push_back( row ); //dodawanie nowych elementow na koncu tablicy
        else
             rows_[ y ] += row;
       
        ++y;
    }
}

"file" jest naszą zmienną, która pozwala nam na wszelkie operacje na pliku, zaś "row" jest nazwą obiektu klasy string, w której funkcja getline ma umieścić wczytywany tekst. Samo "getline" pozwala nam wczytywać bardzo wiele wyrazów bez konieczności wcześniejszego rezerwowania miejsca w tablicy. Ponadto "getline" wczytuje nasz plik wierszami.
getline( file, row ) jest naszym warunkiem kończącym pętle, czyli jak cały plik się wczyta to pętla się zakończy. W samej pętli mamy warunek, że jeśli rozmiar wierszy (size() zwraca nam rozmiar/długość zmiennej rows, czyli wszystkich wierszy, tak?) jest mniejszy lub równy 0 to zostanie dodany nowy element, w naszym wypadku cała plansza, na końcu tablicy (z prawej strony).
W przeciwnym wypadku... no właśnie, o co chodzi z tym "else"? Bo rozumiem, że doda nam planszę wtedy tylko, gdy jest ona takiego samego rozmiaru co tablica pierwsza, ale nie za bardzo rozumiem ten warunek "else".

C/C++
void show()
{
    for( int y = 0; y < rows_.size(); ++y )
    {
        const string & row = rows_[ y ];
        if( y == robot_y_ )
             cout << row.substr( 0, robot_x_ ) << robot << row.substr( robot_x_ + 1, string::npos ) << '\n';
        else
             cout << row << '\n';
       
    }
}

Tej funkcji nie rozumiem za bardzo. Pętla for inicjuje nam działanie od y=0, ++y - wpierw nam zwiększa o 1, potem zwraca tę wartość, pętla zakończy się w momencie gdy y będzie mniejsze do rozmiaru zmiennej "rows", czyli wszystkich wierszy.

C/C++
const string & row = rows_[ y ];

Tego nie rozumiem całkowicie. I z tym miejscem mam też problemy podczas podziały programu na pliki (na koniec postu dodam mój program).

Dalej mamy warunek, że jeśli y jest równy położeniu robot_y to wyświetli nam się... i tu też problem. nie rozumiem tego ciągu. Z tego, co wyczytałam to "substr" zwraca nam nowy string, który powstał poprzez skopiowanie ilości znaków łańcucha "row". czy chodzi o to, że on zwraca nam planszę wpierw od pozycji 0 to pozycji "x" robota, następnie sam robot jest umieszczany, a następnie znów zwraca się nam plansza od kolejnej linii "pod" robotem oraz reszta znaków planszy?
W przeciwnym razie pętla wyświetli nam całą planszę.

C/C++
bool move_robot( int dx, int dy ) //zwraca true wtedy i tylko wtedy gdy ruch był możliwy
{
    const int new_x = robot_x_ + dx;
    const int new_y = robot_y_ + dy;
    if( new_x >= 0 && new_x < rows_[ 0 ].size() && new_y >= 0 && new_y < rows_.size() && rows_[ new_y ][ new_x ] != wall )
    {
        rows_[ robot_y_ ][ robot_x_ ] = trace; //zostaw ślad
        robot_x_ = new_x;
        robot_y_ = new_y;
        return true;
    }
   
    return false;
}

Tutaj mamy funkcię odpowiedzialną za ruch robota. Przypisuję ona nowym zmiennym "new_x, new_y" sumę starej pozycji robota oraz podane "dx, dy". Jeśli nowe zmienne są większe lub równe 0, mniejsze od rozmiaru wiersza_[0] (dla new_x), mniejsze od rozmiaru wszystkich wierszy (dla new_y) oraz pozycja wiersza (jakiś punkt x,y) nie jest ścianą to ruch jest możliwy. W miejscu starej pozycji robota pojawi się ślad "x", zaś starym pozycją zostanie przypisana nowa pozycja. Funckaja zwróci prawdę.
W przeciwnym razie, gdy ruch nie będzie możliwe, zwróci fałsz i ruch się nie wykona.

C/C++
private:
int robot_x_, robot_y_;
vector < string > rows_;

Prywatne zmienne położenia robota. A jak dokładnie zrozumieć tę drugą linijkę? Deklaruje wektor rows typu "string"?

Main cały rozumiem, więc go nie zamieszczam.

Próbowałam sama napisać program, jednak wyszło, że bardzo opierałam się na Twoim, co trochę jest załamujące, że nie potrafię nic stworzyć.
P-107694
Monika90
» 2014-04-05 10:09:40
Rozumiem, że jest to konstruktor, który stwarza obiekt Planszę [...]
Tak, to jest konstruktor, który inicjalizuje obiekt klasy Board. Zadaniem konstruktora jest wprowadzenie obiektu w określony stan początkowy, tzn. taki żeby spełniony był niezmiennik klasy. U nas niezmiennik brzmi: plansza ma wymiar co najmniej 1x1 (tzn. rows_ ma co najmniej jeden niepusty wiersz) i współrzędne robota nie są poza planszą. Temu konstruktorowi uda się ten stan osiągnąć pod warunkiem, że w pliku z planszą są poprawne dane - należałoby dodać sprawdzanie poprawności i rzucić wyjątek gdy dane sa niepoprawne.

W przeciwnym wypadku... no właśnie, o co chodzi z tym "else"? Bo rozumiem, że doda nam planszę wtedy tylko, gdy jest ona takiego samego rozmiaru co tablica pierwsza, ale nie za bardzo rozumiem ten warunek "else".

Może najpierw ustalmy co robią te instrukcje
C/C++
rows_.push_back( row );
Dodaje row jako nowy wiersz na końcu wektora rows_, a to
C/C++
rows_[ y ] += row;
dodaje wiersz row na końcu wiersza numer y, tzn. jeżeli rows_[y] było równe "pies", a row było równe " czyli kot", to teraz rows_[y] będzie równe "pies czyli kot".

Ale żeby można było dodać coś do wiersza, to ten wiersz musi istnieć. Więc to
C/C++
if( rows_.size() <= y )
     rows_.push_back( row );
else
     rows_[ y ] += row;

znaczy: jeżeli w wektorze nie ma wiersza o indeksie y, to dodaj row jako nowy wiersz, a jak wiersz o indeksie y już jest, to doklej row po prawej stronie tego wiersza.

Przy pierwszym wywołaniu funkcji add_segment z konstruktora, wektor rows_ jest pusty, wtedy wszystkie wiersze wczytane z pliku będą dodawane na końcu. W kolejnych wywołaniach będą się doklejać na końcu już istniejących wierszy, no chyba, że w dodawanej planszy będzie więcej wierszy niż w pierwszej, wtedy nadmiarowe się dodadzą jako nowe na końcu wektora.

C/C++
const string & row = rows_[ y ];
Tego nie rozumiem całkowicie. I z tym miejscem mam też problemy podczas podziały programu na pliki (na koniec postu dodam mój program).
To definiuje row jako referencję do rows_[y], to znaczy, że w zakresie w którym ta deklaracja jest widoczna, gdy użyjesz row, to efekt jest taki jakbyś użyła rows_[y] - to takie uproszczenie zapisu.
Nie rozumiem jaki to może mieć wpływ na podział na pliki, zresztą chyba tych plików dużo nie masz: board.cpp, board.hpp i main.cpp?

Dalej mamy warunek, że jeśli y jest równy położeniu robot_y to wyświetli nam się... i tu też problem. nie rozumiem tego ciągu. Z tego, co wyczytałam to "substr" zwraca nam nowy string, który powstał poprzez skopiowanie ilości znaków łańcucha "row". czy chodzi o to, że on zwraca nam planszę wpierw od pozycji 0 to pozycji "x" robota, następnie sam robot jest umieszczany, a następnie znów zwraca się nam plansza od kolejnej linii "pod" robotem oraz reszta znaków planszy?
Dla wszystkich wierszy planszy, od góry do dołu, robimy tak: jeżeli w wierszu nie ma robota, to wyświetlamy ten wiersz i przechodzimy do natępnego. Jeżeli w wierszu jest robot, to wyświetlamy część wiersza po lewej stronie robota, potem literę r, następnie część wiersza po prawej stonie robota i przechodzimy do następnego wiersza planszy.

Można wyświetlanie planszy zrobić inaczej. Podczas poruszania robotem można zapisywać literę r
w odpowiednim miejscu planszy
rows_[ new_y ][ new_x ] = robot;
, dzięki temu wyświetlanie byłoby proste - wystarczyłoby wyświetlić kolejne wiersze. To by było dobre, zwłaszcza gdyby okazało się, że robotów ma być więcej niż jeden.

C/C++
private:
int robot_x_, robot_y_;
vector < string > rows_;
Prywatne zmienne położenia robota. A jak dokładnie zrozumieć tę drugą linijkę? Deklaruje wektor rows typu "string"?
Wektor, którego elementami są obiekty typu (klasy) string. Analogicznie vector<int> liczby;, vector<Robot> roboty; - wektor intów i wektor robotów. std::vector to tablica dynamiczna w eleganckim opakowaniu.
P-107727
1 « 2 »
Poprzednia strona Strona 2 z 2