# Algorithmus im Spiel "vier gewinnt"



## g_a_d_ (28. Mrz 2006)

hallo, alle zusammen. Ich hab folgendes problem: Jeder kennt bestimmt das Spiel "4 gewinnt". Ich versuche  es in java zu programmieren und hab da ein kleines Problem. Da muss nach jedem Zug überprüft werden, ob 4 gleiche Chips horizontal , vertikal oder diagonal liegen. für vertikal und horizontal hab ich folgenden Quelltext:


```
public class Spielfeld
{
	Chip[][] spielfeld;;
	
	 public Spielfeld ()
    {
        spielfeld = new Chip[7][6];
        for (int j=0; j<=5; j++)
        {
            for (int i=0; i<=6; i++)
            {
                spielfeld[i][j]=null;
            }
        }
    }
    

...
	
public boolean gewinnzeile(Chip[][] spielfeld)
	{
	Chip[][] spfeld = new Chip[6][7];
		spfeld= spielfeld;
		for (int zeile=0; zeile<6; zeile++)		
			{int summe=1;
			for (int spalte=0; spalte<6; spalte++)
				{
				if(spfeld[zeile][spalte].equals(spfeld[zeile][spalte+1]) && spfeld[zeile][spalte] != null)	
					{summe=summe+1;}
					else {summe=1;}
						if(summe>=4)
				 		{return true;}
				
				}	
			}
			return false;
				
	}
	private boolean gewinnspalte(Chip[][] spielfeld)
	{
	Chip[][] spfeld = new Chip[6][7];
	spfeld=spielfeld;
	for (int spalte=0; spalte<7;spalte++)		
		{int summe=1;
			for (int zeile=0; zeile<6; zeile++)
			{
			if(spfeld[zeile][spalte].equals(spfeld[zeile+1][spalte])& spfeld[zeile][spalte] != null)	
				summe=summe+1;
				else summe=1;
					if(summe==4)
				 	return true;}
			}
		}
				
	return false;
	}
```
also ich vergleiche 2 benachbarte chips und wenn sie gleich und nicht leer sind, wird die summe um 1 erhöht bis die summe gleich 4 ist, wenn sie ungleich sind, wird sie auf 1 zurückgesetzt. 

hier noch ein Paar Sachen , die man vielleicht braucht:

