Tischbelegung Mathematisches Problem Codekürzung

Hallöle ihr Alle,

ich habe da ein kleines mathematisches Problemchen. Mein Quellcode ist mir viel zu lang und manuell geprägt, ich überlege die ganze Zeit, wie man das als mathematischen Ansatz mit Schleifen machen kann.

Folgendes:

Wir hier zu sehen habe ich ein Spielfeld mit 12 Orangenen Feldern (Tische) und 24 Roten Feldern. Das sind Stühle, die an den Tischen stehen.
Ich habe eine Klasse Stuhl und eine Klasse Tisch und füge jeweils 12 bzw. 24 Stück davon in mein Projekt ein.
Ich speichere je sie in einer ArrayList in einer anderen Klasse:

	private ArrayList<Spielzelle> spielfeldstuhl = new ArrayList<Spielzelle>(24);```

Nun muss ich jedem Tisch zuordnen, welche Stühle an ihm dran stehen und jedem Stuhl sagen, an welchen Tischen er steht.
Es gilt: Die Elemente die gemeinsame Seiten auf dem Bild haben, stehen auch nebeneinander. ;)

Ich habe zwei Settermethoden.
Für die Stühle:
```public void setTische(Tisch...tische) {
		this.tische = tische;
	}```

Und für die Tische:
```public void setStuehle(Stuhl... stuhl) {
		this.stuhl = stuhl;
	}```

Das Spielfeld sieht ja eigentlich so regelmäßig aus, aber ich finde da kein mathematisches Modell, um das einzukürzen.

Aktuell sieht das nämlich so aus, wenn ich alles zuordne:
```Spielklasse sk = new Spielklasse();
sk.getTische().get(0).setStuehle(sk.getStuehle().get(11),sk.getStuehle().get(12),sk.getStuehle().get(13),sk.getStuehle().get(0));
sk.getTische().get(1).setStuehle(sk.getStuehle().get(1),sk.getStuehle().get(2),sk.getStuehle().get(12),sk.getStuehle().get(13));
sk.getTische().get(2).setStuehle(sk.getStuehle().get(2),sk.getStuehle().get(3),sk.getStuehle().get(13),sk.getStuehle().get(14));
sk.getTische().get(3).setStuehle(sk.getStuehle().get(3),sk.getStuehle().get(4),sk.getStuehle().get(5),sk.getStuehle().get(14));
sk.getTische().get(4).setStuehle(sk.getStuehle().get(4),sk.getStuehle().get(5),sk.getStuehle().get(15),sk.getStuehle().get(16));
sk.getTische().get(5).setStuehle(sk.getStuehle().get(5),sk.getStuehle().get(6),sk.getStuehle().get(16),sk.getStuehle().get(17));
sk.getTische().get(6).setStuehle(sk.getStuehle().get(6),sk.getStuehle().get(7),sk.getStuehle().get(17),sk.getStuehle().get(18));
sk.getTische().get(7).setStuehle(sk.getStuehle().get(7),sk.getStuehle().get(18),sk.getStuehle().get(19),sk.getStuehle().get(20));
sk.getTische().get(8).setStuehle(sk.getStuehle().get(7),sk.getStuehle().get(8),sk.getStuehle().get(20),sk.getStuehle().get(21));
sk.getTische().get(9).setStuehle(sk.getStuehle().get(8),sk.getStuehle().get(9),sk.getStuehle().get(21),sk.getStuehle().get(22));
sk.getTische().get(10).setStuehle(sk.getStuehle().get(9),sk.getStuehle().get(10),sk.getStuehle().get(22),sk.getStuehle().get(23));
sk.getTische().get(11).setStuehle(sk.getStuehle().get(9),sk.getStuehle().get(10),sk.getStuehle().get(11),sk.getStuehle().get(0));

