Autor Wątek: C++ Problem ze stworzeniem ekwipunku.  (Przeczytany 21998 razy)

Offline Acarin1995

  • Użytkownik

# Styczeń 05, 2014, 20:15:30
Witam chcę stworzyć ekwipunek do swojej gry rpg w konsoli. I mam pytanie czy pomożecie mi skończyć kod. Bo niewiem co dalej zrobić.
//main.CPP
#include <iostream>
#include <vector>
#include "Postac.hpp"
#include "Przedmiot.hpp"
#include "Ekwipunek.hpp"
#include"Bron.hpp"
int main()
{
CPostac Postac;
CEkwipunek Ekwipunek;
CPrzedmiot* bron = new CMiecz();
Ekwipunek.plecak.push_back(bron);
bron = new CSztylet();
Ekwipunek.plecak.push_back(bron);
cout<<Ekwipunek.plecak[0]->nazwa<<endl;
cout<<Ekwipunek.plecak[1]->nazwa<<endl;
cout<<Ekwipunek.plecak[0]->nazwa<<endl;
cout<<Ekwipunek.plecak[1]->nazwa<<endl;


return 0;
}
//Postac.hpp
#ifndef POSTAC_hpp
#define POSTAC_hpp
#include <string>
#include "Przedmiot.hpp"
using namespace std;
class CPostac
{
public:
    string imie;
    int atakMin;
    int atakMax;
    CPostac();
    ~CPostac();
};


#endif
//Przedmiot.hpp
#ifndef PRZEDMIOT_hpp
#define PRZEDMIOT_hpp
#include <string>
using namespace std;
class CPrzedmiot
{
public:
    string  nazwa;
};

#endif
//Bron.hpp
#ifndef BRON_hpp
#define BRON_hpp
#include"Przedmiot.hpp"
class CBron : public CPrzedmiot
{
public:
    int atakMin;
    int atakMax;
};
class CSztylet : public CBron
{
public:
CSztylet();

};
class CMiecz : public CBron
{
public:
CMiecz();

};

#endif
//Ekwipunek.hpp
#ifndef _EKWIPUNEK_hpp
#define _EKWIPUNEK_hpp

#include <string>
#include <vector>
#include "Przedmiot.hpp"
class CEkwipunek
{
public:
  vector<CPrzedmiot*> plecak;
};

#endif
//Bron.cpp
#include "Bron.hpp"
CSztylet::CSztylet()
{
nazwa="Sztylet";
atakMin=2;
    atakMax=2;
}
CMiecz::CMiecz()
{
nazwa="Miecz";
atakMin=1;
    atakMax=4;
}
//Postac.cpp
#include "Postac.hpp"
CPostac::CPostac()
{
imie="Gracz";
atakMin=0;
    atakMax=2;
        bron = 0;

}
CPostac::~CPostac()
{

}
Wytłumaczę wam czego potrzebuje... Chcę zrobić by plecak mieścił 25 przedmiotów, jeżeli jest pusty to się wyświetla "Pusto, jeżeli są jakieś elementy to je wyświetla, tak samo ekwipunek postaci, by dało się założyć/użyć przedmiot z plecaka, Chcę stworzyć ekwipunek postaci zawierający: reka prawa (bron), reka lewa (bron pomocnicza/tarcza), glowa, korpus, nogi. Tak by dało się zdejmywać przedmioty które trafiały by do plecaka. Albo jeżeli postać chcę to może je wyrzucić lub sprzedać w sklepie. Dziękuje za pomoc.

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Estivo

  • Użytkownik
    • Blog

# Styczeń 06, 2014, 00:10:28
Zrobiłbym tablice 25 elementową i tam trzymał rzeczy. Dodał do CPrzedmiot wartość. Do tego ekwipunek niezależny od gracza to średniawy pomysł. Według mnie wszystko powinno przelatywać przez gracza, bo to on sprzedaje i wywala rzeczy, a nie Ekwipunek.

Offline Xirdus

  • Redaktor

  • +3
# Styczeń 06, 2014, 01:35:06
Zacznijmy od tego, że sztylet i miecz nie powinny być podklasami broni, tylko jej instancjami (zwykłymi obiektami). Dziedziczenie stosuje się wtedy, gdy zachowanie obiektu jest inne. Sztylet i miecz zachowują się dokładnie tak samo - kod gry pobiera min i max ataku z broni i losuje liczbę spomiędzy. Nie ważne, czy będzie to miecz, sztylet, siekiera, wakizashi, działko laserowe - kod gry będzie traktował to w identyczny sposób. W takiej sytuacji nie ma sensu robić dziedziczenia - wręcz przeciwnie, ono będzie strasznie przeszkadzać. Za to przy podziale na bronie/zbroje/używalne/itp. to dziedziczenie już ma sens - chociaż da się to też rozwiązać bez niego (o czym niżej).

