Du bist nicht angemeldet.

Werbeanzeige

Tris

Frischling

  • »Tris« ist der Autor dieses Themas

Beiträge: 27

Wohnort: Nähe Stuttgart

Beruf: neu kompilierter Fachinformatiker Anwendungsentwickler

  • Private Nachricht senden

1

05.08.2018, 01:28

byte[,] - Werte drumherum überprüfen

Hallo zusammen,

Ich habe zur Speicherung meiner Map ein 2dimensionals Byte Array genommen.
Dort speichere ich nur eine Zahl anhand derer ich dann weiß welches Feld an dieser Stelle gespawnt werden soll. Das Speichern und Laden der Map funktioniert auch. Nun möchte ich überprüfen ob die Karte auch korrekt ist. Z.B. ob es Felder gibt die nicht verbunden sind. Und später möchte ich dann noch zur Navigation Checkpoints erstellen. Beides möglichst anhand des Byte[,].

Z.B. ist Map[0,0] = 1. 1 wäre dann z.B. ein leeres Feld, 2 Grass usw.

Mein Problem ist nun folgendes: Ich möchte für jedes Feld überprüfen ob es ein Pfad ist und wenn ja soll überprüft werden ob der Pfad an ein weiteres Pfad Feld anknüpft.
Und bei jeder Überprüfung muss ich ja beachten ob das Feld nicht an einem Rand liegt.
Allein schon die Abfrage ob das Feld nicht an einem Rand liegt ist schon unschön.
Ich habe an der Stelle dann aufgehört, weil ich dachte da muss es doch eine schönere Lösung für geben.
Im Moment habe ich also nur die Überprüfung ob links, rechts, unter- oder oberhalb des Feldes ein Pfad Feld ist wenn das Feld nicht am Rand liegt.

Hat jemand einem Tipp wie man das einfacher, schöner lösen kann?
Außerdem verstehe ich nicht warum ich das Enum Tiles vom Typ Byte nochmals zu Byte casten muss? (PlacedTiles[i, j - 1] == (byte)Tiles.Path)


EDIT: Hier nur ein paar Gedanken die mir aufkommen:
Felder die Nachbar eines überprüften Feldes sind und ein Pfadfeld sind, kann ich bei der Überprüfung überspringen.


C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
        // Check if there are path tiles that are not connected
        int unconnectedTiles = 0;
        bool isConnected = false;
        for (int i = 0; i < PlacedTiles.GetLength(0); i++)
        {
            for (int j = 0; j < PlacedTiles.GetLength(1); j++)
            {
                isConnected = false;
                if (PlacedTiles[i, j] == (int)Tiles.Path)
                {
                    // Check all 4 directions (if array boundaries X and Y are not hit)
                    if (i > 0 && i < PlacedTiles.GetLength(0) && j > 0 && j < PlacedTiles.GetLength(1))
                    {
                        if ((PlacedTiles[i - 1, j] == (byte)Tiles.Path ||
                             PlacedTiles[i + 1, j] == (byte)Tiles.Path ||
                             PlacedTiles[i, j - 1] == (byte)Tiles.Path ||
                             PlacedTiles[i, j + 1] == (byte)Tiles.Path))
                        {
                            isConnected = true;
                        }
                        else
                        {
                            isConnected = false;
                            unconnectedTiles++;
                        }
                        continue;
                    }
                    // Check all 3 directions, if ...
                }
            }
        }


Grüße
Tris

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Tris« (05.08.2018, 01:46)


BlueCobold

Community-Fossil

Beiträge: 10 842

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

05.08.2018, 08:06

Die Prüfung, ob es ein Randfeld ist, lässt sich relativ einfach mit einem Trick umgehen. Du machst die Map einfach an jeder Seite eine Feld breiter und prüfst nur den Index 1..n-2, wobei n die Höhe/Breite ist. Damit lassen sich diese Zusatzzeilen/Spalten nicht betreten und du brauchst sie auch nicht anzeigen. Es entfällt aber vollständig die Prüfung, ob du am Rand der Karte herum rechnest.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

3

05.08.2018, 08:57

Quellcode