sk.getStuehle().get(0).setTische(sk.getTische().get(11),sk.getTische().get(0));
sk.getStuehle().get(1).setTische(sk.getTische().get(1));
sk.getStuehle().get(2).setTische(sk.getTische().get(1),sk.getTische().get(2));
sk.getStuehle().get(3).setTische(sk.getTische().get(2),sk.getTische().get(3));
sk.getStuehle().get(4).setTische(sk.getTische().get(3),sk.getTische().get(4));
sk.getStuehle().get(5).setTische(sk.getTische().get(3),sk.getTische().get(4),sk.getTische().get(5));
sk.getStuehle().get(6).setTische(sk.getTische().get(5),sk.getTische().get(6));
sk.getStuehle().get(7).setTische(sk.getTische().get(6),sk.getTische().get(7),sk.getTische().get(8));
sk.getStuehle().get(8).setTische(sk.getTische().get(8),sk.getTische().get(9));
sk.getStuehle().get(9).setTische(sk.getTische().get(9),sk.getTische().get(10),sk.getTische().get(11));
sk.getStuehle().get(10).setTische(sk.getTische().get(10),sk.getTische().get(11));
sk.getStuehle().get(11).setTische(sk.getTische().get(11),sk.getTische().get(0));
sk.getStuehle().get(12).setTische(sk.getTische().get(0),sk.getTische().get(1));
sk.getStuehle().get(13).setTische(sk.getTische().get(1),sk.getTische().get(2),sk.getTische().get(0));
sk.getStuehle().get(14).setTische(sk.getTische().get(2),sk.getTische().get(3));
sk.getStuehle().get(15).setTische(sk.getTische().get(4));
sk.getStuehle().get(16).setTische(sk.getTische().get(4),sk.getTische().get(5));
sk.getStuehle().get(17).setTische(sk.getTische().get(5),sk.getTische().get(6));
sk.getStuehle().get(18).setTische(sk.getTische().get(6),sk.getTische().get(7));
sk.getStuehle().get(19).setTische(sk.getTische().get(7));
sk.getStuehle().get(20).setTische(sk.getTische().get(7),sk.getTische().get(8));
sk.getStuehle().get(21).setTische(sk.getTische().get(8),sk.getTische().get(9));
sk.getStuehle().get(22).setTische(sk.getTische().get(9),sk.getTische().get(10));
sk.getStuehle().get(23).setTische(sk.getTische().get(10));```


Hat da jemand eine Idee, wie man diesen riesigen Klopper kürzen könnte?

Ihr könnt auch die Nummern der Tische und Stühle vertauschen, das ist jetzt nur mein Modell da oben.

Achso und: Tisch12 ist Element 0 und Stuhl24 ist Element 0, als ich das Bild erstellte vergaß ich, dass der bei 0 loszählt.


Schöne Grüße und Vielen Dank
Gruß
Lukas

Tja, da hatten wir schon jede Menge Tipps gegeben, du machst es anders, und jetzt…

Hast du die “Koordinaten” der Tische und Stühle? Sonst wird es schwierig.

Natürlich kann man auch die Zuweisung etwas hübscher machen:

private static void setStuehle(int tischNr, int ... stuehleNr) {
   Tisch tisch = sk.getTische().get(tischNr);
   Stuhl[] stuehle = new Stuhl[stuehleNr.length];
   int i = 0;
   for(int stuhlNr : stuehleNr) {
       stuehle[i++] = sk.getStuehle().get(stuhlNr); 
   } 
   tisch.setStuehle(stuehle);
}

//analog für Stühle

//dann in deinem Code
setStuehle(0, 11, 12, 13, 0);
setStuehle(1, 1, 2, 12, 13);
...

Auch wenn du meinen Vorschlag nicht zu mögen scheinst, bringe ich ihn nochmal. Meiner Meinung nach ist eine kleine “String-Map” die beste Lösung:

String[] map = {
  "       #      ",
  "      #o#     ",
  "     #o#o#    ",
  "    #o# #o#   ",
  "     #o#o#    ",
  "      #o#     ",
  "       #      "
}

Daraus lässt sich alles ableiten: wo Tische und Stühle stehen, und welcher Tisch zu welchem Stuhl gehört. Tisch- und Stuhlnummern kannst du einfach fortlaufend nach der Reihenfolge im String vergeben.

Wunderschönen Guten Tag und vielen Dank für Deine Antwort,

Tja, da hatten wir schon jede Menge Tipps gegeben, du machst es anders, und jetzt…

Ich bin seit Oktober in dem Forum unterwegs. Damals wusste ich noch nicht mal, was nen Array oder eine Klasse ist. :wink: Als ich damals das Thema aufgemacht habe, hab ich bestimmt 90% von dem, was ihr gesagt habt ne Stunde googlen müssen. Deshalb war das Thema auch so ewig lang. (120 Beiträge?) Wenn ich da jetzt so rüberlese, hätten es auch 5 sein können. Und ich hätte 10 Themen weniger aufgemacht. Naja, war halt ein Lernprozess.
Entschuldige, ich habe den Tipp damals einfach schlichtweg nicht verstanden.:smiley: Wollte es irgendwie machen, wie ich es verstehe.

Hast du die „Koordinaten“ der Tische und Stühle? Sonst wird es schwierig.

Ja, klar. Also das ist folgendermaßen:
Man schaue auf das Bild in dem Beitrag davor. Ist ein einfaches GridBagLayout. Die sind in nem 2D-Array gespeichert. Mit [x][y]. Gezählt von oben Links bis unten Rechts geht es von [0][0] bis [10][10].
Das kann man als Alternative Zählvariante auch in Betracht ziehen.

Zuallererst einmal muss ich noch sagen, ich trenne Grafik und die internen Rechnungen ab.
Das heißt ich habe diesen fetten Klopper einmal für das Zuordnen von Stuhl und Tisch generell und einmal, um die 11 mal 11 JPanel einfach einem Element aus einem Enum zuzuordnen: enum Typ {Leer, Stuhl, Tisch}. Leer sind die Weißen Felder drum herum.

Ich habe die Grafiksache nun schon schick einkürzen können.
Vorher:

		spielfeldtisch.add(spielfeldzelle[5][2]);
		spielfeldtisch.add(spielfeldzelle[6][3]);
		spielfeldtisch.add(spielfeldzelle[7][4]);
		spielfeldtisch.add(spielfeldzelle[8][5]);
		spielfeldtisch.add(spielfeldzelle[7][6]);
		spielfeldtisch.add(spielfeldzelle[6][7]);
		spielfeldtisch.add(spielfeldzelle[5][8]);
		spielfeldtisch.add(spielfeldzelle[4][7]);
		spielfeldtisch.add(spielfeldzelle[3][6]);
		spielfeldtisch.add(spielfeldzelle[2][5]);
		spielfeldtisch.add(spielfeldzelle[3][4]);
		
		spielfeldstuhl.add(spielfeldzelle[4][4]);
		spielfeldstuhl.add(spielfeldzelle[5][1]);
		spielfeldstuhl.add(spielfeldzelle[6][2]);
		spielfeldstuhl.add(spielfeldzelle[7][3]);
		spielfeldstuhl.add(spielfeldzelle[8][4]);
		spielfeldstuhl.add(spielfeldzelle[7][5]);
		spielfeldstuhl.add(spielfeldzelle[6][6]);
		spielfeldstuhl.add(spielfeldzelle[5][7]);
		spielfeldstuhl.add(spielfeldzelle[4][6]);
		spielfeldstuhl.add(spielfeldzelle[3][5]);
		spielfeldstuhl.add(spielfeldzelle[2][4]);
		spielfeldstuhl.add(spielfeldzelle[3][3]);
		spielfeldstuhl.add(spielfeldzelle[4][2]);
		spielfeldstuhl.add(spielfeldzelle[5][3]);
		spielfeldstuhl.add(spielfeldzelle[6][4]);
		spielfeldstuhl.add(spielfeldzelle[9][5]);
		spielfeldstuhl.add(spielfeldzelle[8][6]);
		spielfeldstuhl.add(spielfeldzelle[7][7]);
		spielfeldstuhl.add(spielfeldzelle[6][8]);
		spielfeldstuhl.add(spielfeldzelle[5][9]);
		spielfeldstuhl.add(spielfeldzelle[4][8]);
		spielfeldstuhl.add(spielfeldzelle[3][7]);
		spielfeldstuhl.add(spielfeldzelle[2][6]);
		spielfeldstuhl.add(spielfeldzelle[1][5]);
		
		for(Spielzelle a:spielfeldtisch) {
            a.setTyp(Spielzelle.Typ.Tisch);
        }
        for(Spielzelle b:spielfeldstuhl) {
            b.setTyp(Spielzelle.Typ.Stuhl);
        }```

