Irgendwie verstehe ich immer noch nicht, was bei mir nicht klappt.
Meine Arbeit besteht darin alle Lösungen für das N Damenrpblem auf einem n*x Schachbrett zu berechnen und die Ergebnisse grafisch darzustellen (nicht wirklich heftig, aber wir hatten nie Programmieren in der Schule, schon gar nicht Java).
Es lief alles wunderbar, ich habe den Algorithmus als kleine Herausforderung rekursiv programmiert. Um dir mein Problem zu zeigen habe ich eine primitive Swing Oberfläche erstellt mit nur wenigen Komponenten und das ganze Programm so weit abgespeckt wie nur möglich.
Das Problem ist jetzt nur, dass wenn das repaint gemacht wird, falsche Zahlen im Array f sind. So wie ich das sehe läuft die ganze for-Schleife durch, und erst dann kommt das repaint ==> falsche Werte im Array.
Das merkwürdige ist:
Beim Methodenaufruf ausgabe() werden alle Lösungen richtig ausgegeben. Bei repaint() nicht mehr.
Hier ist mal der gesamte Code:
Die Klasse, die von JFrame abgeleitet wird:
[Java]
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class AlgoGrafisch2 extends JFrame implements ActionListener {
Container c;
Schachbrett sb;
JPanel optionen;
JButton start;
AlgoGrafisch2(){
c = getContentPane();
optionen = new JPanel();
sb = new Schachbrett();
start = new JButton("Start");
start.addActionListener(this);
optionen.add(start);
c.add(optionen, BorderLayout.NORTH);
c.add(sb, BorderLayout.CENTER);
}
@Override
public void actionPerformed(ActionEvent arg0) {
sb.berechnePosition(0);
}
public static void main(String[] args) {
AlgoGrafisch2 window = new AlgoGrafisch2();
window.setTitle("Algo grafisch Test");
window.setSize(800, 500);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
[/Java]
Die Klasse Schachbrett, die von JPanel abgeleitet ist:
[Java]
import java.awt.*;
import javax.swing.*;
public class Schachbrett extends JPanel {
int n = 13;
final int DAMEN = n; //Anzahl Damen auf dem Feld
int solutions = 0;
int[] f = new int[DAMEN];
boolean positionenBerechnet = false;
public void paintComponent(Graphics g){
super.paintComponent(g);
g.translate(50,20);
//Zeichnet das Schachbrett
//Länge des Schachbretts: 400
//Feldbreite des Schachbretts: 50
drawChessBoard(g);
//Zeichnet die Damen
//Erst wenn die positionenBerechnet true ist sollen die Damen gezeichnet werden
System.out.println(positionenBerechnet);
if(positionenBerechnet){
drawQueens(g);
}
}
//Das Schachbrett wird gezeichnet
public void drawChessBoard(Graphics g){
int x = 0;
int y = 0;
//Zeichnet die horizontalen Linen im Schachbrett
for (int i=0; i <= n; i++) {
g.drawLine(0, y, 400, y);
y+=50;
}
y = 0;
x = 0;
//Zeichnet die vertikalen Linien im Schachbrett
for (int i=0; i <= n; i++) {
g.drawLine(x, y, x, 400);
x += 50;
}
}
//Die Damen werden gezeichnet
public void drawQueens(Graphics g){
int x = 0;
int y;
g.setColor(Color.red);
for(int i = 0 ; i < f.length ; i++){
y = ( f+1 ) * 50;
g.fillOval(x, y, 20, 20);
x += 50;
System.out.println("f["+(i+1)+"] = "+(f+1));
}
}
//Die möglichen Positionen werden rekursiv aufgelistet.
//Dazu wird für jede Spale die for-Schleife durchlaufen. Ist die Dame oben am Rand
//angekommen ist die for-Schleife zu Ende und k wird automatisch zu k-1.
//Die Schleife ist dann fertig, wenn f[0] == DAMEN - 1 und die for-Schleife für alle
//folgenden Spalten durchlaufen ist.
/*
* @param
* int k steht für die Spaltenzahl auf dem Schachbrett (0 <= k < DAMEN)
*/
public void berechnePosition(int k) {
for(int s = 0; s < DAMEN; s++) {
//Dem arry f[k] wird bei jedem Durchlauf der entsprechende Wert vertikale
//Werte übergeben, damit dieser in der positionFree()-Methode verglichen
//werden kann.
f[k] = s;
//Wenn die Position frei ist
//positionFree() überprüft, ob die Position der Dame frei ist
//Wenn die Position frei ist ist der Rückgabewert true, wenn nicht false
if(positionFree(k)) {
//Wenn die letzte Spalte erreicht ist, ist eine neue Lösung bekannt
if(k == DAMEN - 1){
solutions++; //Die Anzahl Lösungen wird um 1 erhöht
positionenBerechnet = true; //positionenBerechnet wird auf true gesetzt, damit die Damen aktualisiert werden.
ausgabe(); //Gibt die Positionen in der Konsole aus
repaint(); //Ruft paintComponent() auf, damit alles notwendige neu gezeichnet wird
}
//Wenn noch nicht die letzte Spalte erreicht ist
else {
berechnePosition(k+1); //rekursiver Aufruf
}
}
}
}
/*
* Überprüft, bo die aktuelle Position der Dame nicht bedroht ist.
*
* @param
* int k, um anzugeben, an welcher horizontalen Stelle man sich gerade
* befindet ==> f[k]
*/
public boolean positionFree(int k) {
boolean posFrei = true;
//Wenn die Position bereits belegt ist, wird die boolean Variable posFree, die
//anfänglich immer true ist, auf false gesetzt und zurückgegeben
for(int i = 0; i < k; i++){
if(Math.abs( f- f[k] ) == k - i | f == f[k]) {
posFrei = false;
break;
}
}
return posFrei;
}
//Gibt alle Wörter und die Anzahl Lösungen über die Konsole aus
public void ausgabe(){
String ausgabe = "";
for(int i=0; i< f.length; i++){
ausgabe += (" "+(f+1));
}
System.out.println("Ausgbae1: "+ausgabe);
System.out.println("Anzahl Lösungen: "+ solutions);
}
}
[/Java]
Zum Code:
Die Ausschlaggebenden Methoden sind paintComponent, berechnePosition, ausgabe. Den Rest hab ich einfach mal mitgepostet, damit ihr den Code mal ausprobieren könnt, falls das nötig ist.
Ich habe2 Ideen:
1.
Ich muss die for-Schleife so lange warten lassen, bis das repaint() beendet ist. Also diese Schleife irgendwie blockieren können. Aber wie weiss ich nicht.
2.
Ich rechne zuerst alles aus, speichere das in einem weiteren 2D-Array und erst dann kommt das repaint für alle Positionen.
Gibt es Ideen oder Vorschläge wie das zu lösen wäre? Ich bin schon sehr lange vorm Rechner und hab keine gute Lösung hingebracht.