Vier gewinnt - Koordinaten verwalten (war: Array)
-
Hallo!
Sorry, aber ich glaub das ist noch etwas zu hoch für mich!

Ich habs jetzt mal versucht, allerdings funktioniert es nicht wirklich!
Hier mal mein Code:__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { xpos = ypos = 0; move_shape = false; //int gatter[5][6]; int zeilen = 6, spalten = 7, i, gatter; gatter = new int*[zeilen]; for(i=0;i<zeilen;i++) { gatter[i] = new int[spalten]; }Er bringt mir die Fehlermeldung, dass ich int** nicht nach int konvertieren kann!?
Was mach ich falsch (wahrscheinlich alles
)Danke schon mal für die Hilfe!
Gruß Elle
-
Hallo Eleonora,
Du hast Gatter als int deklariert, Gatter muß als int** deklariert werden. Außerdem solltest (mußt) Du gatter, spalten und zeilen im Header deklarieren, sonst kannst Du die Variablen nur im Konstruktor verwenden, aber nicht mehr im weiteren Programmverlauf.
Header
int Spalten, Zeilen; int** Gatter;__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { xpos = ypos = 0; move_shape = false; int zeilen = 6; spalten = 7; gatter = NULL; // vorsichtshalber, damit man überprüfen kann, ob die Erzeugung erfolgreich war gatter = new int*[zeilen]; for(int i=0;i<zeilen;i++) { gatter[i] = new int[spalten]; }
-
Hallo!
Ok, so weit funktioniert es schon mal! Nun möchte ich es allerdings auch noch verstehen und nicht nur abtippen!
Für was steht int** eigentlich? Kann nichts in der Hilfe dazu finden! Und seh ich es richtig, das ich jetzt ein Feld erstellt hab welches im Hintergrund dargestellt wird?
Stimmt das, dass ich im Destruktor nur den Inhalt lösche und nicht das Komplette Feld?
Gruß Elle
-
Hallo Eleonora,
int** ist ein Zeiger auf einen Zeiger.
Das Thema ist recht komplex und ich wüßte gar nicht, wo ich mit den Erklärungen beginnen sollte. (Davon abgesehen bin ich ein schlechter 'Erklärer'
.)
Such mal in der Hilfe nach Referenzierungs-/Dereferenzierungsoperatoren.Ich hab' hier mal ein Beispiel vorbereitet, das Dir verschiedene Zugriffsarten auf ein Array verdeutlichen soll. Dazu brauchst Du ein TStringGrid und 2 Buttons auf einem Form. Versuch mal zu nachzuvollziehen was da passiert.
Du mußt nur die beide Buttonfunktionen einfügen:void __fastcall TForm1::Button1Click(TObject *Sender) { int max_zeilen = 14; int max_spalten = 6; StringGrid1->RowCount = max_zeilen; StringGrid1->ColCount = max_spalten; // erzeugen int** DatenMatrix = new int*[max_zeilen]; for (int z = 0; z < max_zeilen; z++) DatenMatrix[z] = new int[max_spalten]; // initialisieren for (int z = 0; z < max_zeilen; z++) for (int s = 0; s < max_spalten; s++) DatenMatrix[z][s] = (z * max_spalten) + s + 1; // ausgeben for (int z = 0; z < max_zeilen; z++) for (int s = 0; s < max_spalten; s++) StringGrid1->Cells[s][z] = AnsiString(DatenMatrix[z][s]); // löschen for (int i = 0; i < max_zeilen; i++) delete[] DatenMatrix[i]; delete[] DatenMatrix; } //-------------------------------------------------------------------------- - void __fastcall TForm1::Button2Click(TObject *Sender) { int max_zeilen = 14; int max_spalten = 6; int* pZeile; int* pSpalte; int** pDatenMatrix; StringGrid1->RowCount = max_zeilen; StringGrid1->ColCount = max_spalten; // erzeugen int** DatenMatrix = new int*[max_zeilen]; for (int z = 0; z < max_zeilen; z++) DatenMatrix[z] = new int[max_spalten]; // initialisieren pDatenMatrix = DatenMatrix; for (int z = 0; z < max_zeilen; z++) { pZeile = *pDatenMatrix; for (int s = 0; s < max_spalten; s++) { pSpalte = pZeile; *pSpalte = (z * max_spalten) + s + 1; pZeile++; } pDatenMatrix++; } // ausgeben for (int i = 0; i < max_zeilen; i++) { pZeile = *(DatenMatrix + i); for (int o = 0; o < max_spalten; o++) { pSpalte = pZeile + o; StringGrid1->Cells[o][i] = *pSpalte; } } // löschen for (int i = 0; i < max_zeilen; i++) delete[] DatenMatrix[i]; delete[] DatenMatrix; } //-------------------------------------------------------------------------- -Ob Du int* DatenMatrix (int* DatenMatrix = new int[max_zeilen * max_spalten]) oder int** DatenMatrix verwendest ist eigentlich egal. Ich dachte nur, dass die Aufteilung in einzelne Zeilen leichter zu verstehen wäre (offensichtlich habe ich da geirrt, ist nicht das erste Mal
).
-
Hallo!
Erst mal danke für die Erklärung und den Code. Das mit dem StringGrid versteh ich soweit. Ich hatte bis jetzt nur keine Zeit es irgendwie bei mir einzubauen! Ich meld mich wieder wenn es nicht klappen sollte.
Danke noch mal!Gruß Eleonora
Hätte nicht gedacht, dass das für einen "Anfänger" so ein Aufwand ist!

-
Ein int array[x][y]; hätte es sicher auch getan und dir die wüste Zeigerarithmetik erspart.

-
Jansen schrieb:
Ein int array[x][y]; hätte es sicher auch getan und dir die wüste Zeigerarithmetik erspart.

Ok, ich gebe zu, war vielleicht ein bißchen hochgegriffen. Aber unter Berücksichtigung der Tatsache, dass Zugriffe mir reiner Zeigerarithmetik schneller laufen...
-
Joe_M. schrieb:
Aber unter Berücksichtigung der Tatsache, dass Zugriffe mir reiner Zeigerarithmetik schneller laufen...
Schneller als was? Der Zugriff auf ein int-Array das auf dem Stack liegt?
-junix
-
junix schrieb:
Schneller als was? Der Zugriff auf ein int-Array das auf dem Stack liegt?
... ja, wo Du das so schreibst, bekomme ich Zweifel an meiner Aussage. Ich habe morgen und übermorgen viel Arbeit, aber spätestens Freitag werde ich dafür eine kleine Testroutine schreiben.
-
Was ist, wenn die Größe des Spielfeldes erst zur Laufzeit festgelegt werden soll? Dann kann man anscheinend kein normales Array benutzen:
Header:
int x,y;irgendwo:
x = 12;
y = 13;irgendwo dahinter:
int Feld[x][y];Da kommt der Fehler, dass man nur Konstanten benutzen darf.
Oder gibt es da eine andere Möglichkeit?
-
Blackshadow schrieb:
Was ist, wenn die Größe des Spielfeldes erst zur Laufzeit festgelegt werden soll?
Da mußt Du zwangsläufig new verwenden.
Joe_M. schrieb:
...eine kleine Testroutine schreiben.
Bin doch schon dazu gekommen. Allerdings mit dem Ergebnis, dass sich bei keinerlei Perfomanceunterschiede ergeben...
// Testroutinen (nur 3 Buttons und 3 Labels auf einem Form und die 3 Variablen aus der OnCreate im Header deklarieren): void __fastcall TForm1::FormCreate(TObject *Sender) { max_zeilen = 10; max_spalten = 10; loop_count = 1000000; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { Button1->Enabled = false; int test; int start; int ende; int** DatenMatrix = new int*[max_zeilen]; for (int z = 0; z < max_zeilen; z++) DatenMatrix[z] = new int[max_spalten]; for (int z = 0; z < max_zeilen; z++) { for (int s = 0; s < max_spalten; s++) { DatenMatrix[z][s] = (z * max_spalten) + s + 1; } } start = GetTickCount(); for (int loop = 0; loop < loop_count; loop++) { for (int z = 0; z < max_zeilen; z++) for (int s = 0; s < max_spalten; s++) test = DatenMatrix[z][s]; } ende = GetTickCount(); Label1->Caption = AnsiString(ende - start); for (int i = 0; i < max_zeilen; i++) delete[] DatenMatrix[i]; delete[] DatenMatrix; Button1->Enabled = true; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { Button2->Enabled = false; int* pDatenMatrix; int test; int start; int ende; int* DatenMatrix = new int[max_zeilen * max_spalten]; pDatenMatrix = DatenMatrix; for (int z = 0; z < max_zeilen; z++) { for (int s = 0; s < max_spalten; s++) { *pDatenMatrix = (z * max_spalten) + s + 1; pDatenMatrix++; } } start = GetTickCount(); for (int loop = 0; loop < loop_count; loop++) { pDatenMatrix = DatenMatrix; for (int z = 0; z < max_zeilen; z++) { for (int s = 0; s < max_spalten; s++) { test = *pDatenMatrix; pDatenMatrix++; } } } ende = GetTickCount(); Label2->Caption = AnsiString(ende - start); delete[] DatenMatrix; Button2->Enabled = true; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button3Click(TObject *Sender) { Button3->Enabled = false; int test; int start; int ende; int DatenMatrix[10][10]; for (int z = 0; z < max_zeilen; z++) for (int s = 0; s < max_spalten; s++) DatenMatrix[z][s] = (z * max_spalten) + s + 1; start = GetTickCount(); for (int loop = 0; loop < loop_count; loop++) { for (int z = 0; z < max_zeilen; z++) { for (int s = 0; s < max_spalten; s++) { test = DatenMatrix[z][s]; } } } ende = GetTickCount(); Label3->Caption = AnsiString(ende - start); Button3->Enabled = true; } //---------------------------------------------------------------------------Vielleicht ist dieses Testszenario auch einfach nicht geeignet um die Performance zu testen... Irgendwelche Anregungen oder Erklärungen, junix?
EDIT:
Ich habe das jetzt mal mit QueryPerformance Counter gemessen:LARGE_INTEGER start, ende, frequenz; start.QuadPart = 0; ende.QuadPart = 0; QueryPerformanceFrequency(&frequenz); QueryPerformanceCounter(&start); // ein Schleifendurchlauf QueryPerformanceCounter(&ende); LabelX->Caption = AnsiString(((double) ende.QuadPart - (double) start.QuadPart) / (double) frequenz.QuadPart);Hierbei ergibt sich das (von mir) erwartete Bild. Die Methode unter Button1 ist schneller. Ergebnisse (AMD Athon XP 2400, Array 1500 * 500, 1 Schleifendurchlauf):
Button1: 0,0007615...
Button2: 0,0011317...
Button3: 0,0011317...
Die Ergebnisse variieren bei jedem Durchlauf etwas, aber die Relation bleibt idenntisch. Offensichtlich ist GetTickCount nicht genau genug.