• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Przekazanie zmiennej do metody klasy pochodnej

0 głosów
121 wizyt
pytanie zadane 26 czerwca 2020 w C i C++ przez Slasher Nowicjusz (120 p.)

Cześć,

można powiedzieć, że jestem laikiem w programowaniu, stąd najlepiej uważam, że człowiek uczy się w praktyce - zacząłem więc pisać prosty program/grę rpg, wykorzystując obiektowy c++. I o ile dużo problemów byłem już w stanie rozwiązać samemu, o tyle ten to całkowicie dla mnie ściana nie do przebycia. 

Chciałem stworzyć system walki, który opierałby się na wywoływaniu odpowiednich metod wskaźnikiem polimorficznym. Prosty schemat walki: wprowadzenie obiektu klasy Wrog -> ustawienie wskaźnika -> ustawienie zmiennych (punkty życia itd.) -> wyliczenie obrażeń -> zadanie obrażeń postaci. W prostszym schemacie wywoływanych metod: Wrog wilk; wskaźnik; w->statystyki(); w->atak(); p->przyjecie_obrazen().

No i problem leży w tym ostatnim kroku, gdzie metoda klasy Rycerz miałaby przyjąć wartość obrażeń wykalkulowanych przez metodę atak() w klasie Wilk. 

Próbowałem więc różnych sposobów, przesyłałem do tej metody tę wartość różnorako, i przez wskaźnik, i przez osobną zmienną, którą stworzyłem w programie głównym, i poprzez wskaźnik polimorficzny (chociaż do końca nie wiem, czy tak się da, ale kompilator nie narzekał). Program, gdy dochodzi do tego momentu, zwraca po prostu dziwnie dużą liczbę i zakończa proces (dokładnie na linijce wskaznikpostaci1->przyjecie_zmiennej(i);, gdyż to już testowałem).

Program główny: https://pastebin.com/EJ11n2LE , nagłówek postac: https://pastebin.com/GKChC1vx , nagłówek wrog: https://pastebin.com/VgtSK2zx .

I nie mam niestety dalej pomysłu, nawet przeczucia, że mogę coś źle robić. (i dodam tylko jeszcze, że funkcja przyjecie_zmiennej jest nowym "nabytkiem", bez niej również nie działało)

#include <iostream>
#include <cstdlib>
#include <conio.h>
#include <stdio.h>
using namespace std;
#include "klasapostac.h"
#include "klasawrog.h"

char co;
char imie_postaci[20];
void nadanie_imienia()
	{
	cout<<"\nPodaj imie postaci: ";
	cin.getline(imie_postaci, 20);
	};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