Nachher:
```int[] tischkoordx = {4,5,6,7,8,7,6,5,4,3,2,3};
		int[] tischkoordy = {3,2,3,4,5,6,7,8,7,6,5,4};
		for(int i=0;i<12;i++) {
			spielfeldtisch.add(spielfeldzelle[tischkoordx**][tischkoordy**]);
			spielfeldzelle[tischkoordx**][tischkoordy**].setTyp(Spielzelle.Typ.Tisch);
		}
		
		int[] stuhlkoordx = {4,5,6,7,8,7,6,5,4,3,2,3,4,5,6,9,8,7,6,5,4,3,2,1};
		int[] stuhlkoordy = {4,1,2,3,4,5,6,7,6,5,4,3,2,3,4,5,6,7,8,9,8,7,6,5};
		for(int i=0;i<24;i++) {
			spielfeldstuhl.add(spielfeldzelle[stuhlkoordx**][stuhlkoordy**]);
			spielfeldzelle[stuhlkoordx**][stuhlkoordy**].setTyp(Spielzelle.Typ.Stuhl);
		}```

Habe die Nummern einfach in einem Array drin und gehe sie dann durch.
Da sieht man übrigens auch das mit den Koordinaten, wie gerade erwähnt.

======
Und nun zu dem, was ich eigentlich gefragt hatte, der Zuordnung von Tischen und Stühlen:
Zu dem ersten Ansatz mit dem einzelnen Code:
Das ist eine sehr gute Idee. Schlimm, dass ich darauf nicht gekommen bin. Meine Setter-Methoden nehmen ja nur die Stühle und Tische als Parameter auf, weshalb die Methode dann so ewig lang wird.
Es ist in der Tat sinnvoller, wenn ich als Parameter stattdessen einfach nur eine Menge an Integern aufnehme und dann in der Setter-Methode mit den Integern die Stühle und Tische nachlade.
```private static void setStuehle(int tischNr, int ... stuehleNr) {
   Tisch tisch = sk.getTische().get(tischNr);
   Stuhl[] stuehle = new Stuhl[stuehleNr.length];
   int i = 0;
   for(int stuhlNr : stuehleNr) {
       stuehle[i++] = sk.getStuehle().get(stuhlNr);
   }
   tisch.setStuehle(stuehle);
}```
Wie Du es hier geschrieben hast. Ich werde mir das einmal ansehen. Ich melde mich, wenn ich es fertig habe. Wird sicherlich ähnlich aussehen.


