# zirkuläre LinkedList



## tom003 (29. Apr 2008)

Hallo Leute!

Eine kleine Frage zur LinkedList:
Ist es möglich aus einer normalen LinkedList eine zirkuläre Liste zu machen?
Also ich bräuchte eine Liste, die nach dem letzten Element wieder bei index 0 beginnt.
Bzw. gibt es Alternativen dazu?

Kleine Hintergrundinformation:
Ich programmiere gerade an einem "Mensch ärger dich nicht" Spiel, bei dem alle Spielfelder in einer LinkedList abgespeichert sind. Dabei durchläuft jede Figur diese Liste von Feldern. Dabei kommt es jedoch zu dem Problem, dass z.B.: die Startposition des 3. Spielers in der Mitte der Liste ist und der 3. Spieler somit keine ganze Runde absolvieren kann, da der Index außerhalb des Arraybereichs läuft. Darum soll die Figur, während des Durchlaufens wieder bei index 0 beginnen.

Edit: Sry, ich glaube ich hab im falschen Forum gepostet. Wollte eigentlich ins Anfängerforum  

mfg Thomas


----------



## SlaterB (29. Apr 2008)

das ist doch eine recht normale Anforderung, 
warum deshalb irgendwelche grundlegenden Klassen umbauen?

wenn überhaupt dann programmiere dir einen eigenen Iterator für die Liste,
die beim letzen Element einen neuen Iterator anfragt und von vorne anfängt, transparent für den Aufrufer,

oder im Programm selber auf das Ende reagieren,
wie ist denn dein bisheriger Code an dieser Stelle?


----------



## tom003 (29. Apr 2008)

Also das mit dem Iterator ist mir neu. Wie funktioniert das?

Naja auf das Ende reagieren würde den Code mindestens verdoppeln, da ich, bei if-Abfragen ,immer wenn der Index außerhalb liegt, dieselbe Abfrage mit verändertem Index machen müsste.

Hier zum Beispiel ein kleiner Codeausschnitt in dem der Index überläuft
sf.felder sind die Felder auf dem Spielbrett (in einer LinkedList, die zirkulär werden soll)
gedrF ist die gedrückte Figur die vorwärts bewegt werden soll


```
if (sf.felder.get(sf.felder.indexOf(gedrF) + wuerfelBenutzer).belegt == false)
 {
      sf.felder.get(sf.felder.indexOf(gedrF) + wuerfelBenutzer).color = sf.felder.get(sf.felder.indexOf(gedrF)).color;
      sf.felder.get(sf.felder.indexOf(gedrF) + wuerfelBenutzer).belegt = true;
 }
 else
 {
      schlagen(sf.felder.get(sf.felder.indexOf(gedrF)), sf.felder.get(sf.felder.indexOf(gedrF) + wuerfelBenutzer));
 }
```


----------



## SlaterB (29. Apr 2008)

sf.felder.get(sf.felder.indexOf(gedrF))
oder 
sf.felder.get(sf.felder.indexOf(gedrF) + wuerfelBenutzer)
solltest du in allen denkbaren Fällen nicht mehrmals schreiben,
sowas macht jeden Code kaputt

ordentliches Programmieren sieht so aus:
int currentIndex = ..;
int nextIndex = ..;
Feld current = ..;
Feld next = ..;

an dieser Stelle musst du nur einmal die Berechnung von nextIndex anpassen:
statt (current + wuerfelBenutzer) muss es eben
((current + wuerfelBenutzer) % anzahlFelder) heißen,

schon wird bei 20 Feldern bei 17+6 3 statt 23 rauskommen,
wenn du es doch an mehreren Stellen brauchst, dann schreibe dir eine Operation:
int nextIndex = calculateNextIndex(currentIndex,wuerfelBenutzer);
fertig


----------



## Marco13 (30. Apr 2008)

Hm. Mit einem Iterator wird man da wohl nicht so weit kommen. Spätestens, wenn man mal kurz das nächste Feld angucken will, ist der eher unpraktisch. (Genaugenommen immer dann, wenn man nicht von Anfang bis Ende durchlaufen will)