void wyborRycerz()
{
	Postac *wskaznikpostaci;
	Rycerz Gracz1;
	wskaznikpostaci = &Gracz1;
	wskaznikpostaci->statystyki();
}
void wyborMag()
{
	Postac *wskaznikpostaci;
	Mag Gracz2;
	wskaznikpostaci = &Gracz2;
	wskaznikpostaci->statystyki();
}
void wyborLotr()
{
	Postac *wskaznikpostaci;
	Lotr Gracz3;
	wskaznikpostaci = &Gracz3;
	wskaznikpostaci->statystyki();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
void walka(Postac *wskaznikpostaci1,Wrog *wskaznikwroga)
{
	system("cls");
	cout<<"Napotykasz na lesnej drodze wyglodnialego wilka. Zaczyna biec w twoja strone..."<<endl;
	Wilk A;
	wskaznikwroga = &A;
	wskaznikwroga -> statystyki();
	wskaznikwroga -> atak();
	int *i;
	i = &wskaznikwroga->obrazenia;
	cout<<*i;
	wskaznikpostaci1->przyjecie_zmiennej(i);
	//wskaznikpostaci1->otrzymaj_obrazenia();
	
	//wskaznikpostaci1 -> otrzymaj_obrazenia();
	cout<<"\nWilk wbiegl na ciebie z impetem, zadajac "; 
	cout<<wskaznikwroga->obrazenia;
	cout<<" obrazen!\n";
	cout<<"Akcje:\n1. Uderz.";

while(true)
{
	co=getch();
		switch(co)
		{
			case '1': wskaznikpostaci1 -> atak(); 
			int i; cout<<wskaznikpostaci1->obrazenia;
		}
}

}


int main(){
menu:	
	cout<<"============================\nNajprostsza gra RPG historii\n============================\n";
	cout<<"1. Zacznij przygode\n"
		<<"2. Tworcy\n"
		<<"3. Wyjscie\n";
	while(true)
	{
	co=getch();
		switch(co)
		{
		case '1': goto kontynuacja;
		case '2': cout<<"\nPomysl i realizacja - Nikodem Bochnacki\n"
					<<"Kod i testy - Nikodem Bochnacki\n"
					<<"Wszystkie prawa zastrzezone :)\n\n";
					goto menu;
					break; 
		case '3': exit(0);
		default: exit(0);
		}
	}
kontynuacja:
	system("cls");
	cout<<"TUTORIAL\n";
	cout<<"U gory ekranu zawsze wyswietli sie lokacja, w ktorej znajduje sie obecnie postac. Pod nia ewentualne dialogi\n"
	<<"i wydarzenia. Nizej wyswietlaja sie dostepne akcje (nie musisz potwierdzac wyboru).\n\nUlepszaj ekwipunek, walcz z potworami i przetrwaj.\nPowodzenia!";
	cout<<"\n\n(Nacisnij dowolny klawisz, by rozpoczac gre)\n";
	getchar();
	system("cls");
	
	cout<<"Budzisz sie na srodku drogi. Pochyla sie nad toba chlop i mowi:\n"
		<<"- Zes spadl jak grom z nieba! Jak cie zwa?"
		<<"\nNo wlasnie... Jak Cie zwa?";
		nadanie_imienia();
		system("cls");
		
	cout<<"- "<<imie_postaci<<"? Pracy szukasz moze? Dobrze zbudowany to w polu sie nadasz, a i potworow kilka ubic chyba dasz rade!\n"
		<<"Chlop, odwracajac sie, rzucil jeszcze:\n- Idz do tawerny, tam na pewno cos znajdziesz. - i udal sie w swoja strone. "
		<<"\nCoz... Chyba nie masz lepszego wyboru.\n\n";
		
	cout<<"Akcje:\n1. Idz do tawerny.\n";
while(true)
		{
	co=getch();
	switch(co)
		{
		case '1': goto rozmowa;
		default: cout<<"\nUps! Zly przycisk...";
		}}
rozmowa:
	system("cls");
	cout<<"- Witaj! Jestem Karczmarzem - potrzebujesz czegokolwiek? Przychodz do mnie! Zawsze \n"
	"chetnie pomoge... za odpowiednia zaplata. No, ale opowiedz cos o sobie!\n\n";
	cout<<"A wiec jestes...\n";
	cout<<"============================\n\tWybor klasy\n============================\n"
		<<"1. Rycerzem\n"
		<<"2. Magiem\n"
		<<"3. Lotrem";
	Wrog *wskaznikwroga;
while(true){
	co=getch();
		switch(co)
		{
			case '1': wyborRycerz(); system("cls"); goto kontynuacja1;
			case '2': wyborMag(); system("cls"); goto kontynuacja1;
			case '3': wyborLotr(); system("cls"); goto kontynuacja1;
			default: cout<<"\nUps! Zly przycisk..."<<endl;
		}}
kontynuacja1:
		cout<<"\n- Ach, alez dobrze miec takiego kogos w takich ciezkich czasach. No wiec, jak bedziesz\n"
			<<"czegokolwiek potrzebowal - porozmawiaj ze mna. Jak na karczmarza przystalo, mam dostep do wie-\n"
			<<"lu przywilejow. Jesli natomiast chcesz wyruszyc w dalsza podroz, zawsze bedziemy tu czekac."<<endl;
		cout<<"\n Jak zawsze... Zero bezinteresownosci. No nic, i tak nie masz pieniedzy, wiec pora pokrecic sie\n"
			<<"po okolicy."<<endl;
		cout<<"\nAkcje:\n1. Wyjdz z tawerny.\n";
	Postac *wskaznikpostaci1;
while(true)
	{
	co=getch();
		switch(co)
		{
			case '1': walka(&*wskaznikpostaci1,&*wskaznikwroga); break;
			default: cout<<"\nUps! Zly przycisk..."<<endl;
		}
	}
		
		
		
		return 0;
}

Może istnieje jakiś prostszy sposób, a kombinuję niepotrzebnie? Prosiłbym również o wyrozumiałość, wiem, że kodowi daleko do zoptymalizowania, zapewne nie powinienem również wszystkiego w klasie pochodnej dawać jako "public", ale takimi rzeczami zajmę się, gdy program doprowadzę do końca.

Z góry dzięki za poświęcony czas!

komentarz 26 czerwca 2020 przez Michał Gibas Pasjonat (19,630 p.)

Ogólnie, mam jedno zastrzeżenie, takie jak do wielu początkujących, proszę o nie używanie polskich nazw w kodzie, tylko angielskie nazwy zmiennych/klas/metod ;) Jak coś w kodzie nie działa, to polecam zainteresować się takim bardzo przydatnym programem jakim jest debugger i samemu postarać się wywnioskować dlaczego taki bug w ogóle powstał.