```
public class Chip //deklariert die Klasse Chip 
{

	//Attribute
	public int nr; //es gibt zwei Arten von chips: Chip "1" (X)  und Chip "2" (O)
	public Spieler spieler;
//....

public class Spieler
{
    public String name;
   	public int nr;
    public Spieler (int nummer)
    {
        nr = nummer;
        if(nummer == 1)
            name = "Spieler X";
        else
            name = "Spieler O";
    }
```
wenn man das spiel startet, wird das spielfeld ausgegeben und nach der spaltennr. gefragt, danach kommt in diese spalte ein "X" (die chips haben enweder"X" oder "O")  , dann kommt aber die fehlermeldung :
Exception in thread "main" kava.lang.NullPointerException
at Spielfeld.gewinnzeile<Spielfeld.java:72> (das ist die Zeile: if(spfeld[zeile][spalte].equals(spfeld[zeile][spalte+1]) && spfeld[zeile][spalte] != null) ...
dann kommen die Zeilen , wo die methode gewinnzeile benutzt wird..

Also ist an  meinem Algorithmus mit großer Wahrscheinlichkeit irgendwas falsch. ich bin aber ein blutiger anfänger und kann den Fehler nicht finden vielleicht darf man zwei Objekte nicht mit "equals.()" vergleichen o.ä? vielleicht hilft mir jemand , plz Bitte, wenn möglich mit demselben Ansatz , über die Summe, also wenn zwei benachbarte Steine gleich sind , erhöhe die summe und überprüfe ob sie = 4 ist.. 

mfg, Alex


----------



## norman (29. Mrz 2006)

> ```
> for (int zeile=0; zeile<6; zeile++)
> {
> if(spfeld[zeile][spalte].equals(spfeld[zeile+1][spalte])& spfeld[zeile][spalte] != null)
> ```


hallo,
du gehst durch die schleife für zeile = 0 bis zeile=5, greifst aber an einer stelle auf spfeld[6][spalte] zu, nämlich im letzten durchlauf.
	
	
	
	





```
Chip[][] spfeld = new Chip[6][7];
```
dein spfeld geht in der ersten dimension aber nur von 0 bis 5. er kann also spfeld[6][irgendwas] nicht finden => NullPointerException

grüße


----------



## Johanness (29. Mrz 2006)

Also, ein Problem ist schon mal, daß equals angewendet auf null eine nullPointerException wirft. Und da Du im Constructor für Spielfeld alles auf null (überflüssigerweise, null ist sowieso der Default) setzt, hast Du genau dieses Problem.

Wenn Du in einer Condition auf ungleich null prüfen willst, solltest Du das als erstes tun. Dann bricht die Prüfung ab, wenn die Variable null ist.
Außerdem solltest Du Dich mal über 'equals' schlau machen, z.B. hier: 
http://www.galileocomputing.de/openbook/javainsel4/

Zum Beispiel könntest Du schreiben:


```
if (spfeld[zeile][spalte] != null
                        && spfeld[zeile][spalte + 1] != null
                        && spfeld[zeile][spalte].nr == (spfeld[zeile][spalte + 1].nr))
                  {
                     summe += 1;
                  } else
                  {
                     summe = 1;
                  }
```

Ich glaube eher nicht, daß Dein Algorithmus funktioniert, aber das musst Du selber ausprobieren.

Johannes


----------



## g_a_d_ (29. Mrz 2006)

Nun hab ich den Algorithmus in dieser Form:

```
public boolean gewinnzeile(Chip[][] s)
	{
	Chip[][] spfeld = new Chip[7][6];
		spfeld= s;
		for (int zeile=0; zeile<6; zeile++)		
			{int summe=1;
			for (int spalte=0; spalte<4; spalte++)
				{
				if((spfeld[zeile][spalte])==(spfeld[zeile][spalte+1])
				&& spfeld[zeile][spalte] != null
				&& spfeld[zeile][spalte+1] != null)	
					{summe=summe+1;	
					if(summe>=4)
				 	{return true;}}
					else {summe=1;}
					
				
				}	
			}
			return false;
				
	}
	private boolean gewinnspalte(Chip[][] s)
	{
	Chip[][] spfeld = new Chip[7][6];
	spfeld=s;
	for (int spalte=0; spalte<4;spalte++)		
		{int summe=1;
			for (int zeile=0; zeile<5; zeile++)
			{
			if((spfeld[zeile][spalte])==(spfeld[zeile+1][spalte])
			&& spfeld[zeile][spalte] != null
			&& spfeld[zeile+1][spalte] != null)	
				{summe=summe+1;
				if(summe==4)
				{return true;}}
				else {summe=1;}
					
			}
		}
				
	return false;
	}
```

Das Spiel laüft jetzt auch, es gibt keine Fehlermeldung, aber es gibt auch keinen Gewiner das heisst, es läuft unendlich lang

Hier noch mal alle Klassen, vielleicht ist der Fehler anderswo:



```
public class VierGewinnt //deklariert die Klasse VierGewinnt
{
	public static Spiel neuesspiel = new Spiel(); // ein neues Objekt der Klasse Spiel wird definiert

		public static void main(String [] args)
		{
		neuesspiel.start();		//Ein neues Spiel wird gestartet, in dem die Methode start()
								// der Klasse Spiel auf das Objekt neuesSpiel angewandt wird
								
		}
}
```


```
public class Spiel // deklariert die Klasse Spiel
{
	public Spielfeld spielfeld; 	//ein Objekt der Klasse Spielfeld wird deklariert
	public Spieler spieler1;		//ein Objekt der Klasse Spieler wird deklariert
 	public Spieler spieler2;		//ein Objekt der Klasse Spieler wird deklariert
	public Spieler aktuellerspieler;//ein Objekt der Klasse Spieler wird deklariert


	public Spiel() //Konstuktor Spiel() erzeugt ein neues Spielfeld, 2 neue Spieler
				   //und legt den 2. Spieler als aktuellen Spieler fest.
 	{
 		spielfeld = new Spielfeld(); //ein Objekt der Klasse Spielfeld wird mit dem Konstruktor erzeugt
 		spieler1 = new Spieler(1);	//ein Objekt der Klasse Spieler mit dem Konstruktor erzeugt
 		spieler2 = new Spieler(2);	//ein Objekt der Klasse Spieler mit dem Konstruktor erzeugt
 		aktuellerspieler = spieler2;//ein Objekt der Klasse Spieler mit dem Konstruktor erzeugt
 	}


	public void start()  //die "wichtigste Methode, die den Ablauf des Spiels steuert
	{
   		spielausgabe();  // Bildschirmausgabe des Spiels
   		int spalte; 	 //Variable spalte ist die Spalte, in die der Chip hineingewrofen wird
		do 
  		{
			spielerwechsel();// Nach jedem Zug wird der aktuller Spieler gewecheselt
			spalte = aktuellerspieler.chipsetzenspieler();  // spalte wird durch den Aufruf der Methode
															//chipsetzenspieler() geholt
			spielfeld.chipsetzenfeld(spalte, aktuellerspieler); //Der Chip wird auf den richtigen Platz
																//auf dem Spielfeld gesetzt
    		spielausgabe();										
  		}while(!gewinncheck(spalte));	//Das Spiel laüft solange der Gewinncheck negativ ist.
	}
	
	private void spielerwechsel() // der aktuelle Spieler wird gewcheslt
	{
  		if (aktuellerspieler == spieler1) 
  			aktuellerspieler = spieler2;      
  		else 
  			aktuellerspieler = spieler1;
  	}	
	private boolean gewinncheck(int spalte)  //Überprüft, ob das Spiel zu Ende ist      
	{
		if(spielfeld.istvoll()) //1.Fall: Das Spielfeld ist voll, Unentschieden. wird durch Anwenden 
								//der Methode istvoll() auf das spielfeld überprüft
		{
  			System.out.println("Das Spielfeld ist voll! Unentschieden!");
  			return true;	
		}
		if (spielfeld.gewinnzug())	//2.fall: Einer der Spieler hat einen Gewinnzug gemacht
		{							//wird durch die Methode gewinnzug überprüft
    	
    		Spieler spieler = spielfeld.gewinner(spalte); //Objekt der Klasse Spieler wird erstellt
    													  //das ist der Spieler, der gewonnen hat,
    													  //weil er den Rückwert der Methode gewinner() zugewisen bekommt 
    		System.out.println("Der Spieler "+ spieler.getname()  +" hat gewonnen");
    		return true;
		}
		return false;
	}
	public void spielausgabe()	//Methode für die Bildschirmausgabe	
 	{
     	spielfeld.spielfeldausgabe(); //die Methode Spielfeldausgabe wird auf das Objekt spielfeld angewandt
 	}
}
```


```
public class Spielfeld // Klasse Spielfeld wird definiert
{
	Chip[][] spielfeld;; //Array spielfeld der Klasse Chip
	
	 public Spielfeld ()
    {
       spielfeld = new Chip[7][6]; 	//Dimension des Arrays wird festgelegt(das Spielfeld besteht 
       								//aus 7x6 Objekte der Klasse Chip)
    }
    public boolean istvoll()		// Die Methode überprüft, ob das Spielfeld voll ist
    {
        for (int i = 0; i < spielfeld.length; i++ )
        {
            if (spielfeld[i][0] == null) 
            { 
            	return false; 
            }
        }
        return true;
    }
	public void spielfeldausgabe()  // Das Spielfeld wird augegeben. Wenn kein Chip vorhanden ist, 
    {								// wird ein Plazhalter "_" ausgegeben, sonst wir die Methode chipausgabe()
    	System.out.println();		// der Klasse Chip aufgerufen und für jede Koordinate im Array enweder "X" oder "O"
        for(int i = 0; i<=5; i++)	//ausgegeben
        {
            System.out.print("| ");
            for(int j = 0; j<=6; j++)
            {
               Chip chip = spielfeld[j][i];
                    if(chip == null)
                        System.out.print("_");
                    else
                        chip.chipausgabe();
                    System.out.print(" | ");
            }
            System.out.println();
        }
	System.out.println("-----------------------------");
    System.out.println("  1   2   3   4   5   6   7");
    System.out.println();
    }
    
    
    public boolean chipsetzenfeld(int spalte, Spieler aktuellerspieler) //ein neuer Chip wird mit dem Konstruktor Chip()
    {																	// erstellt und in dieser Methode an die
        for(int zeile = 5; zeile>=0; zeile--) 							// richtige Stelle im Array gesetzt
        {
            if(spielfeld[spalte-1][zeile] == null)						
            {														
                Chip chip = new Chip(aktuellerspieler);
                spielfeld[spalte-1][zeile] = chip;
                return true;
            }
        }
        return false;
    }	
    
    public Spieler gewinner(int spalte) //die Methoder ermittelt den Gewinner des Spiels und
    {									//hat logischerweise als Rückgabewert ein Objekt der
        int zeile = 0;					//Klasse Spieler
        while (spielfeld[spalte-1][zeile] == null)
        { 
            zeile++; 
        } 
        Chip chip = spielfeld [spalte-1] [zeile];     
        return chip.getspieler();
    }			
	
	public boolean gewinnzug () //Wenn ein Gewinn vorliegt - vier richtige in einer Reihe
								//(entweder in einer Spalte, einer Zeile oder einer Diagonalen) -
								//wird als Rückgabewert true zurückgegeben.
    {
  		if (gewinnzeile (spielfeld)) return true;
  		if (gewinnspalte (spielfeld)) return true;
		
  								//ansonsten ist der Rückgabewert false (kein Gewinn).

  		return false;
	}
	
	public boolean gewinnzeile(Chip[][] s) //Diese Methode überprüft, ob in einer Zeile 
	{										// 4 gleiche Chips vorliegen
	Chip[][] spfeld = new Chip[7][6];
		spfeld= s;
		for (int zeile=0; zeile<6; zeile++)		
			{int summe=1;
			for (int spalte=0; spalte<4; spalte++)
				{
				if((spfeld[zeile][spalte])==(spfeld[zeile][spalte+1])	//es wird überprüft ob in einer Zeile
				&& spfeld[zeile][spalte] != null					//2 gleiche Chips vorliegen. wenn ja, wird die
				&& spfeld[zeile][spalte+1] != null)					//variable summe um 1 höher gesetzt. wenn die Summe 4 erreicht
					{summe=summe+1;									//wird als Wert "true" zurückgegeben, wenn nicht dann "false"
					if(summe>=4)
				 	{return true;}}
					else {summe=1;}
					
				
				}	
			}
			return false;
				
	}
	private boolean gewinnspalte(Chip[][] s)				//Diese Methode überprüft, ob in einer Spalte
	{														// 4 gleiche Chips vorliegen
	Chip[][] spfeld = new Chip[7][6];	
	spfeld=s;
	for (int spalte=0; spalte<4;spalte++)		
		{int summe=1;
			for (int zeile=0; zeile<5; zeile++)
			{
			if((spfeld[zeile][spalte])==(spfeld[zeile+1][spalte])	//es wird überprüft ob in einer Spalte
			&& spfeld[zeile][spalte] != null						//2 gleiche Chips vorliegen. wenn ja, wird die
			&& spfeld[zeile+1][spalte] != null)						//variable summe um 1 höher gesetzt. wenn die Summe 4 erreicht
				{summe=summe+1;										//wird als Wert "true" zurückgegeben, wenn nicht dann "false"
				if(summe==4)
				{return true;}}
				else {summe=1;}
					
			}
		}				
	return false;
	}
		


	
}
```


```
public class Chip //deklariert die Klasse Chip 
{

	public int nr; 			//Die Chips haben entweder den Wert 1 (für "Farbe" "X")  oder 2 (für "Farbe" "O")
	public Spieler spieler; //Obejkt der Klasse Spieler wird erzeugt, damit jedem Chip
							//der zugehörige Spiler zugewiesen werden kann
	


	public Chip (Spieler aktuellerspieler) //Konsruktor, der dem Chip den Spieler und den 
											//Wert 1( oder 2 zuweist (also die "Farbe" des Chips)
	{
		nr = aktuellerspieler.getspielernr(); //setzt den Wert des aktuellen Chips gleich der Nummer des Spielers
		spieler = aktuellerspieler; //weist dem Chip den aktullen Spieler zu
	}

	public int getchipnr() //gibt den Wert des Chips zurück
	{
 		return this.nr;
	}

	public Spieler getspieler() // gibt ein  Objekt der Klasse Spieler zurück
	{
		return this.spieler;
	}
	public void chipausgabe() 	// Der Wert des Chips 1 bzw. 2 wird auf dem Bildschirm
								// durch die Methode als "X" bzw. "O" ausgegeben
 	{
  		if(this.getchipnr() == 1)
   			System.out.print("X");
  		else
   			System.out.print("O");
 	}
}
```


```
public class Spieler //deklariert die Klasse Spieler
{
    public String name;
   	public int nr;
    public Spieler (int nummer) // Konstruktor Spieler: jedem Spieler wird die Nummer 1 bzw. 2 in der Klasse 
    							// Spiel zugewiesen, Nummer 1 bekommt den Namen "Spieler X", Nummer 2- "Spieler O" 
    {
        nr = nummer;
        if(nummer == 1)
            name = "Spieler X";
        else
            name = "Spieler O";
    }
    
    public String getname() // Gibt den Namen des Spielers zurück
    {
        return this.name;
    }
	public int getspielernr() //Gibt die Nummer des Spielers zurück
    {
        return this.nr;
    }

	public int chipsetzenspieler() // Methode, die vom Spieler die Spalte abfragt
	{
	
	int spalte;
	System.out.println(this.getname()+", geben Sie bitte die Spaltennummer ein:");
	spalte=Tools.intEingabe();
	return spalte;
	}
}
```


----------

