# [Spiel] Kartenspiel Leben und Tod Tips und Probleme



## MrChT (11. Jan 2011)

Hey,

nachdem ich gebeten wurde, einen neuen Thread zu diesem Thema zu öffnen, bin ich hier also mit meinen Anfängerfragen.
Hier mal die Aufgabe:

Spezifikation eines Computerspiels
Die allgemeinen Spielregeln:
Hierbei handelt es sich um eine ganz einfache Variante des Spiels "Leben und Tod". Das
Spiel wird mit zwei Spielern gespielt. Jeder der Spieler erhält einen Kartenstapel, indem ein
Kartenspiel ausgeteilt wird. Von diesen Stapeln wird jeweils die oberste Karte gezogen und
mit der Karte des Gegners verglichen. Der Spieler mit der höheren Karte erhält beide Karten,
die er auf einen Ablagestapel legt. Die Reihenfolge der Karten ist: 7, 8, 9, 10, B, D, K, As. Bei
gleichem Wert entscheidet die Farbe, hier gilt: Karo, Herz, Pik, Kreuz. Ist ein Kartenstapel zu
Ende, wird mit dem Ablagestapel weitergespielt. Das Spiel ist nach einer festgelegten Anzahl
von Runden (oder wenn ein Spieler keine Karten mehr hat) zu Ende. Gewonnen hat der
Spieler, der am Ende mehr Karten besitzt.
Die Realisierung am Computer:
Es spielen Computer und Spieler gegeneinander. Es gibt keine Strategie, sondern das Spiel
läuft nach dem Geben der Karten voll deterministisch ab. Deshalb kann per
Computerprogramm schnell entschieden werden, wer das Spiel gewinnt. Damit Sie trotzdem
den Spielverlauf verfolgen können, sollte eine geeignete Ausgabe erfolgen (z.B. jeweils die
beiden gezogenen Karten) und jeder Spielzug mittels Drücken der Enter-Taste so verzögert
werden, dass am Bildschirm der Spielverlauf nachvollzogen werden kann.
Tipps:
1. Betrachten Sie das ganze erst mal unter objektorientiertem Aspekt: Gespielt wird ein
Spiel. Zu einem Spiel gehören zwei Spieler. Jeder Spieler bekommt einen Kartenstapel
(klingt doch irgendwie nach Stack), von dem er eine Karte zieht (klingt nach pop()). Wenn
er die höhere Karte hat, legt (klingt nach push()) er die beiden Karten auf seinen
Ablagestapel. Wenn der Kartenstapel zu Ende ist, wird der Ablagestapel zum
Kartenstapel gemacht, usw ... Dann wird schnell klar, welche Objekte, mit welchen
Elementen und Elementfunktionen Sie brauchen.
2. Programmieren Sie nicht alles auf einmal, sondern überprüfen Sie immer wieder ihre
Zwischenergebnisse. Nur ein paar Beispiele: Statt zu mischen, initialisieren Sie die
Anordnung der Karten erst mal "fest verdrahtet" im Programm. Arbeiten Sie erst mal mit
Stapeln, die aus ganz wenigen Karten bestehen, dann kann der Spielverlauf leicht
kontrolliert werden. Statt mit einer komplizierten Klasse Karte können Sie auch erst mal
mit einer Karte, die aus einfachen Integerwerten besteht arbeiten und erst in einem
zweiten Schritt eine Klasse Karte mit allen Details einführen. Für das Bestehen des
Testats reicht eine ganz einfache (allerdings objektorientierte) Version, im Notfall auch
mit Integer-Karten etc. – Hauptsache Sie programmieren selbst.
3. Wenn Ihr Programm nicht das tut, was es soll, dann verfolgen Sie den Spielverlauf
mittels zusätzlicher Ausgaben (die Sie am Ende wieder löschen müssen) solange, bis Sie
den Fehler gefunden haben.
Zusatz:
Wer Lust hat und es sich zutraut, kann auch das wirkliche Spiel "Leben und Tod"
programmieren.

1. 
Um den Kartenstapel zu erzeugen benutze ich Integer-Variablen, ein Array, und am Ende ein Stack, wegen der einfachen Handhabung.
2.
Mit Math.random erzeuge ich Zufallszahlen, mit verschachtelten for und if-Schleifen überprüfe ich, ob die erzeugte Zahl im Array schon vorhanden ist. Aussehen tuts so:


```
import static java.lang.Math.*;

public class TestGenCard
{
	public static void main(String[] args)
	{
		int card = 0;
		int arrnr = 0;
		int [] forbatch = new int[32];

		for (int fill = 0; fill < (forbatch.length + 1); fill++)
		{
			card = (int) (random() * 31);
	
			for (int check = 0; check < forbatch.length; check++)
			{
				if (card == forbatch[arrnr])
				{
					break;
				}
				else 
				{
					arrnr++;
					if (arrnr == 31)
					{					
						forbatch[arrnr] = card;
						break;
					}
				}
			}
		}
		System.out.println(forbatch[0]);
	}
}
```

Compiler machts so wie er soll. Programm gestartet, jetzt habe ich eine OutOfBoundsException 
Was hab ich falsch gemacht???