Druga sprawa - nie jest to obowiązkowe, ale myślę, że byłoby o wiele lepiej, gdyby ekwipunek nie przechowywał wszystkich danych o przedmiotach, tylko same identyfikatory ich typów (zwykły int - np. 0 to sztylet, 2 to kolczuga, 3 to mała mikstura HP itd. Alternatywnie - normalnie stringi), a same dane na ich temat siedziałyby w specjalnie do tego stworzonym obiekcie-bazie danych. Wtedy nie będziesz się musiał obawiać, że gdzieś tam w kodzie zawieruszyła się stara wersja jakiejś broni która ma 10 razy lepsze staty od wersji finalnej, i innych podobnych sytuacji.

Sprawa numer trzy:
Zrobiłbym tablice 25 elementową i tam trzymał rzeczy. Dodał do CPrzedmiot wartość.
Żeby tak zrobić, musiałby zrobić przedmiot jako unię wszystkich "podklas" przedmiotu. Z jednej strony ma to kilka zalet, z drugiej to unie mogą nowemu programiście zdrowo namieszać w głowie (chociażby przez wymuszenie POD-ów). Polecałbym mu jednak pozostać przy dziedziczeniu i trzymaniu przez wskaźnik (a jeszcze lepiej - shared_ptr). Trzecim rozwiązaniem jest wspomniany obiekt bazodanowy i trzymanie samych identyfikatorów. Jeśli dobrze się to zrealizuje, nie będzie trzeba ani unii, ani dziedziczenia.

Czwarte primo:
Do tego ekwipunek niezależny od gracza to średniawy pomysł. Według mnie wszystko powinno przelatywać przez gracza, bo to on sprzedaje i wywala rzeczy, a nie Ekwipunek.
Tutaj się nie zgodzę. Jeśli nie będzie wielu postaci, z których każda ma własny, oddzielny od reszty ekwipunek, nie ma sensu łączyć klasy ekwipunku z klasą gracza. Tutaj wspomnę, że ork trzymający maczugę i noszący dziurawe łachmany niekoniecznie musi posiadać ekwipunek w rozumieniu "plecakowym". Zależnie od paru czynników, nie musi on w rzeczywistości mieć żadnego ekwipunku - po prostu jego "gołe" staty ustawiane są tak, jakby miał, a ewentualny loot to osobna, niezwiązana z ekwipunkiem sprawa. Nie zawsze się to sprawdzi, ale OP chyba takie rozwiązanie zadowala.

Na koniec wspomnę, że nie do końca podoba mi się konwencja nazewnictwa (język polski, zaczynanie nazw klas od C i nazw zmiennych od dużej litery), ale to już tylko takie moje prywatne niekonstruktywne psioczenie :)

Offline Cerberus

  • Użytkownik
    • Moja strona

  • +1
# Styczeń 06, 2014, 02:04:30
To ja jeszcze swoje trzy grosze, żeby autor mógł spojrzeć na różne podejścia do problemu ;)

100% zgody co do niepotrzebnego dziedziczenia - jak już się chcemy pakować w hierarchie klas, niech to będzie jeden abstrakcyjny przedmiot i broń/zbroja/etc. dziedziczące po nim.

Póki co jednak funkcjonalność, którą opisujesz, jest względnie prosta i podział na mnóstwo klas i plików wydaje mi się być overkillem. W najprostszym wariancie zrobiłbym to tak:

Enum określający slot, czyli ręka prawa/ręka lewa/głowa/tors/nogi.

Strukturka reprezentująca przedmiot, niech sobie na początku ma tylko pole powyższego enuma, które określa, jakiego rodzaju jest to przedmiot, oraz nazwę.

Gracz ma pięć slotów na aktywny ekwipunek, czyli miejsce na pięć powyższych strukturek (może być pięcio-elementowa tablica indeksowana naszym enumem). Najchętniej bym tu widział wskaźniki na te struktury przedmiotu. Do tego plecak, czyli tablica 25 elementów, albo std::vector, którego rozmiar będziemy kontrolować.

Offline Acarin1995

  • Użytkownik

