Objekte ohne Namen erstellen?



  • Hallo,

    Ich habe ich gefragt, ob man Objekte auch ohne Objektnamen erstellen kann.
    Beispiel:

    Ich möchte in einem Spiel 100 Gegner erscheinen lassen...
    Dann möchte ich ja nicht in meinem Code schreiben:

    Gegner g1;
    Gegner g2;
    ...
    Gegner g100;

    Ich möchte also viele Objekte mit einer Schleife erstellen, ohne jeden einzelnen einen Namen zu geben. (natürlich bekommen sie über den Konstruktor dann eine ID)

    Könnt ihr mich erklären wie man das geschickter löst? Oder eventuell ein Stichwort geben, über das ich mich informieren kann?



  • Hallo Haolong

    Das Stichwort ist "Array":

    Enemy enemies[100]; // erstelle 100 Gegner mit den Indizes 0 bis 99 inklusive
    enemies[3].attack(); // der vierte (!) Gegner soll angreifen
    

    Die ID, die dir vorgeschwebt hat, ist hinfällig; der Index (=Platznummer) reicht zur Identifikation aus.

    Wenn du dann etwas für alle 100 Gegner machen möchtest, nutzt du eine Schleife:

    for(int i = 0; i < 100; ++i)
        enemies[i].revive();
    

    LG

    PS: Ich würde dir empfehlen, alle Namen auf Englisch zu machen.



  • Fytch schrieb:

    Das Stichwort ist "Array":

    Ich würde eher auf das Stichwort std::vector verweisen. Die Anzahl der Gegner ist ja nicht fest, dann kannst du bei Bedarf mehr oder weniger Gegner haben.



  • Danke schon mal für die Hilfen aber irgendwie klappt das noch nicht ganz so wie ich möchte.

    Zu meinem Fall:

    Ich versuche ein Schachspiel zu programmieren. Dafür habe ich zwei Klassen erstellt.

    -Schachfeld
    -Position

    Das Schachfeld soll in einem Array(oder auch Vector) alle 64 Positionen (Kacheln) gespeichert haben.

    Durch eine Abfrage von statischen Variablen der Klasse Position bekommt jede Position im Konstruktor einen x-Wert und einen y-Wert zugewiesen.

    Im Versuch mit dem Array sah das Ganze dann so aus:

    //Spielfeld.cpp
    #include "Spielfeld.h"
    
    Spielfeld::Spielfeld()
    {
    }
    
    Spielfeld::~Spielfeld()
    {
    }
    
    //Spielfeld.h
    #pragma once
    
    class Spielfeld
    {
    public:
    	Position Positionen[64];
    
    	Spielfeld();
    	~Spielfeld();
    };
    
    //Position.cpp
    #include "Position.h"
    
    Position::Position()
    {
    	pos_x = counter_x;
    	pos_y = counter_y;
    
    	if (counter_x <= 6)
    	{
    		counter_x++;
    	}
    	else {
    		counter_x = 0;
    		counter_y++;
    	}
    
    }
    
    Position::~Position()
    {
    }
    
    int Position::getPos_x()
    {
    	return pos_x;
    }
    
    int Position::getPos_y()
    {
    	return pos_y;
    }
    
    int Position::counter_x = 0;
    int Position::counter_y = 0;
    
    //Position.h
    #pragma once
    class Position
    {
    private:
    	static int counter_x;
    	static int counter_y;
    
    	int pos_x;
    	int pos_y;
    public:
    
    	Position();
    	~Position();
    
    	int getPos_x();
    	int getPos_y();
    };
    

    Erstelle ich damit schon die Objekte? Ich glaube nicht, denn der Konstruktor von Position wird nicht aufgerufen.

    Was fehlt mir denn dafür noch?



  • Das passt schon so, vermutlich fehlt dir schlicht ein Schachfeld-Objekt.

    Und bitte keine Destruktoren explizit anlegen, wenn du sie nicht brauchst. Was die static pos_x/pos_y bezwecken sollen, ist mir auch nicht ganz klar.



  • Danke schon mal für die Hilfen aber irgendwie klappt das noch nicht ganz so wie ich möchte.

    du machst das viel zu kompliziert

    //8x8=64 Felder
    constexpr size_t MAX_X = 8;
    constexpr size_t MAX_Y = 8;
    

    entweder

    position spielfed[MAX_X][MAX_Y]
    

    und dann einfach

    positon& pos = spielfeld[3][4];
    

    oder

    position spielfed[MAX_X*MAX_Y];
    
    position& get_position(x,y)
    {
      assert(x >= 0 && x < MAX_X);
      assert(y >= 0 && y < MAX_Y);
    
      return fields[y*MAX_Y+x];
    }
    

    das ganz geht auch mit vector - falls du dynamische Spielfeldgroessen haben willst?

    std::vector<std::vector<position>> spielfeld(MAX_X, std::vector<position>(MAX_Y));
    

    und dann auch wieder

    position& pos = spielfeld[3][4];
    

    dein static Zeug ist total sinnfrei und nutzlos - du löst mit viel Code ein Problem das gar nicht existiert technisch besonders umständlich



  • Ich würde ein std::array<std::array<Feldinfo, 8>, 8> als Schachbrett nehmen.
    Und Feldinfo wäre eine Enumeration, in der empty vorkommt und jede Figur.
    Dann könnte man Funktionen mit Templatespezialisierung nutzen, um mit den Feldinfos zu arbeiten.



  • Dann könnte man Funktionen mit Templatespezialisierung nutzen, um mit den Feldinfos zu arbeiten.

    was auch immer du damit sagen möchtest - Beispiel?



  • Bin gerade am Handy, tut mir leid. Später, ok?



  • Das mit dem Schachspiel ist so eine typische Interviewfrage: man sollte es besser nicht zu kompliziert machen!

    Ich möchte hier ein einfaches 1d-Array vorschlagen. Und zwar, wie wir es hier vor kurzem in einem anderen Thread hatten, würde ich "oben" und "unten" je 2 Extrazeilen mit ungültigen Feldern einfügen und links und rechts vom Feld je eine zusätzliche Spalte, d.h. in 1d hat man dann erst 2x10=20 ungültige Felder, dann noch 1 ungültiges Feld am Rand, dann, 8 gültige, wieder 2 ungültige usw.

    So sähe das Brett so aus:

    uuuuuuuuuu
    uuuuuuuuuu
    uRNBQKBNRu
    uPPPPPPPPu
    u--------u
    u--------u
    u--------u
    u--------u
    uppppppppu
    urnbqkbnru
    uuuuuuuuuu
    uuuuuuuuuu
    

    Mit Großbuchstaben=Schwarze Figuren, u=ungültig, -=leer, Kleinbuchstaben=weiß

    Insgesamt also 120 Felder als 1d-Array. Vorteil dieser Darstellung ist, dass man z.B. Springerbewegungen durch eine einzige Addition oder Subtraktion darstellen kann, und der Test, ob der Zug überhaupt geht, ist dann einfach, dass das Feld != u sein muss (ok, man muss dann noch testen, ob der König dadurch im Schach stehen würde). Bei Turm und Läufer hat man je 4 Richtungen und man addiert/subtrahiert einfach so lange, bis man auf eine Figur oder den Rand (u) trifft.

    Ich weiß nicht, wie das in modernen Schachprogrammen implementiert ist, aber ich denke, dass dies ein brauchbarer Ansatz wäre. Viel schwieriger als die erlaubten Züge zu finden ist es sowieso, eine anständige Bewertungsfunktion zu schreiben sowie wahrscheinlich gute Züge in der Suche möglichst als erstes zu finden.



  • wob schrieb:

    Ich weiß nicht, wie das in modernen Schachprogrammen implementiert ist, aber ich denke, dass dies ein brauchbarer Ansatz wäre. Viel schwieriger als die erlaubten Züge zu finden ist es sowieso, eine anständige Bewertungsfunktion zu schreiben sowie wahrscheinlich gute Züge in der Suche möglichst als erstes zu finden.

    Die führenden Schachprogramme heutzutage nutzen ausschließlich Bitboards (= std::uint64_t ). Dabei macht man sich zunutze, dass die 64 Felder eines Schachbretts gerade schön in ein Register eines x86_64-Prozessors passen. Man nutzt je ein Bitboard pro Figurentyp und eins für Schwarz (Läufer & Schwarz == SchwarzeLäufer).


Log in to reply