2017-03-12 7 views
1

Ich habe Schwierigkeiten, herauszufinden, wie ich mein Array korrekt einrichten kann.Einrichten eines multidimensionalen Arrays ohne Datenduplikation

Ich habe eine grundlegende Reihe von Fliesen auf meinem Array grid[,] eingestellt das funktioniert gut.

Jetzt versuche ich ein Array für meine Kanten zwischen den Gittern zu machen, so dass ich Wände ablegen kann.

Also ich habe dies: walls[,][,] wo jede [,] ist eine Rasterposition, damit jede Wand 2 Rasterpositionen trennt.

Das Ende Ziel ist es, dass ich eine Wand Array mit zwei Gitterpunkten sagen A wollen und B, so dass ich dann tun:

Wall wallObject = walls[A.x,A.y][B.x,B.y];

Hoffnung, die Sinn macht. Ich habe versucht, so etwas wie dies zu tun:

' Jetzt, da jede 1 Kachel 4 Wände haben kann ich versucht, meine Wand Array wie dies einzurichten, konnte aber die Syntax richtig es nicht funktioniert tun:

grids = new Tile[x,y]; 
walls = new Wall[grids.GetLength(0), grids.GetLength(1)][walls.GetLength(0) * 4, walls.GetLength(1) * 4]; // invalid rank specifier ERROR 

for(int i = 0; i < x; i++) { 
for(int j = 0; j < y; j++) { 

    grids[i, j] = new Tile(new Vector3(i, 0, j)); 
    foreach (Vector3 gridNeighbour in AdjacentTiles(new Vector3(i, 0, j))) //4 directions 
    { 
     if (!InGrid(gridNeighbour)) continue;  
     walls[i, j][(int)gridNeighbour.x, (int)gridNeighbour.z] = new Wall(grid[i,j],grid[(int)gridNeighbour.x,(int)gridNeighbour.z]); 
    } 

}} 

Ich bekomme einen Fehler in der zweiten Zeile nicht sicher, der richtige Weg, um es zu schreiben. Ich bin auch ziemlich sicher, dass meine Logik falsch ist, da dieses Datensetup mir doppelte Daten für meine Wände geben würde, so dass ich wall[gridA][gridB] und wall[gridB][gridA] bekommen würde, was ich gerne vermeiden würde, aber ich weiß nicht wie.

+0

Ich glaube wirklich nicht, dass Sie ein 4-dimensionales Array dafür benötigen, vorausgesetzt, dass ich Sie richtig verstehe. Wenn ich nicht bin, können Sie besser erklären, warum Sie ein 4-dimensionales Array benötigen? – Unlocked

+0

Eine gegebene Wand trennt zwei Kacheln "A" und "B". Wenn ich also eine Wand finden möchte, die zwei bestimmte Kacheln trennt, war die Idee, sie wie 'Wände [Ax, Ay] [Bx, By]' aus dem Array zu holen Hoffnung, die Sinn macht. Ich nahm an, dass ich diese Art von Array-Struktur benötigen würde, um es zu tun. – Sir

Antwort

1

Wenn Sie Ihre Frage direkt beantworten, besteht das grundlegende Problem darin, dass Sie nicht wirklich versuchen, ein 4-dimensionales Array zu erstellen. Stattdessen versuchen Sie, ein zweidimensionales Array von zweidimensionalen Arrays zu erstellen.

Wenn Sie das tun wollen, müssen Sie die Top-Level zweidimensionale Anordnung zunächst zuzuordnen und sie dann mit den anderen zweidimensionalen Array-Elemente ausfüllen:

walls = new Wall[grids.GetLength(0), grids.GetLength(1)][,]; 

for (int i = 0; i < grids.GetLength(0); i++) 
for (int j = 0; j < grids.GetLength(1); j++) 
{ 
    walls[I, j] = new Wall[grids.GetLength(0) * 4, grids.GetLength(1) * 4]; 
} 

Alternativ könnten Sie Erstellen Sie ein echtes vierdimensionales Array:

Wall[,,,] walls = new Wall[grids.GetLength(0), grids.GetLength(1), 
          grids.GetLength(0) * 4, grids.GetLength(1) * 4]; 