komentarz 26 czerwca 2020 przez Slasher Nowicjusz (120 p.)
Próbowałem używać i nie do końca rozumiem to, co zwraca. Końcowy komunikat to "Segmentation fault", przy czym wyświetla okienko CPU z różnymi, dziwnymi linijkami kodu, więc byłbym super wdzięczny, gdybym chociaż dowiedział się, na co mam w nim patrzeć.

Swoją drogą, skąd takie "nastawienie" do polskich nazw w kodzie? Teoretycznie to nic nie zmienia?
1
komentarz 26 czerwca 2020 przez Michał Gibas Pasjonat (19,630 p.)

Teoretycznie nic nie zmienia, ale przy normalnych projektach absolutnie niedopuszczalne i poza tym, żeby program po prostu działał, warto jeszcze dbać o 'czystość' kodu i używanie angielskich nazw (to jest must have w programowaniu), bo jak inny programista będzie robił np. review twojego kodu to nigdy nie wiadomo, czy nie będzie obcokrajowcem. Angielski to standard w branży (elementy składniu języków programowania są nazywane po angielsku int - od Integer, string etc; więc lepiej się konsekwentnie trzymać tego), innych języków się po prostu nie używa. Jeśli byśmy używali różnych języków do nazywania klas/metod etc. to gdybym używał kilku zewnętrznych bibliotek (co się często zdarza) to wychodziłyby takie potwory:

void convert_to_string(int liczba) {
/*załóżmy że mamy jakąś lib'ke zewnętrzną konwertującą int'a na string'a, której autor zdecydował się nazywać wszystko np. po niemiecku: */ 
  std::string napis = Beschriftung(liczba);
  return napis;
//to nie wygląda dobrze 
//3 różne języki w kodzie ;(
}

Tutaj jeszcze link do fajnego artykułu na temat dlaczego angielski jest ważny: https://it-academy.pl/dlaczego-programista-powinen-znac-jezyk-angielski/

Jeśli chodzi o debugger, to zależy jakiego używasz i trzeba się po prostu nauczyć tym posługiwać, nie ma zmiłuj. Musisz trochę o tym poczytać: jak ustawiać breakpoint'y, używać ptrace, sprawdzać wartości zmiennych etc. Jeśli używasz gdb to: https://youtu.be/sCtY--xRUyI a jeśli visual studio to: https://youtu.be/0ebzPwixrJA

Pozdrawiam! :)

