Array an Funktion übergeben



  • Guten Morgen zusammen,

    ist es möglich ein 3-dim Array als Kopie an eine Funktion zu übergeben?

    Mit Kopie meine ich, dass das Array in der Funktion die selben Werte hat wie das übergebene Array, das übergebene Array jedoch nicht verändert wird, wenn das Array in der Funktion geändert wird.

    Hoffe es ist einigermaßen verständlich.



  • Pack das Array in eine struct. Der Compiler-generierte Kopierkonstruktor macht genau das, was du möchtest. Stattdessen kannst du auch einfach std::vector nehmen. Rohe Arrays sind in den meisten Fällen falsch.



  • Ich glaube nicht, das eine struct oder ein vector mir hilft.

    Zur Erklärung: Ich programmier gerade Schach, dazu habe ich ein 3-Dim Array mit [2][16][3]. In diesem Array speicher ich die Figuren der jeweiligen Farbe ab mit den Infos wo sie sind und was für eine Figur sie sind.

    Zum Überprüfen ob das Spiel vorbei ist, muss ich jeden möglichen Zug jeder Figur überprüfen, dafür will ich diesen Arrray an eine Funktion übergeben, die genau das tut. Um zu verhindern das die wirklichen Daten des Array überschrieben werden, sondern eben nur eine Kopie übergeben werden.



  • Falls Du schon TR1 oder C++2011 Features nutzen kannst und willst, ist std::array<double,3> (bzw std::tr1::array<double,3>) das richtige. Dieses Ding verhält sich im Gegensatz zu "build-in arrays" regulär und kann wie ints und doubles auch "per value" (als Kopie) übergeben werden. Eine gute Implementierung von std::array bietet Dir im Library-Debug-Modus auch Indexprüfungen und co an.



  • Tal Ker schrieb:

    Ich glaube nicht, das eine struct oder ein vector mir hilft.

    Programmierung hat relativ wenig mit glauben zu tun, auch wenn viele Leute immer wieder in die Falle tappen, dass sie denken, ihr Code wäre richtig, wenn sie nur fest genug daran glauben.
    Wenn du statt des "losen" Arrays das Array in einem struct hälst und das per value (=per Kopie) übergibst, wird es perfekt kopiert. Wenn du an Stelle des Arrays einen std::vector oder (std[::tr1]|boost)1::array benutzt, läuft die auch so wie man es erwarten kann.
    Wenns nur darum geht, dass die Daten in der Funktion nicht verändert werden dürfen wie in deinem Fall, wäre ein const-Referenz wohl das passendste.

    ____________________
    1 tr1 = Technical Report von 2003, std = C++0x-Standard, boost = Boost C++ Libraries für Standard-C++98/03



  • Vielleicht solltest du dich noch mal den Grundlagen der Parameterübergabe vertraut machen. Hier mal ein Link für den Anfang:
    Übergabe der Argumente
    Gruß



  • Wie man schon gesagt hat, sollst du (praktisch) nie rohe Arrays verwenden. Das Mindeste ist noch ein struct drumherum. Wieso nutzt du nicht die bereits vorgeschlagenen Container? Mit konstanter Grösse nutzt du ein std::tr1::array oder wenn du Technical Report 1 noch nicht hast eben boost::array , welches die ursprüngliche Version ist. Mit variabler nimmst du den std::vector .



  • Dann haben wir hier ein gutes Beispiel für std::array. Ich nehme an, du verwendest Visual Studio. Include den <array> Header, in dem Befindet sich std::array. std::array ist ein Wrapper für ein rohes Array, du kannst std::array auch wie eines verwenden. Du kannst mit dem Index-Operator auf Elemente zugreifen, durchiterieren, allerdings ist es kopierbar und kennt seine Größe.

    Dein Spielfeld würde ich dann als

    std::array<std::array<Spielfigur, 8>, 8>; // Entspricht Spielfigur[8][8]
    

    repräsentieren. (Allerdings würde ich das noch in eine Klasse "Spiel" packen.)

    Übrigens: Ich weiß nicht, was du da machst, aber wozu möchtest du das Array ändern, wenn du auf Schach prüfen willst?

    Es gibt verschiedene Vorgehensweisen, ein Schach Matt zu überprüfen.

    Ich würde zuerst prüfen, ob der König überhaupt im Schach ist. Dann würde ich alle freien Randfelder prüfen. Ist man auf jedem Randfeld im Schach, so ist das Spiel zu Ende.

    Ob ein Feld im Schach ist, ist auch relativ einfach. Prüfe, ob in den Diagonalen ein Läufer oder eine Dame steht. Für die Gerade überprüfst du auf Türme oder Damen. Für Springer gibt es pro Feld 8 mögliche Positionen. Dann sollte noch ein Königs-Check auf benachbarte Felder her, um Matt Situtationen prüfen zu können. Für Bauern musst du die relative Position zu den Bauern beachten, das sollte allerdings auch recht einfach sein.

    Message angekommen? Du musst hier nirgens etwas verändern.



  • Erst einmal danke für die ganzen infos.

    Weil ich noch ein Anfänger im Programmieren bin ist mir OOP noch ein bisschen suspekt.

    314159265358979 schrieb:

    Ich nehme an, du verwendest Visual Studio.

    Stimmt

    314159265358979 schrieb:

    std::array<std::array<Spielfigur, 8>, 8>; // Entspricht Spielfigur[8][8]
    

    Wo gebe ich den Namen des Arrays an? Immer im tiefsten geschachtelten?

    314159265358979 schrieb:

    Ich würde zuerst prüfen, ob der König überhaupt im Schach ist.

    Tu ich ja auch

    314159265358979 schrieb:

    Dann würde ich alle freien Randfelder prüfen. Ist man auf jedem Randfeld im Schach, so ist das Spiel zu Ende.

    Nein, weil das die Figur ungedeckt vor dem König stehen könnte, oder nur über eine Senkrechte, oder nur über eine Waagrechte oder nur über eine Diagonale Schach gegeben werden könnte.

    314159265358979 schrieb:

    Ob ein Feld im Schach ist, ist auch relativ einfach.

    Stimmt, ist ja auch nicht das Problem.

    314159265358979 schrieb:

    Message angekommen? Du musst hier nirgens etwas verändern.

    Doch, ich muss prüfen ob es einen möglichen Zug gibt der das Schach aufhebt, sei es durch schlagen der Schachgebenden Figur, durch wegziehen des Königs, oder durch Ziehen einer anderen Figur vor den König, wenn es ihn nicht gibt ist Matt.

    und um das zu überprüfen, übergebe ich den array an eine Funktion, die mir die x und y werte für jeden gültigen Zug sucht, in den Array schreibt und dann an eine Funktion übergibt, die testet ob mit diesen neuen Werten immer noch schach gegeben wird.

    Nochmals zur Verdeutlichung: In diesem Array steht nicht das Spielfeld, sondern jede der 32 Figuren, mit ihrer aktuellen Position und welche figur es ist (Bauer, Turm, Springer, Läufer, Dame, König)



  • Ich hab mal wieder zu wenig nachgedacht *schäm*
    Ich hab den Namen beim Array vergessen, ich meinte natürlich:

    std::array<std::array<Spielfigur, 8>, 8> spielfeld;
    


  • 314159265358979 schrieb:

    Ich hab den Namen beim Array vergessen, ich meinte natürlich:

    std::array<std::array<Spielfigur, 8>, 8> spielfeld;
    

    Für was steht Spielfigur?



  • Eine Klasse, die du schreiben kannst/solltest 😉



  • Tal Ker schrieb:

    314159265358979 schrieb:

    Ich hab den Namen beim Array vergessen, ich meinte natürlich:

    std::array<std::array<Spielfigur, 8>, 8> spielfeld;
    

    Für was steht Spielfigur?

    std::array<Spielfigur,8> arr; //definiert ein array-Objekt mit 8 Elementen vom Typ Spielfigur.
    std::array<std::array<Spielfigur,8>, 8> arr2; //definiert ein array-Objekt mit 8 Elementen vom Typ std::array<Spielfigur, 8>
    


  • Tachyon schrieb:

    std::array<Spielfigur,8> arr; //definiert ein array-Objekt mit 8 Elementen vom Typ Spielfigur.
    std::array<std::array<Spielfigur,8>, 8> arr2; //definiert ein array-Objekt mit 8 Elementen vom Typ std::array<Spielfigur, 8>
    

    Danke und wenn ich den Typ Spielfigur nicht habe?
    Dann so

    std::array<std::array<std::array<3>, 16>,2>
    

    ?



  • Dann bastelst du ihn dir :p



  • Und wie? Als struct von einem int oder wie? 🙂



  • struct Spielfigur
    {
        Spielerfarme farbe;
        Figurtyp type;
    };
    

    Würde schon ausreichen und deinen Code vereinfachen sowie verständlicher machen. 😉



  • Tal Ker schrieb:

    Zur Erklärung: Ich programmier gerade Schach, dazu habe ich ein 3-Dim Array mit [2][16][3]. In diesem Array speicher ich die Figuren der jeweiligen Farbe ab mit den Infos wo sie sind und was für eine Figur sie sind.

    Wo kommen Deine Figuren denn her? Was ist der Elementtyp von Deinem Array[2][16][3]?



  • Nicht, wenn ich abwechselnd spielen lasse und die farbe über eine bool steuere, also

    bool bfarbe = 0; //0 = weiß, 1 = schwarz
    figuren[bfarbe][zu ziehende figur][typ der figur];
    

    Das Array ist ein int.

    Die Figuren werden am Spielanfang mit der Grundaufstellung initialisiert.
    Die weißen so:

    array[0][0][0] = 0; //Spielfigur ist ein Bauer
    array[0][0][1] = 0; //Bauer hat die x-Koordinate 0
    array[0][0][2] = 1; //Bauer hat die y-Koordinate 1
    array[0][1][0] = 0; //Spielfigur ist ein Bauer
    ...
    array[0][8][0] = 1; //Spielfigur ist ein Turm
    array[0][8][1] = 0; //Turm hat die x-Koordinate 0
    array[0][8][2] = 0; //Turm hat die y-Koordinate 0
    

    und die schwarzen so:

    array[0][0][0] = 0; //Spielfigur ist ein Bauer
    array[1][0][1] = 0; //Bauer hat die x-Koordinate 0
    array[1][0][2] = 6; //Bauer hat die y-Koordinate 6
    array[1][1][0] = 0; //Spielfigur ist ein Bauer
    ...
    array[1][8][0] = 1; //Spielfigur ist ein Turm
    array[1][8][1] = 0; //Turm hat die x-Koordinate 0
    array[1][8][2] = 7; //Turm hat die y-Koordinate 7
    


  • Tal Ker schrieb:

    Nicht, wenn ich abwechselnd spielen lasse und die farbe über eine bool steuere, also

    bool bfarbe = 0; //0 = weiß, 1 = schwarz
    figuren[bfarbe][zu ziehende figur][typ der figur];
    

    Das Array ist ein int.

    Ein bischen umständlich.

    Vielleicht wäre es besser, eine Klasse Feld zu haben, welche Deine Spielfelder kennzeichnet. Dann hättest Du ein Array Felder felder[8][8] . Die Klasse Feld hätte dann vielleicht sinnvollerweise ein Attribut Figur. Figur wäre dabei eine weitere Klasse. So wäre das ganze vielleicht etwas besser zu handhaben.


Log in to reply