Unverständliches Problem



  • Ja, ich habe jetzt auch eine Klasse "Inventory".
    Darf ich meinen gesamten Code hier posten, oder liest das sowieso keiner?

    Ich würde nämlich gerne wissen, ob ich es (halbwegs) richtig gemacht habe.

    (Funktionieren tut es ;))



  • darfst du ruhig posten .....
    lesen tuts auf jedenfall einer....

    Mfg Shade37337



  • Jedenfalls habe ich eine Frage, und zwar möchte ich einer Memberfunktion "addItem()" einen Parameter übergeben, und zwar das jeweilige Item.
    Nur in slots[] kann ich keinen Zeiger vom Typ Slot speichern, da slots[] ein Klassenarray von Slot ist.
    Jetzt weiß ich nicht, wie ich das machen soll.
    Hier mal die Codes:

    main.cpp

    //***INCLUDES***//
    #include "main.h"
    
    //***MAIN FUNCTION***//
    void main()
    {	
    	inventory.addItem();
    	init();
    	mainMenu();
    }
    

    main .h

    #ifndef _MAIN_H_
    #define _MAIN_H_
    
    //***INCLUDES***//
    #include "functions.h"
    
    #endif _MAIN_H_
    

    functions.cpp

    //***INCLUDES***//
    #include "functions.h"
    
    //***FUNCTIONS***//
    void init()
    {
    	std::cout << "* * * T E X T   A D V E N T U R E * * *" << std::endl << std::endl;
    	std::cout << "Wie soll der Held heissen?" << std::endl << std::endl;
    
    	std::string name;
    	std::cin >> name;
    
    	player.nameMe(name);
    
    	std::cout << std::endl << "Willkommen, " << player.name << "!" << std::endl;
    
    	CLS;
    }
    
    void mainMenu()
    {
    	CLS;
    	std::cout << "* * * H A U P T M E N U E * * *" << std::endl << std::endl;
    	std::cout << "<S> STATUS" << std::endl;
    	std::cout << "<I> INVENTAR" << std::endl;
    	std::cout << "<H> HAENDLER" << std::endl;
    	std::cout << "<B> BEENDEN" << std::endl;
    
    	char operation;
    	std::cin >> operation;
    
    	switch(operation)
    	{
    	case 'S':
    	case 's':
    		showStatus();
    		break;
    	case 'I':
    	case 'i':
    		showInventory();
    		break;
    	case 'H':
    	case 'h':
    		showTrade();
    		break;
    	case 'B':
    	case 'b':
    		endGame();
    		break;
    	default:
    		std::cout << "Ungueltige Eingabe. Wiederholen!" << std::endl;
    		Sleep(1000);
    		mainMenu();
    		break;
    	}
    }
    
    void endGame()
    {
    	CLS;
    }
    
    void showStatus()
    {
    	CLS;
    	std::cout << "* * * " << player.name << " * * *" << std::endl << std::endl;
    	std::cout << "Gesundheit: " << player.health_min << " / " << player.health_max << std::endl;
    	std::cout << "Mana: " << player.mana_min << " / " << player.mana_max << std::endl << std::endl;
    	std::cout << "Gold: " << player.gold << std::endl;
    	std::cout << "<Z> ZURUECK" << std::endl;
    
    	char operation;
    	std::cin >> operation;
    
    	switch(operation)
    	{
    	default:
    		mainMenu();
    		break;
    	}
    }
    
    void showInventory()
    {
    	CLS;
    	player.health_min = 0;
    	std::cout << "* * * I N V E N T A R * * *" << std::endl << std::endl;
    	std::cout << "1. Slot: " << inventory.slots[0]->getName() << std::endl;
    	std::cout << "2. Slot: " << inventory.slots[1]->getName() << std::endl;
    	std::cout << "3. Slot: " << inventory.slots[2]->getName() << std::endl;
    	std::cout << "4. Slot: " << inventory.slots[3]->getName() << std::endl;
    	std::cout << "5. Slot: " << inventory.slots[4]->getName() << std::endl << std::endl;
    	std::cout << "<T> TESTADD" << std::endl;
    	std::cout << "<B> BENUETZEN" << std::endl;
    	std::cout << "<Z> ZURUECK" << std::endl;
    
    	char operation;
    	short slot;
    	std::cin >> operation;
    
    	switch(operation)
    	{
    	case 'T':
    	case 't':
    		if(inventory.addItem())
    			std::cout << "Hinzugefuegt!" << std::endl;
    		else
    			std::cout << "Inventar voll!" << std::endl;
    		Sleep(1000);
    		showInventory();
    	case 'B':
    	case 'b':
    		std::cout << "Slot: " << std::endl;
    		std::cin >> slot;
    		if(inventory.useItem(slot-1))
    			std::cout << "Gegenstand in Slot " << slot << " wurde benutzt!" << std::endl;
    		else
    			std::cout << "Gegenstand in Slot " << slot << " wurde nicht benutzt!" << std::endl;
    		Sleep(1000);
    		showInventory();
    	default:
    		mainMenu();
    		break;
    	}	
    }
    
    void showTrade()
    {
    	CLS;
    	std::cout << "* * * HANDEL * * *" <<std::endl << std::endl;
    }
    

    functions.h

    #ifndef _FUNCTIONS_H_
    #define _FUNCTIONS_H_
    
    //***INCLUDES***//
    #include <iostream>
    #include <windows.h>
    #include "Player.h"
    #include "Inventory.h"
    
    //***MACROS***//
    #define CLS system("CLS")
    #define BLUE SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0009);
    #define BLUELINE SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0011);
    #define NORMAL SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0007);
    #define GREY SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0008);
    #define GOLD SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0006);
    #define TURK SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0003);
    #define GREEN SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0002);
    
    //***FUNCTIONS***//
    void init();
    void mainMenu();
    void endGame();
    void showStatus();
    void showInventory();
    void showTrade();
    
    #endif _FUNCTIONS_H_
    

    Player.cpp

    //***INCLUDES***//
    #include "Player.h"
    
    //***GLOBAL***//
    Player player;
    
    //***CLASS PLAYER***//
    Player::Player()
    {
    	health_min = 50;
    	health_max = 100;
    	mana_min = 50;
    	mana_max = 50;
    	gold = 100;
    	slots = (5 - 1);
    }
    
    void Player::nameMe(std::string n)
    {
    	name = n;
    }
    
    void Player::addHealth(short health)
    {
    	health_min += health;
    	if(health_min > health_max)
    		health_min = health_max;
    }
    
    void Player::addMana(short mana)
    {
    	mana_min += mana;
    	if(mana_min > mana_max)
    		mana_min = mana_max;
    }
    

    Player.h

    #ifndef _PLAYER_H_
    #define _PLAYER_H_
    
    //***INCLUDES***//
    #include <string>
    
    //***CLASS Player***//
    class Player
    {
    public:
    	Player();
    	void nameMe(std::string);
    	void addHealth(short);
    	void addMana(short);
    
    	std::string name;
    	int health_min, health_max;
    	int mana_min, mana_max;
    	unsigned gold;
    	unsigned short slots;
    }; extern Player player;
    
    #endif _PLAYER_H_
    

    items.cpp

    //***INCLUDES***//
    #include "Items.h"
    
    //***CLASS Slot***//
    Slot::Slot()
    {
    	;
    }
    Slot::~Slot()
    {
    	;
    }
    
    //***CLASS Empty***//
    Empty::Empty()
    {
    	name = "Leer";
    }
    Empty::~Empty()
    {
    	;
    }
    
    bool Empty::use()
    {
    	return false;
    }
    std::string Empty::getName()
    {
    	return name;
    }
    bool Empty::isFull()
    {
    	return false;
    }
    
    //***ITEM CLASSES***//
    LightPotion::LightPotion()
    {
    	name = "Leichter Heiltrank";
    }
    LightPotion::~LightPotion()
    {
    	;
    }
    
    bool LightPotion::use()
    {
    	if(player.health_min == player.health_max)
    	{
    		return false;
    	}
    	else
    	{
    		player.addHealth(50);
    		return true;
    	}
    }
    std::string LightPotion::getName()
    {
    	return name;
    }
    bool LightPotion::isFull()
    {
    	return true;
    }
    

    items.h

    #ifndef _ITEMS_H_
    #define _ITEMS_H_
    
    //***INCLUDES***//
    #include "Player.h"
    
    //***CLASS Slot***//
    class Slot
    {
    public:
    	Slot();
    	~Slot();
    
    	virtual bool use() = 0;
    	virtual std::string getName() = 0;
    	virtual bool isFull() = 0;
    };
    
    //***CLASS Empty***//
    class Empty : public Slot
    {
    public:
    	Empty();
    	~Empty();
    
    	bool use();
    	std::string getName();
    	bool isFull();
    
    	std::string name;
    };
    
    //***ITEM CLASSES***//
    class LightPotion : public Slot
    {
    public:
    	LightPotion();
    	~LightPotion();
    
    	bool use();
    	std::string getName();
    	bool isFull();
    
    	std::string name;
    };
    
    #endif _ITEMS_H_
    

    inventory.cpp

    //***INCLUDES***//
    #include "Inventory.h"
    
    //***GLOBAL***//
    Inventory inventory;
    
    //***CLASS Inventory***//
    Inventory::Inventory()
    {
    	empty = new Empty;
    
    	slots = new Slot*[player.slots];
    	slots[0] = empty;
    	slots[1] = empty;
    	slots[2] = empty;
    	slots[3] = empty;
    	slots[4] = empty;
    
    	lightpotion = new LightPotion;
    }
    Inventory::~Inventory()
    {
    	delete slots;
    	delete empty;
    
    	delete lightpotion;
    }
    
    bool Inventory::addItem()
    {
    	for(int c = 0; c <= 4; c++)
    	{
    		if(slots[c]->isFull())
    			continue;
    		else
    		{
    			slots[c] = lightpotion;
    			return true;
    		}
    	}
    
    	return false;
    }
    bool Inventory::useItem(short slot)
    {
    	if(slots[slot]->use())
    	{
    		slots[slot] = empty;
    		return true;
    	}
    	else
    		return false;
    }
    

    inventory.h

    #ifndef _INVENTORY_H_
    #define _INVENTORY_H_
    
    //***INCLUDES***//
    #include "Items.h"
    
    //***CLASS Inventory***//
    class Inventory
    {
    public:
    	Inventory();
    	~Inventory();
    
    	bool addItem();
    	bool useItem(short);
    
    	Slot** slots;
    	Empty* empty;
    
    	LightPotion* lightpotion;
    }; extern Inventory inventory;
    
    #endif _INVENTORY_H_
    

    Ich weiß, einiges ist noch zu verbessern.
    Zum Beispiel weiß ich nicht, wie ich statt einer Funktion isFull() nur ein Flag verwende, weil eine Variable kann ich nicht mit slots[]-> ansprechen, nur eine Funktion.

    Bin für alle Tipps dankbar 🙂

    (Beim Aufruf von showInventory() wird player.health_min deshalb auf 0 gesetzt, damit man immer use() verwenden kann [geht nur, wenn player.health_min < player.health_max]und somit das System testen kann)



  • also.. ich hab deinen code noch nicht ganz gelesen aber :
    verwende referenzen und std::vector oder ähnliches und keine zeiger und arrays...
    mit denen handelst du dir nur bufferoverflows ein

    Mfg Shade37337



  • Ja, wenn ich es gelernt habe. Bis jetzt habe ich noch nicht einmal über Klassen gelernt und vererbe schon, also bin ich daweil stolz auf mich 🙂

    Wenn ich dazulerne, werde ich auch versuchen, den Code zu optimieren.
    Ich finde man lernt am besten, wenn man probiert...



  • und noch etwas, member von klassen macht man Gewöhnlich private oder protected, damit eben soetwas:

    std::cout << "* * * " << player.name << " * * *" << std::endl << std::endl;
    

    nicht funktionieren sollte!

    man schreibt für soetwas eigentlich Methoden (Get Set Methoden), für den name die könnte so aussehen:

    string GetName()const
    {
     return name;
    }
    

    denn es sollte verhindert werden, das "unbefugte" auf die member zugreifen könnten!

    so, ich les mir später dann noch weiter durch 😉



  • Hier noch mal ein paar weitere Anmerkungen:

    - Der Rückgabetyp von main() ist int nicht void!

    - Finger weg von dem #define - Krempel. Dazu gibt es in C++ inline.

    - Wie schon gesagt, für das Array besser einen std::vector nehmen. Wenn man nicht ganz genau weiß, was man tut, kann man bei von Hand verwalteten Arrays fürchterlich viel falsch machen (in deinem Code ist z.B. einer der delete-Aufrufe falsch).

    - Die ganzen losen Funktionen gefallen mir nicht. Das schreit doch geradezu danach eine Klasse (Game) daraus zu machen.

    - Das Inventar gehört doch sicherlich zum Spieler, oder? Also sollte die Klasse Player neben Dingen wie Gold oder Mana auch ein Inventory haben.

    class Player
    {
    public:
        Player();
        void nameMe(std::string);
        void addHealth(short);
        void addMana(short);
    
    private:
        std::string name;
        int health_min, health_max;
        int mana_min, mana_max;
        unsigned gold;
        unsigned short slots;
        Inventory inventory;
    };
    


  • Ich habe Inventory einfach extern definiert.
    Weil ich brauche ja nur eine einzige Instanz von Inventory.



  • Solange du nur einen Spieler hast, ja. Aber eventuell willst du das Spiel irgendwann für Team-Play erweitern (oder die NPC's sollen auch in der LAge sein, Items einzusammeln und mitzuschleppen) - dann braucht doch wieder jeder Charakter sein eigenes Inventory.



  • Und selbst wenn nicht ist extern (global) IMHO die am wenigsten Elegante Lösung des Problems 😉



  • Danke für die vielen Tipps!

    Am besten gehe ich mein C++ Buch weiter durch, denn gleich an ein Projekt mit mehreren Klassen usw. zu wagen halte ich ja doch nicht für sinnvoll 😉

    MfG


Anmelden zum Antworten