mmofacts.com

Verschachteletes Programmieren

gepostet vor 16 Jahre, 2 Monate von kevka
Hi,
ich habe gerade folgende Zeile Code, die ich wirklich benötige, in C# geschrieben:
private Dictionary>> Terrains = new Dictionary>>();

Wie sieht euer verschachteltster Code aus?
MfG Kevka
gepostet vor 16 Jahre, 2 Monate von Drezil
wäre an der stelle nicht ein tree sinnvoller?
gepostet vor 16 Jahre, 2 Monate von kevka
Original von Drezil
wäre an der stelle nicht ein tree sinnvoller?

Hast du einen Link dazu?
Alles was unser Freund google zu diesem Thema ausspuckt hat mit TreeViews zu tun.
gepostet vor 16 Jahre, 2 Monate von TheUndeadable
Oder ein:
class TripleString { String, String, String } mit überschriebenem GetHashCode und Equals und dann
Dictionary
Aber leider habe ich persönlich keine solche Mammutkonstrukte.
gepostet vor 16 Jahre, 2 Monate von RaydenDD
Ich hab was gleichwertiges
private HashMap>> prioListPP;

Vielleicht kann ich mit meiner rekursiven Schiffsuche in den verschachtelten Hangars Kontern
    public void rekSearchHangar(ArrayList levelStructure, ArrayList nestedOutputList, int level) {

for (int i=0;i
ShipTypeEntry tmpEntry = levelStructure.get(i);
tmpEntry.setNestedLevel(level);
nestedOutputList.add(tmpEntry);

if (tmpEntry.getLargeHangarLoaded() != null) {
if (DEBUG) DebugBuffer.addLine(DebugLevel.TRACE,"CHECK LARGE HANGAR LIST (LEVEL: " + level + ")");
rekSearchHangar(tmpEntry.getLargeHangarLoaded(),nestedOutputList,level+1);
}
if (tmpEntry.getMediumHangarLoaded() != null) {
if (DEBUG) DebugBuffer.addLine(DebugLevel.TRACE,"CHECK MEDIUM HANGAR LIST (LEVEL: " + level + ")");
rekSearchHangar(tmpEntry.getMediumHangarLoaded(),nestedOutputList,level+1);
}
if (tmpEntry.getSmallHangarLoaded() != null) {
if (DEBUG) DebugBuffer.addLine(DebugLevel.TRACE,"CHECK SMALL HANGAR LIST (LEVEL: " + level + ")");
rekSearchHangar(tmpEntry.getSmallHangarLoaded(),nestedOutputList,level+1);
}
}
}
gepostet vor 16 Jahre, 2 Monate von TheUndeadable
> if (DEBUG) DebugBuffer.addLine(DebugLevel.TRACE,"CHECK SMALL HANGAR LIST (LEVEL: " + level + ")");
Google:
ConditionalAttribute
:-)
BTW: Mein Favorit:
            ListHelper.ForEach(

ListHelper.Distinct(
ListHelper.Convert(_Roles,
x => x.Feedback)),
x => x.Execute(oCore.Configuration, eItem));
gepostet vor 16 Jahre, 2 Monate von Todi42
Ich brauchte letztens eine Map mit einer Liste von Einträgen in einer andere Liste:
typedef std::map::iterator> > update_list_t;
Ich hatte dann aber aus den std::list::iterator einfach ein unsigned gemacht, womit das Ganze nicht mehr ganz so spektakuler aussieht ;-)
gepostet vor 16 Jahre, 2 Monate von kevka
Am besten ich poste noch gleich die Verwendung des Dictonarys:
Sortieren der Terreinobjecte im MapEditor für mein BG:

//TerrainListe ordnen
private void orderTerrainList(List Terrains)
{
foreach (Terrain t in Terrains)
{
if (!OrderedTerrains.ContainsKey(t.Category))//Category falls nötig anlegen
{
Dictionary>> NewCategory = new Dictionary>>(); //die neue Category
Dictionary> NewGroup = new Dictionary>();//Die neue Group
List NewTilegroup = new List();//die neue Tilegruppe
NewTilegroup.Add(t);//Terrain zur neuen Tilegruppe hinzufügen
NewGroup.Add(t.Tilegroup, NewTilegroup);//Tilegruppe mit Verweiß zur neuen Gruppe hinzufügen
NewCategory.Add(t.Group, NewGroup);//Neue Gruppe mit Verweiß zur neuen Category hinzufügen
OrderedTerrains.Add(t.Category, NewCategory);//Neue Category mit Verweiß zu Ordered Tiles hinzufügen
}
else if (!OrderedTerrains[t.Category].ContainsKey(t.Group))//Wenn Category aber nicht Gruop vorhanden
{
Dictionary> NewGroup = new Dictionary>();//Die neue Group
List NewTilegroup = new List();//die neue Tilegruppe
NewTilegroup.Add(t);//Terrain zur neuen Tilegruppe hinzufügen
NewGroup.Add(t.Tilegroup, NewTilegroup);//Tilegruppe mit Verweiß zur neuen Gruppe hinzufügen
OrderedTerrains[t.Category].Add(t.Group, NewGroup);//neue Gruppe mit verweiß zu Ordered Terrains hnzufügen
}
else if (!OrderedTerrains[t.Category][t.Group].ContainsKey(t.Tilegroup))//wenn Category und Group aber keine Tilegroup
{
List NewTilegroup = new List();//die neue Tilegruppe
NewTilegroup.Add(t);//Terrain zur neuen Tilegruppe hinzufügen
OrderedTerrains[t.Category][t.Group].Add(t.Tilegroup, NewTilegroup);//Neue tilegroup mit verweiß zur group hinzufügen
}
else//Wenn alles vorhanden
{
OrderedTerrains[t.Category][t.Group][t.Tilegroup].Add(t);
}
}
}
gepostet vor 16 Jahre, 2 Monate von RaydenDD
Original von TheUndeadable
Google:
ConditionalAttribute
:-)