# Styczeń 06, 2014, 11:20:59
Witam ponownie. Kod poniżej wydaje mi się że rozwiązuje problem z maksymalną ilością przedmiotów w plecaku.
vector<CPrzedmiot*> plecak(25);wasze propozycję wydają się być ciekawe czy mogę was prosić o podstawienie tego pod kod mojego programu??

Offline ArekBal

  • Użytkownik

# Styczeń 06, 2014, 12:25:36
Zamknijcie ten temat bo podchodzi pod paragrafy warsztatowe !!!


Offline Estivo

  • Użytkownik
    • Blog

  • +1
# Styczeń 06, 2014, 13:17:36
@ Xirdus

Chyba za bardzo patrzyłem przez pryzmat gry niekonsolowej, stąd rozgraniczenie gracz i npc, ale o do "ekwipunku" npc, to zawsze może mieć tylko eq[5] i loot[2] i jest to zawsze mniej i łatwiej obsłużyć niż robić kolejne eq[25] z racji, że było by około 20 pustych elementów (ofc jeżeli byłby to vector bez zarezerwowanego rozmiaru, to inna sprawa).

Zawsze można zrobić wskaźnik na ekwipunek, i jeżeli pusty to wiemy ze nie jest graczem, bądź nie ma nic do wypadnięcia. dużo jest możliwość, tylko zależy co się chce osiągnąć.

Hmm nie wiem po co pchać tu coś w unie. Chodziło mi by zrobił eq na normalniej tablicy, a nie na vectorze, bo tutaj mamy stały rozmiar eq(chyba, że gracz kupi większy plecak).

Kwestia CPrzedmiot. Chciał sprzedawać więc musi dodać unsigned (short - 65k ) int wartość, czy tam cena, który będzie trzymał np. wartość zakupu, a sprzedażny była by 3 razy mniejsza.

Offline Acarin1995

  • Użytkownik

# Styczeń 06, 2014, 14:34:50
A możecie podeprzeć swe propozycje kodem cpp, bo  nie zabardzo wiem jak wdrożyć wasze pomysły.

Offline ArekBal

  • Użytkownik

  • +2
# Styczeń 06, 2014, 14:47:15
A może sam spróbujesz chociaż... bo jak do teraz to nic nie pokazałeś.

Na każdym forum źle są widziani ludzie którzy oczekują że ktoś zrobi coś za nich.

Offline Acarin1995

  • Użytkownik

# Styczeń 06, 2014, 15:23:17
Popatrz kilka postwów wyżej. Poniekąd prezentuje to co zrobiłem. Jak i trochę niżej określiłem zakres wektora, bo kombinowałem samemu. Oczekuje pomocy, propozycji na zapis kodu a nie gotowca. Zrobiłem to co potrafiłem. Nie idę na gotowca poprostu się pogubiłem i pytam się jak to dalej robić.

Offline Rokuzo

  • Użytkownik
    • Masz na sprzedaż klucze do cs go?

# Styczeń 06, 2014, 16:27:30
Forum to nie code help line gdzie otrzymujesz gotowy kod dla Twoich pomysłów/problemów. Zakładając temat i pisząc posty dzielisz się swoimi opiniami, a inni swoimi.

Wszyscy już się nimi podzielili (dostałeś oczekiwanej pomocy), jesteś programistą to te pomysły wprowadź w życie, jak nie jesteś w stanie to wróć do nauki samego języka na prostszych przykładach.

A jak nie będą działały jak trzeba to napiszesz je jeszcze raz i jeszcze raz, aż uzyskasz pożądany efekt, bo to jest właśnie programowanie, szukanie optymalnych rozwiązań pewnych problemów :)
« Ostatnia zmiana: Styczeń 06, 2014, 16:30:46 wysłana przez Rokuzo »

Offline Acarin1995

  • Użytkownik

# Styczeń 06, 2014, 17:06:28
Zrobiłem tak jak radziliście.
//Ekwipunek.hpp
#ifndef _EKWIPUNEK_hpp
#define _EKWIPUNEK_hpp

#include <string>
#include <vector>
#include "Przedmiot.hpp"
class CEkwipunek
{
public:
  vector<CPrzedmiot*> plecak;
  enum slot {glowa, korpus,nogi, stopy, rekaPrawa, rekaLewa};
};

#endif
teraz nasuwa mi się pytanie jak założyc do slotu rekaPrawa Miecz?

Offline Rokuzo

  • Użytkownik
    • Masz na sprzedaż klucze do cs go?

