# Vier-Gewinnt-Problem



## Anninha (15. Aug 2007)

Hallo liebe Leute,
Ich brauche unbedingt Hilfe bei einem Java-Projekt für die Uni, das ich schon bald abgeben muss.
Ich mache zum ersten Mal ein Java-Programm und es lief bis jetzt auch ganz gut, aber jetzt komme ich absolut nicht weiter. Ich weiß nämlich nicht, wo der Fehler liegt, dass vier Steine in einer Reihe manchmal nicht erkannt werden.
Wenn ihr den ganzen Quelltext sehen wollt, wäre es lieb, mir eure E-mail-Adresse zu geben, dann schick ich euch das ganze Programm. Die Logik kann ich schonmal hier reinstellen, vielleicht ist da ja schon der Fehler drin.
Vielen Dank für eure Hilfe!
Anna


```
public boolean vierFinden (int y, int x, int spieler) 
			 { 
	                boolean b1 = vierFindenX(y, x, spieler); 
	                boolean b2 = vierFindenY(y, x, spieler); 
	                boolean b3 = vierFindenD1(y, x, spieler); 
	                boolean b4 = vierFindenD2(y, x, spieler); 
	                
	                return (b1 || b2 || b3 || b4); 
	      
			
			 }
			 
			// Diese Methode soll das Spielfeld danach durchsuchen, ob 4 in einer Reihe sind.
			// aufteilen in 4 Methoden - vertikal, horizontal, diagonal nach rechts unten und links oben 
			 
			 
			 boolean vierFindenX(int y, int x, int spieler) 
			 { 
	                // nach links 
	                int start = x - 1; // mit dem Punkt links neber dem gesetzten beginne 
	                                                        // ich 
	                int treffer = 1; // der gesetzte Punkt = 1 Treffer 
	                
	                while (start >= 0) 
	                { 
	                         
	                        	if (spielfeld[y][start].gibSpieler() != spieler)
	                        		
	                                break; 
	                        
	                        start--; 
	                        treffer++; 
	                } 

	                // nach rechts 
	                start = x + 1; 
	                
	                while (start < spielfeld.length) 
	                { 
	                         
	                        	if (spielfeld[y][start].gibSpieler() != spieler)
	                        		
	                                break; 
	                        
	                        start++; 
	                        treffer++; 
	                } 

	                return (treffer > 3);
	                
			 } 
			
			 
			 boolean vierFindenY (int y, int x, int spieler)
			 {
				 // nach oben
				 int start = y - 1;
				 int treffer = 1;
				 
				 while (start >= 1)
				 {
					
						 if (spielfeld[start][x].gibSpieler() != spieler)
							 
							 break;
					 start--;
					 treffer++;
				 }
				 
				 //nach unten
				 
				 start = y + 1;
				 treffer = 1;
				 
				 while (start < spielfeld.length)
				 {
					 
						 if (spielfeld[start][x].gibSpieler() != spieler)
							 
							 break;
					 start++;
					 treffer++;
				 }
				  
				 return (treffer > 3);
			 }
			 
			 
			 boolean vierFindenD1(int x, int y, int spieler)
			 // von links unten nach rechts oben -> richtig.
			 
			 {
				 int start = x + 1;
				 int start2 = y - 1;
				 int treffer = 1;
				 
				 while ((start < spielfeld.length) && (start2 >=1))
				 {
					
						 if (spielfeld[start2][start].gibSpieler() != spieler) 
							 break;
					 start++;
					 start2--;
					 treffer++;
					 
				 }
				 
				// von rechts oben nach links unten -> richtig
				 
				start = x - 1;
				start2 = y + 1;
				
				while ((start >= 0) && (start2 < spielfeld.length))
				{
					
						 if (spielfeld[start2][start].gibSpieler() != spieler) 
							 break;
					start--;
					start2++;
					treffer++;
				}
				 
				return (treffer > 3);
					 
			 }
			 
			 
			 boolean vierFindenD2 (int x, int y, int spieler)
			 
			 {
				 //von links oben nach rechts unten
				 int start = x + 1;
				 int start2 = y + 1;
				 int treffer = 1;
				 
				 while ((start < spielfeld.length) && (start2 < spielfeld.length))
				 {
					
						 if (spielfeld [start2] [start].gibSpieler() != spieler)
							 break;
					 start++;
					 start2++;
					 treffer++;
					
				 }
				 
				 //von rechts unten nach links oben
				 start = x - 1;
				 start2 = y - 1;
				 
				 while ((start >= 0 && start2 >= 1))
				 {
					
						 if (spielfeld [start2] [start].gibSpieler() != spieler)
							 break;
					 start--;
					 start2--;
					 treffer++;
				 }
				 
				 return (treffer > 3);
				
			 }
			 
			 
			 public void beenden(int x, int y, int spieler)
			 {
				  if(vierFinden(x, y, spieler)) 
				  {	// Hat jmd gewonnen? 
					  for( y=0; y<1; y++) // y liegt unter 1. 
						{
				  		for (x=0; x<7; x++)
				  			{     
				  				spielfeld[y][x].removeActionListener(this); // this = für jedes einzelne Feld
				  				spielfeld[y][x].setBackground(Color.WHITE);
				  			}

						} 
					  
					  System.out.println("Spieler "+spieler+" hat gewonnen"); 
					  
				  }
			 
			 }
```