Zu dem anderen Vorschlag mit der String-Map:
Ich hatte den Vorschlag damals ignoriert, weil ich ihn irgendwie nicht verstehe und auch heute nochmal nachfragen muss.
Für mich ist das einfach nur schickes Zeuchs, um mein Problem besser zu visualisieren. Aber ich verstehe nicht, wie der Computer aus sowas denn ableiten soll, wo was steht. Ist für mich wirklich nur eine Ansammlung von Zeichen, die dann so aussehen wie mein Spielfeld. ;)
Kannst Du mir bitte für die Zukünftigen Projekte erläutern, was man damit anfangen kann? Vielleicht entdecke ich diese Methode ja auch für mich. :D 


Schöne Grüße und Dankeschön
Lukas

Gut, die String-Map-Methode etwas ausführlicher (Code aus dem Kopf, keine Gewähr):

Erst einmal braucht man eine kleine Positions-Klasse (wenn man nicht java.awt.Point missbrauchen will):

public class Pos {
   public final int x;
   public final int y;
   public Pos(int x, int y) { 
       this.x = x;
       this.y = y;
   }
   public int hashCode() {
      return x + 1000*y;
   }
   public boolean equals(Object o) {
      //quick und dirty, deine IDE macht das besser
      return (o instanceof Pos) ? hashCode() == o.hashCode() : false;
   }
}