Sorry wegen den Bezeichnungen ich bin nicht so der einfallsreiche Typ.

Mit freundlichen Grüßen


----------



## Quaxli (11. Jan 2011)

Du solltest das nicht alles in die Main-Methode packen, sondern mit Klassen und Methoden arbeiten.

Zu Deinem Fehler: Der IndexOutOfBounds-Fehler resultiert aus dieser Zeile:


```
for (int fill = 0; fill < (forbatch.length + 1); fill++)
```

Ein Array beginnt beim Feld mit dem Index 0. Entsprechend hat ein Array[32] die Felder 0 - 31.
Wenn Du, wie oben die Bedingung mit 


```
fill < (forbatch.length+1)
```

definierst, wird der Fehler genau dann geworfen, wenn Dein Programm versucht auf das Feld mit dem Index 32 zuzugreifen, welches nicht existiert.


----------



## Network (11. Jan 2011)

@Quaxli's-Antwort: Vom Prinzip stimme ich dem zu.
Aber was den Fehler selbst betrifft nicht! Hast ja alles richtig gemacht was das betrifft.

Du solltest vieleicht in Zeile 14

```
arrnr = 0
```
hinzufügen.
Denn arrnr wird ja jedesmal auf 1 aufgezählt. Nach der ersten "31" wird aber dein arrnr nicht wieder auf "0" zurückgesetzt. Der Code ab Zeile 11 beginnt wieder von vorn und wieder zählt weiter ab der Zahl 31!


PS: Warum überschreibst du eig. jedesmal die 31. Stelle neu? Die anderen Stellen werden ja überhaupt nie gefüllt(?)


----------



## MrChT (11. Jan 2011)

Danke euch schon mal die Exception ist weg.

@Quaxli:
Ich habe das Spiel in Klassen programmiert, aber die Class Stack herrauskopiert, um sie zu testen, wobei dann die Exception auftrat. 

@Network:
Das wäre meine nächste Frage gewesen. Ich müsste in den Schleifen die Arrayvariable "arrnr" hochzählen lassen. Allerdings benutze ich ja eben diese um das Array auf doppelte Werte zu testen.

Kann sein, dass ich Tomaten auf den Augen habe, aber ich komm nicht drauf wie ich das machen kann, weil ich ja "arrnr" nicht einfach hochzählen lassen kann, weils im nächsten Schleifendurchlauf wieder geändert wird.

Freundlichste Grüße


----------



## Network (11. Jan 2011)

Aber dass du es hochzählst ist doch gerade das Problem! (?)

In der 2. Zeile zählst du 31mal arrnr um 1 hoch. Die Schleife wird dann gebreakt! Die Hauptschleife ruft jetzt wieder die 2. Schleife auf. Die beginnt dann weiterhin von 31 auf zu zählen... und frägst dann die 32. Stelle ab, bzw. versuchst alles ab 31+ abzufragen.

Ums zu verdeutlichen ein Programmdurchlauf: (grob)
- arrnr = 0
- 1. Schleife wird gestartet
- 2. Schleife wird gestartet
- ... 31x arrnr + 1 ...
- bis arrnr = 31
- Schleife wird unterbrochen
- arrnr ist jetzt 31
- 1. Schleife beginnt von vorn
- 2. Schleife wird gestartet
- arrnr++
- arrnr ist jetzt 32
- 2. Schleife beginnt von vorn
- Wenn card == forbatch[arrnr = 32]
<<<<< Fehlermeldung >>>>>
Es gibt keine 32. stelle von forbatch


----------



## MrChT (11. Jan 2011)

Ja, dass habe ich schon ausgebessert. Die Schleife zählt bis zur 31, von 0 - 31, soweit hab ichs verstanden und ausgebessert, nur brauch ich die Variable ja 2 mal. Einmal für die Schleife für den Test, was jetzt auch läuft, hab also ne zufällige Zahl im Array, aber leider immer nur auf "Platz" 0, weil ich ja die Variable immer auf Null setzen muss.

Mein Problem ist jetzt, ob bzw wie ich die Variable in jeder Runde um 1 hochzusetzen und gleichzeitig zur Überprüfung nutzen kann.

Freundlichste Grüße


----------



## Network (11. Jan 2011)

Ahhh jetzt verstehe ich was du meinst(denke ich).
Ich verstehe nur nicht was es daran nicht zu verstehen gibt...

Warum willst du nur EINE Variable verwenden? Besonderst da du ja bereits "check" auch initialisiert hast!


```
for (int fill = 0; fill < (forbatch.length + 1); fill++)
      {
            card = (int) (random() * 31);
    
            for (int check = 0; check < forbatch.length; check++)
            {
                if (card == forbatch[check])
                {
                    break;
                }
                else 
                {
                    if (check == 31)
                    {                   
                        forbatch[arrnr] = card;
                        arrnry++;
                        break;
                    }
                }
            }
        }
```


----------



## MrChT (11. Jan 2011)

Ui, weil ich dachte die Variable in "forbatch[x]" muss immer die selbe sein, aber so wäre das natürlich echt super.
Danke dafür


----------