----------



## SlaterB (15. Aug 2007)

Tipp: lasse dein Programm mit dir sprechen,

du wunderst dich, dass der Test mal geht und mal nicht?
dann finde heraus, WARUM jeweils das eine oder andere Ergebnis erzielt wurde,
ein Log:


System.out.println("untersuche nun Sieg in alle Richtungen von Feld x y aus");
System.out.println("prüfe waagerecht");
System.out.println("Felde x, y ist  .. -> Trefferanzahl = c [oder Abbruch für waagerecht]");
usw usf

für jeden fraglichen Schritt deines Programmes Ausgaben an den richtigen Stellen,
damit du nicht zu viel Arbeit hast, kannst du erstmal auf hohem Level mit wenigen Ausgaben anfangen, z.B. b1/ b2/ b3 /b4 ausgeben

wenn du dann siehst, dass sich b2, also senkrecht, merkwürdig verhält, dann untersuchst du das genauer


----------



## Anninha (15. Aug 2007)

Danke für den Tipp!!!!!!!! Tausendmal! Jetzt klappt´s!


----------



## Anninha (15. Aug 2007)

Jetzt hab ich gleich die nächste Frage: Wie setzt man mit ImageIcon GIF-Bilder auf die Spielfeld- JButtons?


----------



## SlaterB (15. Aug 2007)

schaue dir die Beispiele hier an:
http://java.sun.com/docs/books/tutorial/uiswing/components/button.html
http://java.sun.com/docs/books/tuto...tonDemoProject/src/components/ButtonDemo.java


----------



## Anninha (16. Aug 2007)

Danke für den Tipp, ich werd´s mir nochmal anschauen, auch wenn ich so meine Problemchen mit der JDK hab.

Ich hab jetzt erstamal noch ein Fenster mit den Spielregeln erstellt (Klasse Regelfenster) und will jetzt, dass das in der Menüleisten-Klasse aufgerufen wird, genau wie z.B. wenn man auf "Ende" klickt das Spiel beendet wird. 
Das Problem ist, dass der ActionListener nicht mit throw klarkommt. Auch wenn ich schreibe:


```
if(kommando.equals("Regeln"))
	    {
	    	new Regelfenster();
	    }
```

und kein Fehler angezeigt wird, wird das Regelfenster nicht geöffnet. 
Könnt ihr mir sagen, wie ich das Regelfenster aufrufen kann?