In Java gibts keine ConditionalAttributes
gepostet vor 16 Jahre, 2 Monate von TheUndeadable
> In Java gibts keine ConditionalAttributes
Ups, war Java. Sry.
Die Sprachen sind einfach zu ähnlich. Ok, ich hätte es am rekIrgendwas statt RekIrgendwas merken sollen... Ich werde halt auch alt.
@kevka:
Da würde ich ein eigenes Dictionary mit überladenem [String, String, String] Operator aufbauen, der genau das intern macht.
gepostet vor 16 Jahre, 2 Monate von kevka
Original von TheUndeadable
Da würde ich ein eigenes Dictionary mit überladenem [String, String, String] Operator aufbauen, der genau das intern macht.

Danke für deinen Tipp. Da jetzt aber schon alles integriert ist und der Map Editor auf Grund des niedrigen Verteilungsgrades nicht unbedingt die beste Performenc haben muss werde ich es nur dann integrieren, sollte ich später einmal Probleme mit der Performenc haben.
MfG Kevka
gepostet vor 16 Jahre, 2 Monate von altertoby

GebäudeWohnung wohnung = geb as GebäudeWohnung;
if (wohnung != null)
//CODE
else
{
GebäudeForschung forschung = geb as GebäudeForschung;
if (forschung != null)
{
//CODE
}
else
{
//Und das noch mit 8 anderen Klassen
}
}

Warum gibt es auch kein switch über verschiedene Klassen... (ich weiß wegen Vererbung... aber so nen Code ist auch mist... weiß da jemand wies besser geht?)
gepostet vor 16 Jahre, 2 Monate von duschendestroyer
geht sicher um einiges einfacher
also zuallererst gibts elseif
aber ich denke sogar dass das problem noch einfacher zu lösen ist
(hab aber nicht viel ahung von Java oder was das ist)
gepostet vor 16 Jahre, 2 Monate von TheUndeadable
Ich würde mir überlegen, ob du nicht alle Gebäudetypen eine Schnittstelle implementieren lässt und die dann aufrufst.
as/is - Aufrufe in C# sind nicht die schnellsten.
gepostet vor 16 Jahre, 2 Monate von TheUndeadable
@kevka:
BTW:
Schau mal nach der Funktion TryGetValue, dann ersparst du das doppelte Referenzieren (Einmal ContainsKey und dann den tatsächlichen Zugriff)
gepostet vor 16 Jahre, 2 Monate von altertoby
das ist c#...
wegen dem else if...
ich brauch aber zb den Verweis auf "wohnung"...
evt müsste man dass dann so machen

if (GebäudeWohnung wohnung = geb as GebäudeWohnung != null)
//CODE
else if(GebäudeForschung forschung = geb as GebäudeForschung != null)
{
//CODE
}
habs gerade nicht getestet ob der Compiler sowas schluckt... sieht aber auch nicht wirklich toll aus!
@TheUndeadable:
Das Problem ist, dass der Code für das Abreißen von Gebäuden ist.
Dort wird je nachdem was für ein Gebäude abgerissen wird eine Aktion durchgeführt (zb einmal die Forscher dezimiert und einmal die normalen Arbeiter)...das könnte man ja noch durch nen Enum lösen, dass der Code dann weiß, welcher Gebäudetyp das ist.
Aber die einzelnen Klassen haben noch unterschiedliche Properties auf die ich dann zugreifen muss... also mit einer grundlegenen Schnittstelle komm ich da nicht weit...
was mir gerade einfällt:
Alle Gebäudetypen erben von "Gebäude"... wenn ich dort nen Gebäudetyp als Property erstelle und im Constructor des entsprechenden Gebäudetyps das Property setzte (bzw das überschreibe... was wäre da besser?) müsste es dann eigentlich gehen...dann geht nen switch und anschließen brauch ich nur noch einmal nen "as" Befehl. (vllt meinst du das auch und ich hab dich nur falsch verstanden)
gepostet vor 16 Jahre, 2 Monate von TheUndeadable
> Alle Gebäudetypen erben von "Gebäude"...
Dachte eher an eine Schnittstelle ICanBeAbgerissen.
Dann testest du auf diese Schnittstelle und führst bei Aktion den Code im Gebäude selbst aus. Natürlich musst du dann noch alle Objekte übergeben, die für einen solchen Abriss notwendig sind, bzw die Methode kann sich ja selbst die Objekte beschaffen (soweit wie möglich).
if (GebäudeWohnung wohnung = geb as GebäudeWohnung != null)