Dann liest man im ersten Schritt die Tische und Stühle in Maps ein:

String[] stringMap = ...
Map<Pos, Tisch> tischMap = new HashMap<>();
Map<Pos, Stuhl> stuhlMap = new HashMap<>();
int tischNr = 0;
int stuhlNr = 0;
int y = 0;
for(String row : stringMap) {
   for(int x = 0; x < row.length(); x++) {
      switch(row.charAt(x)) {
          case '#':  stuhlMap.put(new Pos(x,y), new Stuhl(stuhlNr++); break;
          case 'o':  tischMap.put(new Pos(x,y), new Tisch(tischNr++); break;
      } 
   }
   y++;
}

Jetzt kann man sich die Nachbarn “automatisch” suchen:

for(Map.Entry<Pos, Tisch> entry : tischMap) {
   Pos p = entry.getKey();
   Tisch tisch = entry.getValue();
   List<Stuhl> stuehle = new ArrayList<>();
   for(Pos pos : new Pos[]{ new Pos(p.x,p.y-1), new Pos(p.x,p.y+1), new Pos(p.x-1, p.y), new Pos(p.x+1, p.y) }) {
       Stuhl stuhl = stuhlMap.get(pos);
       if (stuhl != null) {
          stuehle.add(stuhl);
       } 
   }
   tisch.setStuehle(stuehle.toArray(new Stuhl[stuehle.size()]));
}
//analog für Stühle

Der Vorteil ist, dass man flexibler ist: Will man eine andere Tischanordnungen verwenden, stopft man vorn einfach eine andere String-Map rein. Wenn der Code erst einmal läuft, ist er narrensicher - keine Zahlendreher oder so möglich.

(EDIT: Hä, 17 Minuten?! Hätte wohl vorher mal “Reload” drücken sollen :rolleyes: )

Ohne da zu viel vorwegnehmen zu wollen: Mit so einer Map könntest du den Code aus der “nachher”-Variante noch etwas generischer machen. GROB im Sinne von

for (int r=0; r<rows; r++)
{
    for (int c=0; c<cols; c++)
    {
        char type = map[r].charAt(c);
        switch (type) 
        {
            case ' ': break;
            case 'o': spielfeldzelle[r]```.setTyp(Spielzelle.Typ.Tisch); break;
            case '#': spielfeldzelle[r]```.setTyp(Spielzelle.Typ.Stuhl); break;
        }
    }
}

Deutlicher wird der Vorteil, wenn man überlegt, man wollte vielleicht (für ein anderes Spiel oder so…) das ganze mal zu

String[] map = {
  "      #o#     ",
  "      #o#     ",
  "    ###o###   ",
  "   #ooooooo#  ",
  "    ###o###   ",
  "      #o#     ",
  "      #o#     "
}

ändern. Du müßtest dann händisch die Koordinaten-Arrays anpassen. Ich hab’ das jetzt einfach “hingemalt”, und es könnte direkt so in die oben angedeutete Funktion reingefüttert werden, um diese Konfiguration zu erstellen.

Dass solche Spielfelder (also Array von Strings) dann leicht in Dateien geschrieben und gelesen werden können, könnte auch praktisch sein.

(Das ist nur grob angedeutet - bei sowas kann man in bezug auf Abstraktion und Verallgemeinerung beliebig weit gehen…)

Ah, okay, verstehe. Jetzt ergibt das Sinn. Ich frage mich, wie man auf sowas kommt. Brillant. :smiley: Als Narrensicher würde ich das nicht bezeichnen, weil ich mich schon bei der Belegung der Stringmap oft vertippe. :stuck_out_tongue: Das klingt in der Tat, nach einer Programmiervariante, die mir sehr zusagt.
Ich habe jetzt aktuell das hier dahingebaut:

		Tisch[] tischetemp = new Tisch[tischeNr.length];
		int i=0;
		for(int tischNr : tischeNr) {
			tischetemp[i++] = CafeMain.getTische().get(tischNr);
		}
		this.tische = tischetemp;
	}```

```public void setStuehle(int...stuehleNr) {
		Stuhl[] stuehletemp = new Stuhl[stuehleNr.length];
		int i=0;
		for(int stuhlNr : stuehleNr) {
			stuehletemp[i++] = CafeMain.getStuehle().get(stuhlNr);
		}
		this.stuehle = stuehletemp;
	}```

```sz.getTisch(0).setStuehle(11,12,13,0);
		sz.getTisch(1).setStuehle(1,2,12,13);
		sz.getTisch(2).setStuehle(2,3,13,14);
		sz.getTisch(3).setStuehle(3,4,5,14);
		sz.getTisch(4).setStuehle(4,5,15,16);
		sz.getTisch(5).setStuehle(5,6,16,17);
		sz.getTisch(6).setStuehle(6,7,17,18);
		sz.getTisch(7).setStuehle(7,18,19,20);
		sz.getTisch(8).setStuehle(7,8,20,21);
		sz.getTisch(9).setStuehle(8,9,21,22);
		sz.getTisch(10).setStuehle(9,10,22,23);
		sz.getTisch(11).setStuehle(9,10,11,0);
		sz.getStuhl(0).setTische(11,0);
		sz.getStuhl(1).setTische(1);
		sz.getStuhl(2).setTische(1,2);
		sz.getStuhl(3).setTische(2,3);
		sz.getStuhl(4).setTische(3,4);
		sz.getStuhl(5).setTische(3,4,5);
		sz.getStuhl(6).setTische(5,6);
		sz.getStuhl(7).setTische(6,7,8);
		sz.getStuhl(8).setTische(8,9);
		sz.getStuhl(9).setTische(9,10,11);
		sz.getStuhl(10).setTische(10,11);
		sz.getStuhl(11).setTische(11,0);
		sz.getStuhl(12).setTische(0,1);
		sz.getStuhl(13).setTische(0,1,2);
		sz.getStuhl(14).setTische(2,3);
		sz.getStuhl(15).setTische(4);
		sz.getStuhl(16).setTische(4,5);
		sz.getStuhl(17).setTische(5,6);
		sz.getStuhl(18).setTische(6,7);
		sz.getStuhl(19).setTische(7);
		sz.getStuhl(20).setTische(7,8);
		sz.getStuhl(21).setTische(8,9);
		sz.getStuhl(22).setTische(9,10);
		sz.getStuhl(23).setTische(10);```

Das ist jetzt die etwas kürzere Variante von meiner Anfangsvariante.

Ich werde mich mal an der StringMap versuchen, das sieht mir in der Tat um einiges seriöser für meinen Quellcode aus. Auch wenn es anfangs so seltsam erschien.

Vielen Dank Euch beiden für die Erläuterung!

Schönes Restwochenende
Gruß
Lukas