Das Problem ist ja, dass man nicht EINE Liste hat, sondern 4. Die meisten Elemente dieser Listen sind gleich (d.h. liegen auch noch in jeweils 3 anderen Listen). Man könnte auch sagen, dass die Liste "4 Anfänge und 4 Enden" hat. Du hast jetzt über die Klassenstruktur nichts gesagt, aber ... es wäre IMHO einfach un bequem (nicht "schön" oder "elegant", aber einfach), wenn jedes Feld 4 Referenzen auf seine Nachfolger enthalten würde (für jeden Spieler eine). Aber es gibt noch 1000 andere (auch schönere) Möglichkeiten...


----------



## Gast (30. Apr 2008)

Normaler Weise macht man das, in dem man modulo rechnet:


```
int anzFelder = 40;
List felder = new ArrayList( anzFelder );

felder.get( ( sf.felder.indexOf(gedrF) + wuerfelBenutzer ) % anzFelder );
```

Der Modulo Operator funktioniert so [1]:

% Modulo-Operator, errechnet den Rest einer Division. Also: 5%2=1, weil 5/2=2 Rest 1

-Tim

[1] de.wikibooks.org/wiki/Java_Standard:_Operatoren


----------



## Marco13 (30. Apr 2008)

Das Hilft nur bedingt: Man steht mit einer Figur vor dem Roten "Haus" (die 4 Zielfelder). Nun bewegt man sich einen Schritt nach vorne. Wo geht man hin? Das hängt davon ab, welche Farbe die Figur hat: Eine Rote Figur geht ins "Haus", eine Blaue läuft einfach geradeaus weiter...


----------



## Guest (30. Apr 2008)

Also das mit dem Modolo Operator funktioniert schon mal ganz gut, nur ist jetzt, wie Marco 13 schon erwähnt hat, das Problem, dass man schlecht überprüfen kann ob ein Spieler bereits am "Ziel" ist. Hab mir gedacht dass man für jedes Feld noch eine Zählvariable mitgeben könnte, die die Würfelsummen aufsummiert. Wenn er nun über die Zahl 40 (da es 40 Felder gibt) kommt, muss er seine Figur in seinem "Haus" positionieren.
Oder hat jemand einen anderen Vorschlag? 

Das mit der Liste sieht so aus: Ich habe nur 1 Liste für die Felder auf dem Spielbrett selbst. Und diese Liste wird auch immer wieder gezeichnet, wenn sich eine Position ändert. Außerdem habe ich noch eine Liste für die 4 Startfelder und eine Liste für die 4 Zielfelder

Zur Klassenstruktur:


```
public class Feld {
    
    int xcord;
    int ycord;
    Color color;
    boolean belegt = false;
    Color standardfarbe;
    
    /** Creates a new instance of Feld */
    public Feld(int xcord,int ycord, Color color,boolean belegt, Color standardfarbe) 
    {
        this.xcord = xcord;
        this.ycord = ycord;
        this.color = color;
        this.belegt = belegt;
        this.standardfarbe = standardfarbe;
    }
    
}
```



```
public class Spieler 
{ 
    String art;                    //KI oder Benutzer
    int spielerindex;            //1, 2, 3 oder 4
    Color spielerfarbe;
    
    Spieler (String art, int spielerindex, Color spielerfarbe)
    {
        this.art = art;
        this.spielerindex = spielerindex;
        this.spielerfarbe = spielerfarbe;
    }
}
```


So wird gezeichnet