//CODE
else if(GebäudeForschung forschung = geb as GebäudeForschung != null)
{
//CODE
}
Wird der Compiler nicht so schlucken.

GebäudeWohnung wohnung;
GebäudeForschung forschung;
if ((wohnung = geb as GebäudeWohnung) != null)
//CODE
else if((forschung = geb as GebäudeForschung) != null)
{
//CODE
}
schon eher.
Mein Vorschlag wäre allerdings dann folgender:

ICanBeAbgerissen iBuilding;
if ((iBuilding = geb as ICanBeAbgerissen ) != null)
{
iBuilding->ReisseAb ( this );
}
void GebäudeWohnung::ReisseAb( KeineAhnung oObjekt )
{
oObjekt->ReduziereArbeiter();
//etc
}
Pseudecode..., aber ich hoffe du weißt, was ich meine.
gepostet vor 16 Jahre, 2 Monate von altertoby
Das ist ne interessante Methode!
Problem ist nur, dass die Objekte (in dem Fall die Gebäudeklassen) sich nicht selbst verwalten... soll heißen sie agieren nicht mit anderen Objekten sondern verändern nur sich selber (dh eine Instanz von Gebäude würde in der Methode GebäudeAbreißen() nur die eigene Anzahl verringern)... oder anders sie sind etwas intelligente Datenspeicher!
Die eigentliche Logik passiert in BLL-Klassen...die gehen mit den Objekten um und bearbeiten die bzw rufen die passenden Methoden auf.
Wenn ich keinen anderen guten Weg finde werd ich es so machen wie du vorgeschlagen hast...
aber nochmal zu meiner Idee, was hälst du von:

class Gebäude
{
GebäudeTyp GebäudeTyp{get; set;}
...
}
class Wohnung : Gebäude
{
Wohnung() : base()
{
this.GebäudeTyp = GebäudeTyp.Wohnung
}
...
bzw (und dann ohne setter in Gebäude)
override GebäudeTyp
get
{
return GebäudeTyp.Wohnung;
}
}
gepostet vor 16 Jahre, 2 Monate von TheUndeadable
soweit gut, das kannst du aber noch optimieren, so dass du nicht auf Grund der Programmierfaulheit zu Fehlern verleitet wirst:

class Gebäude
{
GebäudeTyp GebäudeTyp{get; set;}
public Gebäude ( GebäudeTyp eType ) { GebäudeTyp = eType; }
}
class Wohnung : Gebäude
{
Wohnung() : base( GebäudeTyp.Wohnung )
{
}
}
Dann kannst du ein schönes switch-case-Statement in deiner Business-Logik nutzen.
gepostet vor 16 Jahre, 2 Monate von altertoby
find ich klasse aus jedem deine Posts kann man was lernen
nur noch eine Frage:
Ich speichere die Daten nicht in einer DB sondern halte sie im Cache (+ Backup als XML Datei)... und beim Serialisieren bzw Deserialisieren muss ja ein Konstruktor ohne Parameter vorhanden sein
Dann würde dein Code nicht klappen oder? (bzw könnte ich dann in Wohnungsklasse immnoch den falschen Konstruktor aufrufen)
gepostet vor 16 Jahre, 2 Monate von duschendestroyer
kann man nicht einfach irgendwie über reflektion an die klasse kommen und darüber dann ein switch machen?
/me hat keine ahnuung von C#
gepostet vor 16 Jahre, 2 Monate von TheUndeadable
> kann man nicht einfach irgendwie über reflektion an die klasse kommen und darüber dann ein switch machen?
Könnte man, macht am aber nicht (Performance der Reflections sind nicht optimal).
Abgesehen davon gehen switches in C# nur auf Primitive (Zahlen und Strings). Man könnte zwar einen Switch auf oBuilding.GetType().ToString() machen, aber das wäre mehr als suboptimal.
@altertoby:
Sollte eigentlich funktionieren, da ja Wohnung selbst einen parameterlosen Konstruktor hat. Ich gehe davon aus, dass du ja niemals Gebäude instantiieren wirst.
Aber genau weiß ich es nicht.

Auf diese Diskussion antworten