Das gesagt, scheinen beide Ansätze äußerst verschwenderisch für mich. Die große Mehrheit der Elemente in diesen Arrays wird nicht verwendet. Sie interessieren sich nur für vier Wände pro Fliese, also warum nicht nur vier pro Fliese speichern? Zum Beispiel:

Wall[,,] walls = new Wall[x, y, 4]; 

(. Anstatt GetLength() verwenden, bin Wiederverwendung ich nur das x und y Variablen, die in Ihrem ursprünglichen Code erscheint die Dimensionen des Gitters zu definieren)

Dann eine Hilfsmethode schreiben dass bei gegebenen x/y-Positionen von zwei verschiedenen Zellen ein Index für die fragliche Wand zurückgegeben wird. Hier ist eine Möglichkeit, es zu nähern:

private static readonly int[,] directions = 
{ 
    { 0, -1 }, 
    { 1, 0 }, 
    { 0, 1 }, 
    {-1, 0 } 
}; 

int GetWallIndex(int x0, int y0, int x1, int y1) 
{ 
    int dx = x0 - x1, dy = y0 -y1; 

    for (int i = 0; i < 4; i++) 
    { 
     if (directions[i, 0] == dx && directions[i, 1] == dy) 
     { 
      return i; 
     } 
    } 

    return -1; 
} 

Die GetWallIndex() oben beschriebene Methode wird den entsprechenden Index für das Wall Objekt in Frage zurückkommen, oder -1, wenn Sie ihm die Standorte für Fliesen passieren, die eigentlich nicht benachbart sind. Sie können diesen Index dann im dreidimensionalen Array Wall[,,] verwenden, um das Objekt Wall zu erhalten.

Dies hat immer noch die Ineffizienz, die Wall Daten duplizieren zu müssen, d. H. Einmal für jede Zelle auf jeder Seite der Wand. IMHO, dies ist eine kleine Konzession, vor allem, wenn das Objekt Wall ein Referenztyp ist (und so ist das einzige, was dupliziert ist die Referenz selbst). Es ist jedoch möglich, sogar diese Ineffizienz zu beseitigen, indem die Daten in einem Wörterbuch gespeichert werden und die Kachelkoordinaten beim Nachschlagen normalisiert werden. Zum Beispiel:

struct WallAddress 
{ 
    public int X0 { get; } 
    public int Y0 { get; } 
    public int X1 { get; } 
    public int Y1 { get; } 

    public WallAddress(int x0, int y0, int x1, int y1) 
    { 
     // Optional, not shown here: 
     // Validate addresses to make sure they represent adjacent tiles 

     if (x1 < x0 || (x1 == x0 && y1 < y0)) 
     { 
      int xT = x0, yT = y0; 

      x0 = x1; 
      x1 = xT; 
      y0 = y1; 
      y1 = yT; 
     } 

     X0 = x0; 
     Y0 = y0; 
     X1 = x1; 
     Y1 = y1; 
    } 
} 

Dictionary<WallAddress, Wall> walls = new Dictionary<WallAddress, Wall>(); 

Dann erstellen Sie einfach den WallAddress Wert für das Paar von Fliesen für jedes Wall Objekt und im Wörterbuch füllen.

1

Anders als in Java, wo man so etwas tun könnte:

walls = new Wall[x][y][x2][y2]; 

C# lassen Sie nicht so initialisieren. Es gibt eine Möglichkeit, Wall[,][,] arbeiten zu lassen, aber es ist viel einfacher, ein 4-dimensionales Array von Wall[,,,] zu erstellen.

Aber das wird nicht einmal funktionieren, denn wenn Sie wirklich die Dinge so mit einem [realbignumber] -dimensionalen Array machen wollen (was ich nicht sicher bin, ist der beste Weg das zu tun, aber lasst uns einfach damit gehen), benötigen Sie ein Array Wall[,,,,], um x1, y1, x2, y2 und die Wandausrichtung zu speichern.

Während dies die geringste Geschwindigkeit kostet (wahrscheinlich? Ich kenne nicht die Leistung Auswirkungen von mehrdimensionalen Arrays in C#), sparen Sie eine Menge Speicher (und Vernunft), wenn Sie nur gehen mit einem Wörterbuch und einer Struktur wie in Peter Dunihos Antwort.

Verwandte Themen