```
public class Spielfeld extends JPanel
{

    int[] xcords = new int[]{20, 60, 100, 140, 180, 180, 180, 180, 180, 220, 260,
        260, 260, 260, 260, 300, 340, 380, 420, 420, 420, 380, 340, 300, 260, 260, 260, 260,
        260, 220, 180, 180, 180, 180, 180, 140, 100, 60, 20, 20
    };
    
    int[] ycords = new int[]{180, 180, 180, 180, 180, 140, 100, 60, 20, 20, 20,
        60, 100, 140, 180, 180, 180, 180, 180, 220, 260, 260, 260, 260, 260, 300, 340, 380,
        420, 420, 420, 380, 340, 300, 260, 260, 260, 260, 260, 220
    };    
    
    int[] xcordsStart = new int[]{20, 60, 20, 60, 380, 420, 380, 420, 380, 420, 380, 420, 20, 60, 60, 20};
    int[] ycordsStart = new int[]{20, 20, 60, 60, 20, 20, 60, 60, 380, 380, 420, 420, 380, 380, 420, 420};
    int[] xcordsEnde = new int[]{60, 100, 140, 180, 220, 220, 220, 220, 260, 300, 340, 380, 220, 220, 220, 220};
    int[] ycordsEnde = new int[]{220, 220, 220, 220, 60, 100, 140, 180, 220, 220, 220, 220, 260, 300, 340, 380};
    LinkedList<Feld> felder = new LinkedList<Feld>();
    LinkedList<Feld> startfelder = new LinkedList<Feld>();


    /** Creates a new instance of Spielfeld */
    public Spielfeld()
    {        
        for (int a = 0; a < xcords.length; a++)
        {
            felder.add(new Feld(xcords[a], ycords[a], 0, Color.WHITE, false, Color.WHITE));
        }     

        for (int i = 0; i < xcordsStart.length; i++)
        {
            if (i >= 0 && i <= 3)
            {
                startfelder.add(new Feld(xcordsStart[i], ycordsStart[i], 0, Color.RED, true, Color.RED));
            }
            if (i >= 4 && i <= 7)
            {
                startfelder.add(new Feld(xcordsStart[i], ycordsStart[i], 0, Color.BLUE, true, Color.BLUE));
            }
            if (i >= 8 && i <= 11)
            {
                startfelder.add(new Feld(xcordsStart[i], ycordsStart[i], 0, Color.GREEN, true, Color.GREEN));
            }
            if (i >= 12 && i <= 15)
            {
                startfelder.add(new Feld(xcordsStart[i], ycordsStart[i], 0, Color.ORANGE, true, Color.ORANGE));
            }

        }
    }

    @Override
    public void paintComponent(Graphics g)
    {
        g.setColor(new Color(244, 248, 114));
        g.fillRect(0, 0, 470, 470);

        for (int i = 0; i < xcords.length; i++)
        {
            g.setColor(this.felder.get(i).color);
            g.fillOval(xcords[i], ycords[i], 30, 30);
            g.setColor(Color.BLACK);
            g.drawOval(xcords[i], ycords[i], 29, 29);
        }

        for (int j = 0; j < xcordsStart.length; j++)
        {
            g.setColor(this.startfelder.get(j).standardfarbe);
            g.fillOval(xcordsEnde[j], ycordsEnde[j], 30, 30);
            g.setColor(this.startfelder.get(j).color);
            g.fillOval(xcordsStart[j], ycordsStart[j], 30, 30);
            g.setColor(Color.BLACK);
            g.drawOval(xcordsStart[j], ycordsStart[j], 29, 29);
            g.drawOval(xcordsEnde[j], ycordsEnde[j], 29, 29);

        }
```



Und noch eine Main Klasse in der das eigentliche Spiel abläuft


----------



## Marco13 (30. Apr 2008)

Das mit Zähler wäre eine Möglichkeit. Sogar "geschickter" als mit den Farb-spezifischen next-Pointern. Wie genau du das mit der "Zählvariable" machen willst, ist aber noch nicht klar. Man bräuchte ja für jede Spiel_figur_ einen solchen Zähler. Eine Klasse "Spielfigur" hast du bisher nicht (wäre aber vielleicht nicht verkehrt - dann hätte das "Feld" einen Member "Spielfigur" die 'null' ist, wenn das Feld frei ist usw. ...)

BTW: Fields sollten IMMER private sein.


----------