# Styczeń 06, 2014, 17:19:33
Wiedząc, że każdy element enuma to int licząc od 0, możesz zrobić tablicę na łącznie 6 slotów (6 elementów).
CPrzedmiot *uzywane_eq[6] = {nullptr};
A następnie robisz sobie funkcje:
void uzyjSlotu(slot ktory) { uzywane_eq[ktory]->akcja(); }
A przydzielasz do slotu np. tak:
void zalozRzecz(slot ktory, CPrzedmiot *przedmiot) {
   if(przedmiot->slot == ktory) uzywane_eq[ktory] = przedmiot;
}
albo tak:
void zalozRzecz(int indeksPrzedmiotu) {
   if(indeksPrzedmiotu < plecak.size())
      uzywane_eq[plecak[indeksPrzedmiotu]->slot] = plecak[indeksPrzedmiotu];
}

Rozwiązań jest wiele :)

Btw. używaj może jakiegoś innego IDE? :)
« Ostatnia zmiana: Styczeń 06, 2014, 17:52:41 wysłana przez Rokuzo »

Offline Acarin1995

  • Użytkownik

# Styczeń 06, 2014, 17:27:40
Dzięki zaraz zobaczę jak to działa.
« Ostatnia zmiana: Styczeń 06, 2014, 18:36:16 wysłana przez Acarin1995 »

Offline Acarin1995

  • Użytkownik

# Styczeń 06, 2014, 18:41:22
kod:
//Ekwipunek.hpp
#ifndef _EKWIPUNEK_hpp
#define _EKWIPUNEK_hpp

#include <string>
#include <vector>
#include "Przedmiot.hpp"
class CEkwipunek
{
public:
  vector<CPrzedmiot*> plecak;
  enum slot {glowa, korpus, nogi, stopy, rekaPrawa, rekaLewa};
    int dodajDoEkwipunku();
    void usunzEkwipunku();
     CPrzedmiot *uzywane_eq[6] = {nullptr};
     void zalozRzecz(slot ktory, CPrzedmiot *przedmiot)
};

#endif
#include <iostream>
//ekwipunek.cpp
#include "Ekwipunek.hpp"
void CEkwipunekzalozRzecz(slot ktory, CPrzedmiot *przedmiot) {
   if(przedmiot->slot == ktory) uzywane_eq[ktory] = przedmiot;
}
int CEkwipunek::dodajDoEkwipunku()
{
short warunekSchowaj;
/*
if ( size > 0 && inventory.size() >= size ) {
cout<<"Brak miejsca w Ekipunku"<<endl;
else
}
*/
cout<<"Co chcesz Schowac? "<<endl;
cin>>warunekSchowaj;
cout<<"[1] Schowaj przedmiot z reki prawej "<<endl;
cout<<"[2] Schowaj przemiot z reki lewej "<<endl;
cout<<"[3] Schowaj przemiot z glowy"<<endl;
cout<<"[4] Schowaj przemiot z korpusu"<<endl;
cout<<"[5] Schowaj przemiot z nog"<<endl;

}

void CEkwipunek::usunzEkwipunku()
{
}

log:
Kompilator: MinGW GCC 4.7.2 32-bit Release
Building Makefile "H:\Nevermore\Ekwipunek\Makefile.win"
Wykonywanie  make...
mingw32-make.exe -f "H:\Nevermore\Ekwipunek\Makefile.win" all
g++.exe -c Ekwipunek.cpp -o Ekwipunek.o -I"C:/Program Files/Dev-Cpp/MinGW32/include" -I"C:/Program Files/Dev-Cpp/MinGW32/lib/gcc/mingw32/4.7.2/include/c++"

In file included from Ekwipunek.cpp:2:0:
Ekwipunek.hpp:15:42: warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default]

Ekwipunek.hpp:16:55: error: expected ';' at end of member declaration
Ekwipunek.hpp:15:35: error: 'nullptr' was not declared in this scope
Ekwipunek.hpp:15:42: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11 [enabled by default]
Ekwipunek.cpp:3:27: error: variable or field 'CEkwipunekzalozRzecz' declared void
Ekwipunek.cpp:3:27: error: 'slot' was not declared in this scope
Ekwipunek.cpp:3:50: error: expected primary-expression before '*' token
Ekwipunek.cpp:3:51: error: 'przedmiot' was not declared in this scope
H:\Nevermore\Ekwipunek\Makefile.win:34: recipe for target 'Ekwipunek.o' failed
mingw32-make.exe: *** [Ekwipunek.o] Error 1

Compilation failed after 2,15 seconds with errors
« Ostatnia zmiana: Styczeń 06, 2014, 18:45:01 wysłana przez Acarin1995 »