Kowal_91 Opublikowano 20 Maja 2013 Zgłoś Opublikowano 20 Maja 2013 Witam, Zaznaczę na początku iż dopiero jakoś od ponad miesiąca przyłożyłem się do nauki c++. Wcześniej na pierwszym roku studiów uczyliśmy się C, potem javy, więc nie jestem w tym temacie aż taki zielony. Programowanie mnie interesuje, dlatego chcę rozwijać swoje zainteresowania i kształcić się w tym kierunku. Zakupiłem do tego celu książkę Jerzego Grębosza - Symfonia C++ standard. Uczę się z niej na bieżąco, razem z przykładami i próbuję pisać swoje własne programy, które przyjdą mi do głowy. Jestem osobą, która lubi uczyć się na własnych błędach, lecz problemu z którym próbuję się uporać nie mogę rozwikłać. Domyślam się, że przyczyna tego jest banalna, lecz na dzień dzisiejszy nie mogę pojąć dlaczego Dlatego mam nadzieję, że mi pomożecie i wyjaśnicie dlaczego to jest źle. Problem, a dokładniej rzecz mówiąc, bardziej taka ciekawostka, której nie mogę zrozumieć pojawia się podczas rysowania mapy (a dokładniej głowy węża). Ale o tym bliżej za chwilę. Moja mapa jest tablicą dwuwymiarową obiektów typu char. Posiadam dwie funkcje, jedna która rysuje mapę (tj. obramowanie i ustawia każdy z elementów tej tablicy jako znak ASCII o kodzie 255 (czyli spacja). Oraz druga, która powinna rysować głowę węża o podanych wartościach tej tablicy. Lecz niestety nie rysuje. Natomiast, gdy rysowanie węża uwzględnie w funkcji, która rysuje mapę to głowa węża zostaje na tej mapie narysowana. Dlaczego tak się dzieje? I dlaczego głowa węża nie chce się narysować za pomocą oddzielnej funkcji? Byłbym niezmiernie wdzięczny, gdyby ktoś mógł mi tę sytuację wytłumaczyć :) Oto kod programu: #include <iostream>#include <conio.h>#include <cstdlib>using namespace std;void rysuj_mape(char mapa[20][60]);void wstaw_weza(char mapa[20][60]);int main(){ char mapa[20][60]; rysuj_mape(mapa); wstaw_weza(mapa); getch(); return 0;}//////////////////// FUNKCJA RYSUJĄCA MAPĘ DO GRY ////////////////////void rysuj_mape(char mapa[20][60]){ cout << " ------------------------------------------------------------" << endl; for(int i = 0; i < 20; i++) { cout << "|"; // ramka od lewej strony for(int j = 0; j < 60; j++) { mapa[i][j]=255; cout << mapa[i][j]; } cout << "|"; // ramka od prawej strony cout << endl; } cout << " ------------------------------------------------------------" << endl;}//////////////////// FUNKCJA USTAWIAJĄCA WĘŻA NA MAPIE ////////////////////void wstaw_weza(char mapa[20][60]){ mapa[10][30] = 'O'; // wstawienie węża do gry} Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach Więcej opcji udostępniania...
MaciekCi Opublikowano 21 Maja 2013 Zgłoś Opublikowano 21 Maja 2013 Nie podałeś funkcji rysowania węża. :) Podaj funkcję, bo gdzieś musisz mieć minimalny błąd. Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach Więcej opcji udostępniania...
Kowal_91 Opublikowano 21 Maja 2013 Zgłoś Opublikowano 21 Maja 2013 Nie podałeś funkcji rysowania węża. Podaj funkcję, bo gdzieś musisz mieć minimalny błąd. Funkcja ta jest zawarta w kodzie, na samym dole :) Ona ustawia (czyli rysuje) węża na mapie, a przynajmniej powinna ale tego nie robi. //////////////////// FUNKCJA USTAWIAJĄCA WĘŻA NA MAPIE ////////////////////void wstaw_weza(char mapa[20][60]){ mapa[10][30] = 'O'; // wstawienie węża do gry} Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach Więcej opcji udostępniania...
m4r Opublikowano 21 Maja 2013 Zgłoś Opublikowano 21 Maja 2013 Spróbuj tak: int main(){ char mapa[20][60]; wstaw_weza(mapa); rysuj_mape(mapa); getch(); return 0;}1. Aktualizujesz tablicę z pozycją węża2. Aktualizujesz ekran opierając się na zaktualizowanej tablicy Nigdy na odwrót. Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach Więcej opcji udostępniania...
MaciekCi Opublikowano 21 Maja 2013 Zgłoś Opublikowano 21 Maja 2013 (edytowane) Funkcja ta jest zawarta w kodzie, na samym dole Ona ustawia (czyli rysuje) węża na mapie, a przynajmniej powinna ale tego nie robi. Zwróć uwagę, że funkcja wstaw_weza tylko aktualizuje tablicę, ale nic nie rysuje, bo przecież Twoim "rysownikiem" jest cout, którego tu nie ma. Tak jak m4r napisał, jeśli chcesz to rozwiązać w ten sposób, najpierw aktualizuj tablicę a dopiero później wywołuj coś do rysowania. Jednak ... To nie ma prawa zadziałać, ponieważ w funkcji rysuj_mape nadpisujesz wszystkie komórki wartością 255, więc Twoje 'O' przepada. EDIT : Możesz jeszcze wstawić fragment kodu rysuj_mape , który "działa". :) W tym momencie masz tak : 1. Rysujesz mapę z wypełnionymi komórkami na 255. 2. Aktualizujesz tablicę. i nic się nie dzieje, bo nie ma prawa się dziać. W drugą stronę : 1. Aktualizujesz tablicę ([10][30]='O') 2. Rysujesz mapę, która zapełnia komórki wartością 255 (w tym Twoje 'O'). W koło Macieju. Musisz pomyśleć nad innym rozwiązaniem. Edytowane 21 Maja 2013 przez MaciekCi Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach Więcej opcji udostępniania...
Kowal_91 Opublikowano 21 Maja 2013 Zgłoś Opublikowano 21 Maja 2013 Okej, wziąłem pod uwagę Wasze informacje i zrozumiałem na czym polegał mój błąd. Dziękuję Wam :) Zmodyfikowałem nieco funkcję rysuj_mape, uwzględniając w niej pozycję węża. Napisałem również pozostałe funkcje, tj. poruszanie węża, oraz sprawdzanie czy wąż nie uderzył w ścianę (czy nie jest przekroczony zakres tablicy). Poniżej przesyłam kod i chciałbym, abyście mi podpowiedzieli w jaki sposób mógłbym ten kod zoptymalizować, by był nieco krótszy i prostrzy. Jestem w tej dziedzinie słaby, także chętnie wysłucham wszystkich Waszych porad :) Wiem też, że używałem tam często polecenia na czyszczenie ekranu (system("cls")) i wiem też, że na pewno można co zrobić inaczej, lepiej. #include <iostream>#include <conio.h>#include <cstdlib>using namespace std;void zeruj_mape(char mapa[20][60]);void rysuj_mape(char mapa[20][60]);void wstaw_weza(char mapa[20][60], int &x, int &y);void ruch(char mapa[20][60], int &x, int &y);bool koniec(char mapa[20][60], int &x, int &y);int main(){ char mapa[20][60]; int x = 30; // współrzędna na osi X, czyli [j]. Przypisane są tylko początkowe wartości int y = 10; // współrzędna na osi Y, czyli [i] do { system("cls"); zeruj_mape(mapa); wstaw_weza(mapa, x, y); rysuj_mape(mapa); ruch(mapa, x, y); koniec(mapa, x, y); } while(!koniec(mapa, x, y)); getch(); return 0;}//////////////////// FUNKCJA ZERUJĄCA MAPĘ DO GRY ////////////////////void zeruj_mape(char mapa[20][60]){ for (int i = 0; i < 20; i++) for (int j = 0; j < 60; j++) mapa[i][j] = 0;}//////////////////// FUNKCJA RYSUJĄCA MAPĘ DO GRY ////////////////////void rysuj_mape(char mapa[20][60]){ cout << " ------------------------------------------------------------" << endl; for(int i = 0; i < 20; i++) { cout << "|"; // ramka od lewej strony for(int j = 0; j < 60; j++) { if(mapa[i][j] != 'O') mapa[i][j]=32; cout << mapa[i][j]; } cout << "|"; // ramka od prawej strony cout << endl; } cout << " ------------------------------------------------------------" << endl;}//////////////////// FUNKCJA USTAWIAJĄCA WĘŻA NA MAPIE ////////////////////void wstaw_weza(char mapa[20][60], int &x, int &y){ mapa[y][x] = 'O'; // wstawienie węża do gry}//////////////////// FUNKCJA PORUSZAJĄCA WĘŻA PO MAPIE ////////////////////void ruch(char mapa[20][60], int &x, int &y){ char ruch = getch(); if(ruch == 'w') { y--; system("cls"); zeruj_mape(mapa); wstaw_weza(mapa, x, y); rysuj_mape(mapa); } if(ruch == 's') { y++; system("cls"); zeruj_mape(mapa); wstaw_weza(mapa, x, y); rysuj_mape(mapa); } if(ruch == 'a') { x--; system("cls"); zeruj_mape(mapa); wstaw_weza(mapa, x, y); rysuj_mape(mapa); } if(ruch == 'd') { x++; system("cls"); zeruj_mape(mapa); wstaw_weza(mapa, x, y); rysuj_mape(mapa); }}//////////////////// FUNKCJA SPRAWDZAJĄCA CZY WĄŻ UDERZYŁ W ŚCIANĘ ////////////////////bool koniec(char mapa[20][60], int &x, int &y){ bool test = false; if(x < 0 || x > 59) { test = true; system("cls"); cout << "nn KONIEC GRY!"; return test; } if(y < 0 || y > 19) { test = true; system("cls"); cout << "nn KONIEC GRY!"; return test; } return test;} Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach Więcej opcji udostępniania...
MaciekCi Opublikowano 21 Maja 2013 Zgłoś Opublikowano 21 Maja 2013 Wiem też, że używałem tam często polecenia na czyszczenie ekranu (system("cls")) i wiem też, że na pewno można co zrobić inaczej, lepiej. Mam już pamięć mocno zakurzoną jeśli chodzi o konsolowe zabawki, ale z tego co kojarzę, używałem funkcji write i gotoXY i zamiast clsować cały czas, używałem funkcji write, która wypisywała zupdatowaną tablicę. ;) Może Ci to w czymś pomoże... Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach Więcej opcji udostępniania...
Kowal_91 Opublikowano 21 Maja 2013 Zgłoś Opublikowano 21 Maja 2013 Program udało mi się skrócić do takiej postaci jak w kodzie poniżej. Dodałem dodatkowo funkcję losującą i wstawiającą na mapę jabłka :) #include <iostream>#include <conio.h>#include <cstdlib>#include <ctime>using namespace std;void zeruj_mape(char mapa[20][60]);void rysuj_mape(char mapa[20][60]);void wstaw_weza(char mapa[20][60], int &x, int &y);void ruch(char mapa[20][60], int &x, int &y);bool koniec(char mapa[20][60], int &x, int &y);void losuj_jablko(char mapa[20][60], int &x, int &y, int &jx, int &jy);int main(){ srand(time(NULL)); char mapa[20][60]; int x = 30; // współrzędna na osi X, czyli [j]. Przypisane są tylko początkowe wartości int y = 10; // współrzędna na osi Y, czyli [i] int jx = rand() % 59; // współrzędne pierwszego jabłka int jy = rand() % 19; // ------------||--------------- do { system("cls"); zeruj_mape(mapa); wstaw_weza(mapa, x, y); losuj_jablko(mapa, x, y, jx, jy); rysuj_mape(mapa); ruch(mapa, x, y); koniec(mapa, x, y); } while(!koniec(mapa, x, y)); getch(); return 0;}//////////////////// FUNKCJA ZERUJĄCA MAPĘ DO GRY ////////////////////void zeruj_mape(char mapa[20][60]){ for (int i = 0; i < 20; i++) for (int j = 0; j < 60; j++) mapa[i][j] = 0;}//////////////////// FUNKCJA RYSUJĄCA MAPĘ DO GRY ////////////////////void rysuj_mape(char mapa[20][60]){ cout << " ------------------------------------------------------------" << endl; for(int i = 0; i < 20; i++) { cout << "|"; // ramka od lewej strony for(int j = 0; j < 60; j++) { if(mapa[i][j] == 0) mapa[i][j]=32; cout << mapa[i][j]; } cout << "|"; // ramka od prawej strony cout << endl; } cout << " ------------------------------------------------------------" << endl;}//////////////////// FUNKCJA USTAWIAJĄCA WĘŻA NA MAPIE ////////////////////void wstaw_weza(char mapa[20][60], int &x, int &y){ mapa[y][x] = 'O'; // wstawienie węża do gry}//////////////////// FUNKCJA PORUSZAJĄCA WĘŻA PO MAPIE ////////////////////void ruch(char mapa[20][60], int &x, int &y){ char ruch = getch(); if(ruch == 'w') y--; if(ruch == 's') y++; if(ruch == 'a') x--; if(ruch == 'd') x++;}//////////////////// FUNKCJA SPRAWDZAJĄCA CZY WĄŻ UDERZYŁ W ŚCIANĘ ////////////////////bool koniec(char mapa[20][60], int &x, int &y){ bool test = false; if(x < 0 || x > 59) { test = true; system("cls"); cout << "nn KONIEC GRY!"; return test; } if(y < 0 || y > 19) { test = true; system("cls"); cout << "nn KONIEC GRY!"; return test; } return test;}//////////////////// FUNKCJA LOSUJĄCA JABŁKO NA MAPIE ////////////////////void losuj_jablko(char mapa[20][60], int &x, int &y, int &jx, int &jy){ if(x == jx && y == jy) { jx = rand() % 59; jy = rand() % 19; } mapa[jy][jx] = '*';} MaciekCi, co do tych funkcji write i gotoXY nie bardzo mogę znaleźć opisy, więc też tym bardziej nie mam pojęcia jak je zastosować. Jest jeszcze jeden problem, ponieważ teraz snake jest praktycznie o zerowym poziomie trudności. Chciałbym dodać, aby wraz z czasem snake się sam poruszał w ostatnim wybranym kierunku, lecz nie mam pojęcia jak taki efekt uzyskać. Może miałby ktoś jakieś porady ? :) Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach Więcej opcji udostępniania...
Kowal_91 Opublikowano 24 Maja 2013 Zgłoś Opublikowano 24 Maja 2013 Ok uzyskałem ten efekt. Przerobiłem funkcję ruch, niby trochę na około ale nie ogarniam jeszcze optymalizacji ;d No ale najważniejsze, że działa :) Teraz chciałbym, aby wąż po każdym zjedzeniu jabłka rósł o jedno pole. Myślałem, żeby robić to na liście bądź na wektorach, ale nigdy jeszcze nie przerabiałem tych elementów, więc nie wiem czy się połapię. Wiem tylko że można tam łatwo dodawać element na początek i usuwać element z ostatniego miejsca, ale co i jak to już nie wiem.Macie jakieś porady dla mnie czy to byłoby dobre rozwiązanie? Czy może jest jeszcze jakieś inne, łatwiejsze?Poniżej przesyłam ponownie cały kod (zmianie uległa przede wszystkim funkcja ruch() ) #include <iostream>#include <conio.h>#include <cstdlib>#include <ctime>#include <Windows.h>using namespace std;void zeruj_mape(char mapa[20][60]);void rysuj_mape(char mapa[20][60]);void wstaw_weza(char mapa[20][60], int &x, int &y);void ruch(char mapa[20][60], int &x, int &y, char &ruch);bool koniec(char mapa[20][60], int &x, int &y);void losuj_jablko(char mapa[20][60], int &x, int &y, int &jx, int &jy, int &pkt);int main(){ srand(time(NULL)); char mapa[20][60]; int x = 30; // współrzędna na osi X, czyli [j]. Przypisane są tylko początkowe wartości int y = 10; // współrzędna na osi Y, czyli [i] int jx = rand() % 59; // współrzędne pierwszego jabłka int jy = rand() % 19; // ------------||--------------- int punkty = 0; char kierunek='w'; do // główna pętla gry { system("cls"); zeruj_mape(mapa); wstaw_weza(mapa, x, y); losuj_jablko(mapa, x, y, jx, jy, punkty); rysuj_mape(mapa); ruch(mapa, x, y, kierunek); koniec(mapa, x, y); } while(!koniec(mapa, x, y)); // warunek kończący grę cout << "nn KONIEC GRY!"; cout << "nn Twoj wynik to: " << punkty; getch(); return 0;}//////////////////// FUNKCJA ZERUJĄCA MAPĘ DO GRY ////////////////////void zeruj_mape(char mapa[20][60]){ for (int i = 0; i < 20; i++) for (int j = 0; j < 60; j++) mapa[i][j] = 0;}//////////////////// FUNKCJA RYSUJĄCA MAPĘ DO GRY ////////////////////void rysuj_mape(char mapa[20][60]){ cout << " ------------------------------------------------------------" << endl; for(int i = 0; i < 20; i++) { cout << "|"; // ramka od lewej strony for(int j = 0; j < 60; j++) { if(mapa[i][j] == 0) mapa[i][j]=32; cout << mapa[i][j]; } cout << "|"; // ramka od prawej strony cout << endl; } cout << " ------------------------------------------------------------" << endl;}//////////////////// FUNKCJA USTAWIAJĄCA WĘŻA NA MAPIE ////////////////////void wstaw_weza(char mapa[20][60], int &x, int &y){ mapa[y][x] = 'O'; // wstawienie węża do gry}//////////////////// FUNKCJA PORUSZAJĄCA WĘŻA PO MAPIE ////////////////////void ruch(char mapa[20][60], int &x, int &y, char &ruch){ if(kbhit()) // sprawdza czy jest jakiś znak w buforze { Sleep(100); ruch = getch(); // jeśli jest to przypisuje go do zmiennej ruch i wykonuje jedną z następujących akcji if(ruch == 'w') y--; if(ruch == 's') y++; if(ruch == 'a') x--; if(ruch == 'd') x++; } else // jeśli nie ma to wykonuje ponownie ostatnio wykonany ruch { Sleep(100); if(ruch == 'w') y--; if(ruch == 's') y++; if(ruch == 'a') x--; if(ruch == 'd') x++; } }//////////////////// FUNKCJA SPRAWDZAJĄCA CZY WĄŻ UDERZYŁ W ŚCIANĘ ////////////////////bool koniec(char mapa[20][60], int &x, int &y){ bool test = false; if(x < 0 || x > 59) { test = true; system("cls"); return test; } if(y < 0 || y > 19) { test = true; system("cls"); return test; } return test;}//////////////////// FUNKCJA LOSUJĄCA JABŁKO NA MAPIE ////////////////////void losuj_jablko(char mapa[20][60], int &x, int &y, int &jx, int &jy, int &pkt){ if(x == jx && y == jy) { jx = rand() % 59; jy = rand() % 19; pkt++; } mapa[jy][jx] = '*';} Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach Więcej opcji udostępniania...
m4r Opublikowano 24 Maja 2013 Zgłoś Opublikowano 24 Maja 2013 Czy fukcja losuj_jablko uwzględnia omijanie "pikseli" zajętych przez węża? Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach Więcej opcji udostępniania...
Kowal_91 Opublikowano 24 Maja 2013 Zgłoś Opublikowano 24 Maja 2013 Czy fukcja losuj_jablko uwzględnia omijanie "pikseli" zajętych przez węża? Poprawione :) Dzięki za informacje :D Dodałem pętle w momencie losowania nowego jabłka: //////////////////// FUNKCJA LOSUJĄCA JABŁKO NA MAPIE ////////////////////void losuj_jablko(char mapa[20][60], int &x, int &y, int &jx, int &jy, int &pkt){ if(x == jx && y == jy) { do { jx = rand() % 59; jy = rand() % 19; } while(jx == x && jy == y); pkt++; } mapa[jy][jx] = '*';} Jak ktoś ma jeszcze jakieś uwagi, wzmianki, które warto byłoby poprawić to proszę pisać :) No i czekam nadal na odpowiedź w sprawie wydłużającego się węża po każdym zjedzeniu jabłka :> Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach Więcej opcji udostępniania...