1
2
3
4
5
6
if(
(i > 0 && PlacedTiles[i - 1, j] == (byte)Tiles.Path) ||
(i < PlacedTiles.GetLength(0) - 1 && PlacedTiles[i + 1, j] == (byte)Tiles.Path) ||
(j > 0 && PlacedTiles[i, j - 1] == (byte)Tiles.Path) ||
(j < PlacedTiles.GetLength(1) - 1 && PlacedTiles[i, j + 1] == (byte)Tiles.Path)
)


https://docs.microsoft.com/en-us/dotnet/…al-and-operator

Tris

Frischling

  • »Tris« ist der Autor dieses Themas

Beiträge: 27

Wohnort: Nähe Stuttgart

Beruf: neu kompilierter Fachinformatiker Anwendungsentwickler

  • Private Nachricht senden

4

06.08.2018, 23:33

Die Prüfung, ob es ein Randfeld ist, lässt sich relativ einfach mit einem Trick umgehen. Du machst die Map einfach an jeder Seite eine Feld breiter und prüfst nur den Index 1..n-2, wobei n die Höhe/Breite ist. Damit lassen sich diese Zusatzzeilen/Spalten nicht betreten und du brauchst sie auch nicht anzeigen. Es entfällt aber vollständig die Prüfung, ob du am Rand der Karte herum rechnest.

Danke, das ist eine gute Idee. Das spart einiges an Code ein und vermeidet sicherlich auch den ein oder anderen Fehler. :)


C#-Quelltext

1
2
3
4
5
6
if(
(i > 0 && PlacedTiles[i - 1, j] == (byte)Tiles.Path) ||
(i < PlacedTiles.GetLength(0) - 1 && PlacedTiles[i + 1, j] == (byte)Tiles.Path) ||
(j > 0 && PlacedTiles[i, j - 1] == (byte)Tiles.Path) ||
(j < PlacedTiles.GetLength(1) - 1 && PlacedTiles[i, j + 1] == (byte)Tiles.Path)
)

https://docs.microsoft.com/en-us/dotnet/…al-and-operator

Auch dir danke, so gefällt mir das deutlich besser.

5

07.08.2018, 10:07

Außerdem verstehe ich nicht warum ich das Enum Tiles vom Typ Byte nochmals zu Byte casten muss? (PlacedTiles[i, j - 1] == (byte)Tiles.Path)


Das mit dem Cast lässt sich nicht vermeiden. Siehe hier: https://docs.microsoft.com/de-de/dotnet/…e/keywords/enum

"...Der zugrunde liegende Typ gibt an, wie viel Speicher für jeden Enumerator reserviert wird. Eine explizite Typumwandlung ist jedoch erforderlich, um einen enum-Typ in einen ganzzahligen Typ zu konvertieren..."

BlueCobold

Community-Fossil

Beiträge: 10 842

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

07.08.2018, 11:03

Und wieso speichert man dann keinen Enum in der Map, sondern einen Int? ;) Wäre doch cleverer dann keinen Int zu nehmen und sich den Cast zu schenken. Das ist vielleicht der bessere Tipp statt zu erklären, warum man casten muss.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

TGGC

1x Rätselkönig

Beiträge: 1 802

Beruf: Software Entwickler

  • Private Nachricht senden

7

08.08.2018, 07:59

Man kann auch einfach eine Funktion/Methode bauen GetInfo(x,y) und da drin dann ausserhalb der Karte immer zurückgeben, was grad passt. Auch der Cast kann da drin sein und alles wird viel übersichtlicher.

8

08.08.2018, 10:40

Und wieso speichert man dann keinen Enum in der Map, sondern einen Int? ;) Wäre doch cleverer dann keinen Int zu nehmen und sich den Cast zu schenken. Das ist vielleicht der bessere Tipp statt zu erklären, warum man casten muss.


Korrekt, den Cast zu vermeiden ist natürlich die bessere Lösung. Ich hatte nur vor ein paar Tagen das gleiche Problem, da musste ich aber ein Enum an eine externe Schnittstelle als Int liefern und ich hatte mich auch gewundert warum man da noch explizit casten muss.

Werbeanzeige