```
package Projekt;
/*
 * 
 */

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;







/**
 * @author Anna
 */

public class Menueleiste extends JMenuBar implements ActionListener 
{ 
	
	private static final long serialVersionUID = 1L;
	
	JMenuBar menueleiste;
	
	public Menueleiste ()
	{
	
		setMenuBar();
	}
	
	

	public JMenuBar setMenuBar() 
	{
		
		
		JMenuItem mi_neu = new JMenuItem ("Neues Spiel");
			mi_neu.addActionListener (this);
			mi_neu.setActionCommand("Neues Spiel");
				
		JMenuItem mi_ende = new JMenuItem ("Ende");
			mi_ende.addActionListener (this);
			mi_ende.setActionCommand("Ende");
			
		JMenuItem mi_regeln = new JMenuItem ("Regeln");
			mi_regeln.addActionListener (this);
			mi_regeln.setActionCommand("Regeln");
			
			
			
		JMenu m_spiel = new JMenu ("Spiel");
		JMenu m_hilfe = new JMenu ("Hilfe");
		
		m_spiel.add(mi_neu);
		m_spiel.add(mi_ende);
		m_hilfe.add(mi_regeln);
		
		
		JMenuBar menueleiste = new JMenuBar();
		
		menueleiste.add(m_spiel);
		menueleiste.add(m_hilfe);
		
		menueleiste.setVisible(true);
		
		return menueleiste;
		
		
	}
	
	public void actionPerformed(ActionEvent event) 
	  {
	  	
	    String kommando = event.getActionCommand();
	    System.out.println( "Kommando = " + kommando );

	    if( kommando.equals( "Ende" ) )
	    {
	      System.exit( 0 );	 
	    }	

	    //funktioniert noch nicht
	    if( kommando.equals( "Neues Spiel" ) )
	    {  	
	    	new Spiel();
	    }	
	    
	    if(kommando.equals("Regeln"))
	    {
	    	new Regelfenster();
	    }
	    
	  }

	
	  
}
```



```
package Projekt;

import java.awt.*;
import javax.swing.*;



class Regelfenster extends JPanel 

{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;



	public Regelfenster() 
	{
	
	}

	public static void main(String args[]) throws Exception 
	{
	

	JFrame regelf = new JFrame("Regeln");
	
	
	String text =
	
	"<h1>Spielregeln</h1>

 Vier Gewinnt ist ein Spiel für zwei Personen. Durch einen Klick in die oberste " +
	"Leiste des Spielfelds wird ein Spielstein in die unterste Reihe der Spalte gesetzt. Die Spieler setzen " +
	"abwechselnd ihre Steine. Gewonnen hat, wer als erster 4 seiner Steine diagonal, vertikal oder horizontal in " +
	"eine Reihe bringt. </p>[/list]";
	
	
	
	regelf.getContentPane().add(new Regelfenster(text), BorderLayout.CENTER);
	
	regelf.setBounds(10,10,225,225);
	
	regelf.setVisible(true);
	
	regelf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	
	}
	
	
	
	// Hier wird einer JEditorPane der Mime-Type und der Text
	
	// zugewiesen und diese dann in eine JScrollPane gepackt
	
	Regelfenster(String text)  throws Exception 
	{

		
		setLayout(new BorderLayout());
		
		
		
		JEditorPane pane = new JEditorPane();
		
		pane.setContentType("text/html");
		
		pane.setText(text);
		
		pane.setEditable(false);
		
		
		
		JScrollPane scrollPane = new JScrollPane(pane);
		
		add(scrollPane, BorderLayout.CENTER);
		
		}

	
	}
```


----------



## SlaterB (16. Aug 2007)

was ist denn jetzt die Frage dabei?
ob der Code ausgeführt wird? dazu kennst du doch das Spiel:

System.out.println("Kommando ist: "+kommando");
if(kommando.equals("Regeln"))
       {
System.out.println("new Regelfenster(); kommt gleich");
          new Regelfenster();
       } 

---------

allerdings scheint dein Regelfenster nur ein einfaches JPanel zu sein,
das wird nicht selbständig auf der GUI angezeigt oder was immer du dir vorstellst,

füge JPanels in JFrames ein, öffne neue JFrames oder auch JDialogs,
das sind aber sehr langwiedrige Themen, ich zumindest werde die hier nicht im Detail erklären,
sowas steht in Lehrbüchern/ Tutorial
( und ist bei deinem Wissenstand idealerweise für die nächsten Monate noch nicht das Thema  )

edit:
in der main(String args[]) sind ja die fehlenden JFrame-Anteile,
die main wird aber nicht automatisch aufgerufen, die musst du schon selber aufrufen, 

da das aber komisch aussieht, verlagere dessen Logik lieber in eine Operation zeigeRegelfensterAn() oder so,
diese Operation kannst du dann sauber aufrufen, und die main ruft auch nur diese Operation auf, falls überhaupt benötigt


----------



## Gast (17. Aug 2007)

Hmm irgendwie klappt das alles nicht wie ich will. Kennst du ne Alternative? Das Regelfenster soll einfach nur einen Text über mehrere Zeilen enthalten... Das krieg ich mit meinem Wissensstand nicht hin.


----------



## SlaterB (17. Aug 2007)

http://www.galileocomputing.de/openbook/javainsel6/javainsel_14_020.htm

14.20.3 Standarddialoge mit JOptionPane


----------



## Anninha (22. Aug 2007)

super jetzt klappt mit den imageicons alles. ich hab auch im regelfenster ein image-icon, auf dem die regeln stehen. 
eine neue frage: wie kann ich dafür sorgen, dass für einen bruchteil einer sekunde in jedem feld der angelickten spalte kurz der entsprechende "spielstein" erscheint? es soll aussehen, als falle der spielstein von oben nach unten in das unterste feld der spalte. ich habe es folgendermaßen versucht, was aber nicht lappt. irgenwo muss man wohl eine seundeneingabe machen oder so?

public void setze(int c, int d, int spieler) // Methode zum Setzen der Steine bzw. der jew. Spieler
			{
				if (spieler==1) // falls spieler 1 dran ist,
				{
					spielfeld[d][c].setzeSpieler(spieler); // setze Spieler 1????

					spielfeld[1][c].setBackground(Color.RED);
					spielfeld[1][c].setBackground(Color.WHITE);

					spielfeld[d][c].setzeStein(true);      // und setze einen Stein
					spielfeld[d][c].setBackground(Color.RED);  // der Farbe rot
				}
				if (spieler==2) // dasselbe mit Spieler 2 und Farbe gelb
				{
					spielfeld[d][c].setzeSpieler(spieler);	
					spielfeld[d][c].setzeStein(true);
					spielfeld[d][c].setBackground(Color.YELLOW);
				}

			}


----------



## SlaterB (22. Aug 2007)

> ich habe es folgendermaßen versucht, was aber nicht lappt.

wo genau soll es da denn passieren,
ich sehe z.B. keine Schleife
'zeige Feld 1 rot an'
'zeige Feld 2 rot an'
'zeige Feld 3 rot an'
usw.

wenn dir dazu gar nix einfällt werde ich persönlich zumindest es nicht für dich programmieren 
jedem das Programm, was er/ sie beherrscht

Grundideen: eine Operation wie setzeFeld(x,y,color), hast du ja schon + repaint()
+ Thread.sleep()
+ ein Schleife 
+ überhaupt ein Thread, weil normalerweise die GUI gar nichts macht, bis ein Button komplett abgearbeitet ist

bevor du das in dein riesiges Programm irgendwo einbaust
und 5 Baustellen gleichzeitig aufmachst,
teste solche neuen Sachen lieber in einem separaten neuen klitzekleinen Programm,
ein fast leeres Fenster, ein Test-Button und 4 Felder deren Hintergrundfarbe gesetzt wird, 
kein ganzes Spielfeld, keine mehreren Spieler usw.

spezielle Tutorials oder ähnliches kann ich nicht nennen, außer die Standardlehrbücher, in denen es sicherlich passende Kapitel gibt,
wenn es nicht voran geht und hier keiner antwortet vielleicht ein neues Topic aufmachen


----------



## Neolity (6. Sep 2007)

Ich bin folgendermaßen vorgegangen:

- Zunächst eine Version, die nicht spielbar war und nur in der Konsole lief:
      - Array, dass Werte von 0 (ungesetzt), 1 (rot), 2 (blau) aufnehmen konnte
      - Methode, die zufällig das Array mit 1 oder 2 besetzt
      - Gewinn Methode, die prüfen kann, ob ein Spieler gewonnen hat
      - Das ganze mal zusammengesetzt (Array mit zufälligen Werten besetzten, Gewinn prüfen)
- Danach die Grafik geschrieben (Buttons, Spielbrettdarstellung etc.) und das erstmal ausgetestet
- Zuletzt beides zusammengesetzt


----------