komentarz 26 czerwca 2020 przez Slasher Nowicjusz (120 p.)
Dzięki, na pewno się rozeznam!
1
komentarz 27 czerwca 2020 przez sunzi Bywalec (2,000 p.)

@Michał Gibas, @Slasher
Zgadam się w 200% odnośnie angielskich nazw. Dodam jednak małą gwiazdeczkę smiley do tego. W przypadku początkujących osób, których może to jest pierwszy, może drugi program w życiu - oczywiście, że nazewnictwo jest bardzo istotne - ale moim zdaniem jeśli "nie czujecie" angielskich nazw, albo utrudniają wam te nazwy zrozumienie lub czytanie kodu, to ja bym nie rozdzierał szat jeśli ktoś by użył tu czy tam lub gdyby ktoś cały program napisał z polskim nazewnictwem. Na nazewnictwo przyjdzie czas - ale bądź tego świadomy i próbuj sukcesywnie wdrażać tą zasadę w życie w miarę jak coraz bardziej oswoisz się z językiem programowania i z samym programowaniem i algorytmami.

Ja pamiętam jak zaczynałem programować to używałem polskich nazw, ale uważam, że pomogło mi to wtedy lepiej zrozumieć co się dzieje w programie. Oczywiście z biegiem czasu przerzuciłem się na angielskie nazewnictwo, ale pamiętam nie było to trudne, bo byłem już dość dobrze oswojony z programowaniem i językiem którego wtedy używałem.

Podsumowując. Oczywiście staraj się używać angielskich nazw, ale jeśli znacznie to Ci utrudnia pisanie programu to odpuść do czasu gdy napiszesz pare/parenaście prostych programów i będziesz się lepiej czuł z językiem którego używasz smiley Nie musisz od dnia pierwszego pisać perfekcyjnego kodu - nie wiem czy to w ogóle możliwe :D

1 odpowiedź

0 głosów
odpowiedź 1 lipca 2020 przez Aqua 4 Gaduła (3,220 p.)

Program, gdy dochodzi do tego momentu, zwraca po prostu dziwnie dużą liczbę i zakończa proces (dokładnie na linijce wskaznikpostaci1->przyjecie_zmiennej(i);, gdyż to już testowałem).

Jakiego typu zmiennej używasz do przechowywania zmiennej HP? Jakiego typu jest zwracana zmienna? Czy gdzieś po drodze nie stosujesz typu unsigned (lub innego podobnego typu: unsigned short, unsigned long, unsigned long long itd.)? Jeśli tak, to zmień go na int. Unsigned zamiast ujemnych liczb przebiera wartość, właśnie tych "dziwnie dużych liczb".

komentarz 1 lipca 2020 przez Slasher Nowicjusz (120 p.)

Problem rozwiązany dość przypadkiem, ale odpowiem na ten komentarz, by może w googlu ludziom wyskakiwało, gdy wpiszą podobny problem :P 

Cóż, okazało się, że kompilator nie pokazał mi braku ";" w jednym miejscu, po czym zaczęły dziać się cuda. 

Program działa dokładnie tak,  jak chciałem, czyli sposób sam w sobie jest w porządku (zmienna hit_points to zwykły int, unsigned int używam, ale tylko i wyłącznie w miejscach, gdzie muszę losować jakąś wartość (srand ((unsigned int)time(NULL));), więc nie wychodzi to poza metodę klasy. 

Teraz jednak przesyłam wartość wskaźnikiem (wcześniej kompilator przy braku ";" nie chciał wysyłać w sposób: wskaznikwroga->zadaj_obrazenia(wskaznikpostaci->obrazenia)).

Dzięki za pomoc!

Podobne pytania

0 głosów
4 odpowiedzi 409 wizyt
0 głosów
5 odpowiedzi 1,209 wizyt

88,355 zapytań

136,952 odpowiedzi

305,669 komentarzy

58,619 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Sklep oferujący ćwiczenia JavaScript, PHP, rozmowy rekrutacyjne dla programistów i inne materiały

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...