Warum terminiert mein Programm nicht!?

oberbimbo

Mitglied
Hallo liebe Community. Bin neu hier, also erstmal Gruß an alle🙂

Ich habe folgendes Problem:

Zum Damen-Problem muss ich eine Klasse schreiben und dazu eine statische Methode angeben, die die Anzahl der möglichen Lösungen mit Hilfe von Backtracking ermittelt und ausgibt.
Ich habe das wie folgt gelöst🙁Quelltext siehe unten)

Problem1: Ich weiss, dass der Algorithmus doppelte Einträge nicht herausfiltert, denke aber das ich das noch hinbekommen werde.

Problem2 ist viel wichtiger: Mein Programm terminiert nicht! Ich habe mir meinen Quelltext schon 20 Mal durchgesehen, etliche Fehler behoben und nun stehe ich auf dem Schlauch???:L;(

Ich sitze seit geschlagenen 8 std dran. Bitte seid so nett und helft mir! Danke
Wenn ich etwas schlecht kommentiert haben sollte tut mir das Leid. Bin noch ein Anfänger.

Java:
import java.awt.Point;
import java.util.ArrayList;

public class checkers {
	
	public boolean[][] brett;
	
	
	//Konstruktor
	public checkers (int anz)
	{
		brett = new boolean[anz][anz];
	}
	
	//markiert die Stellen auf dem Brett mit true, wo andere durch die Dame im übergebenen Punkt Damen gefährdet sind
	public void besetze(Point D)
	{
		//besetzt die Zeilen des Schachbretts
		for (int i = 0; i < this.brett.length; i++) 
		{
			this.brett[i][D.x]=true;
		}
		
		//besetzt die Spalten des Schachbretts
		for (int i = 0; i < this.brett.length; i++) 
		{
			this.brett[D.y][i] = true;
		}
		
		//besetzt die 1. Diagonale des Schachbretts
		Point X = new Point();
		X.x = D.x;
		X.y = D.y;
		
			//geht die Diagonale "zurück" bis zur 0. Spalte oder 0. Zeile
		while (X.x>0 && X.y>0)
		{
			X.x -= 1;
			X.y -= 1;
		}
		
			//besetzt die Diagonale
		while (X.x < this.brett.length - 1 && X.y < this.brett.length - 1)
		{
			this.brett[X.x][X.y]=true;
			X.x += 1;
			X.y += 1;
			this.brett[X.x][X.y]=true;
		}		
		
		//besetzt die 2. Diagonale des Schachbretts
			//geht die Diagonale "zurück" bis zur 0. Spalte oder 8. Zeile
		Point Y = new Point();
		Y.x = D.x;
		Y.y = D.y;
		
		while (Y.x > 0 && Y.y < this.brett.length - 1)
		{
			Y.x -= 1;
			Y.y += 1;
		}
		
			//besetzt die Diagonale
		while (Y.x < this.brett.length - 1 && Y.y > 0)
		{
			this.brett[Y.x][Y.y] = true;
			Y.x += 1;
			Y.y -= 1;
			this.brett[Y.x][Y.y] = true;
		}		
	}
	
	
	//Methode, die die Position des nächsten Kästchens des übergebenen Punktes bestimmt
	public Point moveNext(Point p)
	{	
		if(p.x < this.brett.length - 1 && p.y <= this.brett.length - 1)
		{
			p.x = p.x + 1;
		}
		
		if(p.x == this.brett.length - 1 && p.y < this.brett.length - 1)
		{
			p.x = 0;
			p.y = p.y + 1;
		}
		
		return p;
	}
	
	
	public ArrayList<ArrayList<Point>> loese()
	{
		ArrayList<ArrayList<Point>> lmenge = new ArrayList<ArrayList<Point>>();
		ArrayList<Point> l = new ArrayList<Point>();	
		Point Null = new Point(0,0);
		Point Punkt = new Point(0,0);
		Point Start = new Point(0,0);
		Point Nullpunkt = new Point(0,0);
		
		for (int i = 1; i <= this.brett.length * this.brett.length; i++) 
		{
			//Methode zur Ermittlung einer Lösung
			//führt die Schleife für n Damen durch
			for (int iy = 0; i < this.brett.length; iy++) 
			{   
				//Wenn die Stelle noch frei, besetze sie und schreibe die Koordinaten in eine Liste
				if (this.brett[Start.x][Start.y]==false)
				{
					besetze(Start);
					l.add(Start);
				}
				
				//gehe bis zur nächsten freien Stelle
				for (int j = 1; j < this.brett.length * this.brett.length; j++) 
				{
					if(this.brett[Null.x][Null.y] == true) 
					{
						moveNext(Null);
					}
				}
				
				Start.x = Null.x;
				Start.y = Null.y;
				Null.x = 0;
				Null.y = 0;
				
			}
			
			if(l.size() == this.brett.length)lmenge.add(l);
			l.clear();
			
			//setzt das komplette Schachbrett zurück auf leer (unbesetzt)
			for (int j = 1; j < (this.brett.length) * (this.brett.length); j++) 
			{
				this.brett[Nullpunkt.x][Nullpunkt.y] = false;
				moveNext(Nullpunkt);
			}
			Nullpunkt.x = 0;
			Nullpunkt.y = 0;
			moveNext(Punkt).x = Start.x;
			moveNext(Punkt).y = Start.y;
		}
		return lmenge;
	}
	
	
	public static int numberSolutions(int n)
	{
		checkers test = new checkers(n);
		return test.loese().size();
	}
	
	
	public static void main(String[] args) 
	{
		System.out.println(numberSolutions(3));
	}
}
 
yay supi! Danke jketzt terminiert er! War echt zu blind für diesen kleinen Fehler.

Aber da kommt immer 0 raus... hm komisch. muss es mir noch genauer ansehen. Wenn es jemand zuerst sieht, sagt es mir bitte.

Danke
 
Bei solchen Programmen frag ich mich fast immer das Gleiche. "Wo ist denn da die Ausgabe, mit der Du Dir die ganzen Zwischenschritte angesehen hast?".
Du sagst selbst, dass Du Anfänger bist, also mach das nicht im Kopf, sondern schau es Dir WIRKLICH an.
Und wenn Du einen Ablauf hast, aus dem Du nicht schlau wirst, dann darfst Du den auch gerne hier zeigen und uns das Rätselraten etwas leichter machen. 😉

Dann ist das Dameproblem mit Backtracking ein klassischer Fall für eine Rekursion. Kann es sein, dass ihr sowas dabei lernen sollt?

Und dann mach Dir mal Gedanken, was Dein Programm wirklich tut. Geh es Schritt für Schritt durch und dann wirst Du auch rausfinden, was es nicht tut. (bzw. warum nicht)
Wenn Du selbst entwickelst, sollte die zu bearbeitende Frage sein "Welches Programm tut, was ich will?" und nicht "Was tut dieses Programm hier?". Letzteres fragt man sich bei fremdem Code, aber wenn man gerade selbst daran arbeitet, sollte zumindest DAS klar sein. Du wirst in Deinem Programm nämlich niemals einen "Fehler" finden, wenn es nicht wenigstens sehr dicht an einem richtigen Lösungsprogramm dran ist. Dein Programm hat vielleicht keinen "Fehler", sondern macht nur was ganz anderes. So anders, dass es vielleicht nicht durch einen falschen Indexoperator etc. korrigiert werden kann.

Überleg Dir mal im Kopf und auf Papier ein Verfahren, von dem Du zumindest theoretisch 😉 überzeugt bist, dass es funktioniert. Dei Grundlagen mit der Markierung der Felder und dem nächsten Versuch sind ja soweit ganz richtig. Aber schau Dir das mal noch konkreter an.

Und warum machst Du es Dir so schwer, mit der Punktliste? Kannst Du nicht alles auf dem Brett speichern? Aus den Booleans könntest Du doch eine andere Variable machen, in der Du noch mehr unterschiedliche Werte speichern kannst. Da wäre dann doch Platz für 0 = unbesetzt, 1 = Dame und -1 = blockiert, oder etwas ähnliches.
Das würde auch prima zu der überfälligen Ausgabefunktion passen. *mitdemzaunpfahlwink*
 
Zuletzt bearbeitet:
Yay, da freuen die sich. ^^

oberbimbo, Du kannst Dir als "Fingerübung" mal überlegen, was
Java:
moveNext(Punkt).x = Start.x;
moveNext(Punkt).y = Start.y;
so alles bewirkt. Und schau auch in die moveNext() nochmal rein. Vielleicht findest dabei schon Überraschungen.
Lass Dir das Brett regelmäßig ausgeben und versuch Dir zu erklären, was da abgeht.
 
Danke für die Tips.

Ich habe mir l ausgeben lassen (vor deinem Tip schon 🙂 ). da steht nur Müll drin. Werd mir den anderen Müll auch ausgeben lassen ...

zum Anderen hab ich
Java:
moveNext(Punkt).x = Start.x;
moveNext(Punkt).y = Start.y;
in
Java:
Start.x = moveNext(Punkt).x;
Start.y = moveNext(Punkt).y;

ist ja logisch.

Rekursion sollten wir nicht unbedingt anwenden (Was das ist ist mir bewusst)
die moveNext() scheint auf den ersten Blick in Ordnung zu sein

werde morgen weiter schauen. Bin jetzt vollkommen betriebsblind... sitze an dieser Aufgabe seit gestern 14:00😱;🙂autsch: (mit Essenspausen natürlich 😀)

Ach und mit Papier und Stift ist ja auch klar. kannst die gar nicht vorstellen, wie viel ich gemalt und geschrieben hab ...

so gehe jetz schlecht gelaunt und deprimiert ins Bette und wünsche euch ne gute Nacht ;(
 
Zuletzt bearbeitet:
Bist Du mit der moveNext() sicher? Was passiert denn, wenn Du z.B. bei einem 4x4 Brett auf dem dritten Feld in der ersten Zeile stehst? Wo stehst Du nach moveNext()?

Und was passiert, wenn Du moveNext() zweimal nacheinander aufrufst und beim ersten mal den x-Wert und beim zweiten mal den y-Wert kopierst?

Lass doch mal die weitere Lösung weg und prüfe erstmal, ob Du mit einer Schleife, die nur moveNext() ausführt, sauber über das Feld laufen kannst.
 
ja moin noch mal und danke
Hab mein moveNext wie folgt geändert
Java:
//Methode, die die Position des nächsten Kästchens des übergebenen Punktes bestimmt
	public static Point moveNext(boolean[][] c, Point p)
	{	
		if(p.x < c.length - 1 && p.y <= c.length - 1)
		{
			p.x = p.x + 1;
		}
		else
		if(p.x == c.length - 1 && p.y < c.length - 1)
		{
			p.x = 0;
			p.y = p.y + 1;
		}
		
		
		return p;
	}

Diese Methode funzt jetzt, den Rest habe ich dem entsprechend angepasst.
Das Programm macht aber immer noch nicht das, was ich will. werde mal weiter suchen ...
 
Wie gesagt, vielleicht kann es auch gar nicht machen, was Du willst.
Hast Du vielleicht einen Ablauf mit den Ausgaben vom Brett und der Punktliste? Dann können wir hier ja auch mal draufschauen.
 
Moin nochmal.
Hab jetz mein programm modifiziert und herausgefunden, dass meine besetze-Methode nicht so funzt wie ich es will.
Wenn ich ein checkers in einem Punkt besetze, wird das ganze Feld besetzt. Komm mal wieder nicht weiter ... help pls *cry

Hier der Code samt Testroutine:
Java:
import java.awt.Point;
import java.util.ArrayList;

public class checkers 
{
	
	public boolean[][] brett;
	
//__________________________________________________________________	
	//Konstruktor
	public checkers (int anz)
	{
		brett = new boolean[anz][anz];
	}
//__________________________________________________________________
	//markiert die Stellen auf dem Brett mit true, wo andere Damen durch die Dame 
	//im übergebenen Punkt gefährdet sind
	public void besetze(Point D)
	{
		//besetzt die Zeilen des Schachbretts
		for (int i = 0; i < this.brett.length; i++) 
		{
			this.brett[i][D.y] = true;
		}
		
		//besetzt die Spalten des Schachbretts
		for (int i = 0; i < this.brett.length; i++) 
		{
			this.brett[D.x][i] = true;
		}
		
	//besetzt die 1. Diagonale des Schachbretts
		Point X = new Point();
		X.x = D.x;
		X.y = D.y;
		
			//geht die Diagonale "zurück" bis zur 0. Spalte oder 0. Zeile
		while (X.x>0 && X.y>0)
		{
			X.x -= 1;
			X.y -= 1;
		}
		
			//besetzt die Diagonale
		while (X.x < this.brett.length - 1 && X.y < this.brett.length - 1)
		{
			this.brett[X.x][X.y]=true;
			X.x += 1;
			X.y += 1;
			this.brett[X.x][X.y]=true;
		}		
		
	//besetzt die 2. Diagonale des Schachbretts
			
		Point Y = new Point();
		Y.x = D.x;
		Y.y = D.y;
		
		//geht die Diagonale "zurück" bis zur 0. Spalte oder 8. Zeile
		while (Y.x > 0 && Y.y < this.brett.length - 1)
		{
			Y.x -= 1;
			Y.y += 1;
		}
		
			//besetzt die Diagonale
		while (Y.x < this.brett.length - 1 && Y.y > 0)
		{
			this.brett[Y.x][Y.y] = true; 
			Y.x += 1;
			Y.y -= 1;
		    this.brett[Y.x][Y.y] = true;
		}		
	}
//______________________________________________________________
	
	//Methode, die die Position des nächsten Kästchens des übergebenen Punktes bestimmt
	public static Point moveNext(boolean[][] c, Point p)
	{	
		if(p.x < c.length - 1 && p.y <= c.length - 1)
		{
			p.x = p.x + 1;
		}
		else
		if(p.x == c.length - 1 && p.y < c.length - 1)
		{
			p.x = 0;
			p.y = p.y + 1;
		}
		
		
		return p;
	}
//_________________________________________________________________________	
	
	public ArrayList<ArrayList<Point>> loese()
	{
		ArrayList<ArrayList<Point>> lmenge = new ArrayList<ArrayList<Point>>();
		ArrayList<Point> l = new ArrayList<Point>();	
		Point Null = new Point(0,0);
		Point Punkt = new Point(0,0);
		Point Start = new Point(0,0);
		Point Nullpunkt = new Point(0,0);
		
		for (int i = 1; i <= this.brett.length * this.brett.length; i++) 
		{
			//Methode zur Ermittlung einer Lösung
			//führt die Schleife für n Damen durch
			for (int iy = 0; iy < this.brett.length; iy++) 
			{   
				
				//System.out.println(l);
				/*for (int j = 0; j < this.brett.length; j++) {
					int q = 0;
					
					for (int h = 0; h < this.brett.length; h++) 
					{
						System.out.print(this.brett[q][h]);
						System.out.print(" ");
					}
					System.out.println();
					q++;
					}
				System.out.println();*/
				
			   
			    
				//gehe bis zur nächsten freien Stelle
				while(this.brett[Null.x][Null.y] == true)	
					{
						moveNext(this.brett,Null);
						if(Null.x==this.brett.length-1 && 
						   Null.y==this.brett.length-1)
						{
							break;
						}
					}
				
						//besetze freie Stelle
				        Start.x = Null.x;
				        Start.y = Null.y;
				        if (this.brett[Start.x][Start.y] == false) l.add(Start);
						besetze(Start);
						
						
						Null.x = 0;
						Null.y = 0;	
			}
     	}
		Nullpunkt.x = 0;
		Nullpunkt.y = 0;
		if (l.size()==this.brett.length)lmenge.add(l);

			
			//setzt das komplette Schachbrett zurück auf leer (unbesetzt)
			for (int j = 1; j < (this.brett.length) * (this.brett.length); j++) 
			{
				this.brett[Nullpunkt.x][Nullpunkt.y] = false;
				moveNext(this.brett,Nullpunkt);
			}
			Null.x = moveNext(this.brett,Punkt).x;
			Null.y = moveNext(this.brett,Punkt).y;
			System.out.println(l);
			l.clear();
		
		return lmenge;
     }
//______________________________________________________________________
	
	public static int numberSolutions(int n)
	{
		checkers test = new checkers(n);
		return test.loese().size();
	}
	
	
	public static void main(String[] args) 
	{
		checkers test1 = new checkers(4);
		Point p = new Point(0,3);
		test1.besetze(p);
		for (int j = 0; j < test1.brett.length; j++) {
			int q = 0;
			
			for (int h = 0; h < test1.brett.length; h++) 
			{
				System.out.print(test1.brett[q][h]);
				System.out.print(" ");
			}
			System.out.println();
			q++;
			}
		System.out.println();
		
		
		//System.out.println(numberSolutions(4));
/*		for (int j = 0; j < test1.brett.length; j++) {
			int q = 0;
			
		for (int i = 0; i < test1.brett.length; i++) 
		{
			System.out.print(test1.brett[q][i]);
			System.out.print(" ");
		}
		System.out.println();
		q++;
		
		}*/
		//System.out.println(test1.loese());
		//System.out.println(moveNext(test1.brett,moveNext(test1.brett,p)));
	}
}
 
Moin sorry für Doppelpost aber ich muss wohl präzisieren.
Java:
 //besetzt die Zeilen des Schachbretts
        for (int i = 0; i < this.brett.length; i++) 
        {
            this.brett[i][D.y] = true;
        }
        
        //besetzt die Spalten des Schachbretts
        for (int i = 0; i < this.brett.length; i++) 
        {
            this.brett[D.x][i] = true;
        }
habe ich ersetzt durch das äquivalente

Java:
{
		//besetzt die Zeilen und Spalten des Schachbretts
		for (int i = 0; i < this.brett.length; i++) 
		{
		     this.brett[i][D.x] = true; //Zeilen
	             this.brett[D.y][i] = true; //Spalten
		}
und die komplette Diagonalenbesetzung auskommentiert.

für
Java:
               checkers test1 = new checkers(4);
		Point p = new Point(1,2);
		test1.besetze(p);
ergibt es bei auskommetierter //Zeilen Zeile
Java:
false false false false 
false false false false 
false false false false 
false false false false
und bei auskommentierter //Spalten Zeile
Java:
false true false false 
false true false false 
false true false false 
false true false false
also die Spalte besetzt er schon richtig, aber komischerweise mit der Schleife, die die Zeilen besetzen sollte.

für den Punkt (0,0) wird die Spalte ebenfalls belegt(mit der Zeilenschleife).
Die Splatenschleife setzt das komplette array auf true. HÄÄÄÄÄÄÄ????

warum bloss? warum bin ich zu dumm für den Scheiß?
Ich lass aber nicht locker!!
 
Moin,

Dein Programm arbeitet halt so wie Du es programmiert hast. Zwei Tipps:
Du hast die Felder bisher wie folgt besetzt:
Java:
this.brett[i][D.y] = true; //Zeilen
this.brett[D.x][i] = true; //Spalten
und der modifizierte Code danach ist halt nicht äquvalent:
Java:
this.brett[i][D.x] = true; //Zeilen
this.brett[D.y][i] = true; //Spalten

Was Die Ausgabe des Brettes angeht:
Du hast zwei Schleifen mit den Variablen j und h und nutzt für die Ausgabe stattdessen aber q, welches Du IN der Schleife immer wieder auf 0 setzt. Dein Programm kommt nie über die erste Zeile hinaus. Schmeiss q weg und nutze einfach j!

Grüße
 
*puh
Danke! Jetzt belegt er schon mal die Zeilen und Spalten korrekt.

Nun hab ich ein Problem mit den Diagonalen: wenn x und y meines Punktes gleich sind, belegt er die richtig. Wenn sie verschieden sind, belegt er nur eine Diagonale

Woran liegt das denn jetzt? ???:L

Bin ich vieleicht abgenervt von dem Zeug. Das könnt ihr euch gar nicht vorstellen.

Ohne eure Hilfe bin ich verloren ;( ...
 

Zurück
Oben