Seite 1 von 2 12 Letzte »
Ergebnis 1 bis 20 von 38

Java - Grafik

  1. #1 Zitieren
    Sergej Petrow
    Gast
    Ich habe mal ein Beispiel von hier genommen:
    http://www.willemer.de/informatik/java/grafik.htm
    Code:
    import javax.swing.*;
    import java.awt.*;
    
    public class MyGraphics extends JFrame {
    
      public static void main(String[] args) {
        MyGraphics fenster = new MyGraphics();
      }
    
      public MyGraphics() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setTitle("Zeichnen mit Java");
            setSize(400, 300);
            setVisible(true);
      }
    
      @Override public void paint(Graphics g) { // @Override ermöglicht dem Compiler die Kontrolle
        Insets insets = getInsets();
        int originX = insets.left;
        int originY = insets.top;
        int breite   = getSize().width  - insets.left - insets.right;
        int hoehe   = getSize().height - insets.top  - insets.bottom;
        g.setColor(Color.yellow);
        g.clearRect(originX, originY, breite-1, hoehe-1);
        g.fillOval(originX, originY, breite-1, hoehe-1);
        g.setColor(Color.black);
        String meldung  = "" + breite + " x " + hoehe + " Pixel";
        g.drawString(meldung, breite/2, hoehe/2);
      }
    }
    Hier kann man ja sehen, wie man Grafik in einem Java-Programm einbauen kann. Es funktioniert mit der Methode paint(Graphics g), die quasi selbstständig aufgerufen wird.

    Das funktioniert auch so weit so gut.

    Jetzt kommt das große Aber. Ich möchte gerne noch andere Parameter übergeben.

    Etwa in der Form:

    Code:
        public void paint(Graphics2D g2d, int x, int y, short inhalt)
        {
            
        	Graphics2D g=(Graphics2D) g2d;
        	super.paint(g2d);
        	
        	if(inhalt==1)
        	{
                g.setColor(Color.GREEN); 
        		g.fillOval(x*100, y*100, 50, 50);
        	}
        	else if (inhalt==0)
        	{
                g.setColor(Color.BLACK); 
        		g.drawOval(x*100, y*100, 50, 50);
        	}
        	   		
        }
    Nur passiert hier gar nichts. Ich habe es auch schon mit einem Construktor versucht. Nur kann ich dann Graphics2D g nicht initialisieren, etwa in der Form Graphics2D g = new Graphics2D();
    Das funktioniert leider nicht.

    Wie kann ich die Methode paint dazu bringen, dass ich Variablen übergeben kann?

  2. #2 Zitieren
    Knight Commander Avatar von Kellendil
    Registriert seit
    Jul 2009
    Beiträge
    2.093
    Du kannst paint gar nicht aufrufen (weil paint von einem seperaten Render-Thread aufgerufen wird, der quasi unsichtbar fürs rendern zuständig ist), deshalb macht es auch nicht Sinn eine weitere paint-Methode mit Argumenten zu erstellen.

    Du kannst paint zwar manuell triggern (mit this.repaint), damit sagts du aber auch nur dem Render-Thread, dass er painten soll, und kannst wieder keine Argumente übergeben.

    Selbst wenn du Argumente übergeben könntest: Da du nie weißt, wann und wie oft der Render-Thread tatsächlich die paint-Methode aufruft, wäre das unmöglich, sie immer zum richtigen Zeitpunkt an den Render-Thread zu übergeben (bzw. nur mit extremem Aufwand). Sie viel zum WARUM es nicht geht.

    Wie du das Problem löst: Klassenvariablen (bzw. state im allgemeinen). Die kannst du in der paint Methode abrufen. Dann kann es dir auch egal sein, wie oft/wann die paint methode aufgerufen wird, solange deine Klassenvariablen gültige Werte besitzen.
    Kellendil ist offline

  3. #3 Zitieren
    Sergej Petrow
    Gast
    Ok, das hilft mir weiter. Wollte eigentlich ohne Klassenvariablen arbeiten. Aber wenn das nicht geht, mache ich es halt so. Danke für die Erklärung. So wird einiges deutlicher.

  4. #4 Zitieren
    Sergej Petrow
    Gast
    Also direkt so hat es nicht geklappt, weil man nicht wirklich steuern kann, wann paint ausgeführt wird. Selbst mit repaint() geht das nicht.
    Gibt da zwar noch einen anderen Weg, wenn man das buffered. Aber das war mir hierfür zu aufwendig.

    Was aber ging, ich habe einfach die Methode paint quasi als meine main benutzt. Alles, was berechnet werden musste, habe ich statt in der Main in die paint gepackt und dann lief das.

    hier das ganze Programm:
    (Das Programm berechnet eine Lösung für das Spiel Solitär. Ich fand es einfacher, ein Programm zu schreiben, als das Spiel selbst zu lösen. Der Code für die Berechnung hat mich eine halbe Stunde gekostet. Für die grafische Ausgabe aber habe ich fast zwei Tage gebraucht.)

    Code:
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    
    import javax.swing.JFrame;
    
    public class Solit extends JFrame
    {
    
    	static short [][][] loesung= new short[32][7][7];
    	static boolean zeichnen=true;
    	
    	public Solit() 
    	{
    	super(); 
            setDefaultCloseOperation(EXIT_ON_CLOSE);       
    	}
    	
    	
    	public void paint(Graphics gs) 
    	{ 
    		
    		Graphics2D g=(Graphics2D)gs;
    		
    		short [][] A = new short [7][7];
    		A[0][0]=9; A[1][0]=9; A[2][0]=1; A[3][0]=1; A[4][0]=1; A[5][0]=9; A[6][0]=9;
    		A[0][1]=9; A[1][1]=9; A[2][1]=1; A[3][1]=1; A[4][1]=1; A[5][1]=9; A[6][1]=9; 
    		A[0][2]=1; A[1][2]=1; A[2][2]=1; A[3][2]=1; A[4][2]=1; A[5][2]=1; A[6][2]=1;
    		A[0][3]=1; A[1][3]=1; A[2][3]=1; A[3][3]=0; A[4][3]=1; A[5][3]=1; A[6][3]=1;
    		A[0][4]=1; A[1][4]=1; A[2][4]=1; A[3][4]=1; A[4][4]=1; A[5][4]=1; A[6][4]=1;
    		A[0][5]=9; A[1][5]=9; A[2][5]=1; A[3][5]=1; A[4][5]=1; A[5][5]=9; A[6][5]=9;
    		A[0][6]=9; A[1][6]=9; A[2][6]=1; A[3][6]=1; A[4][6]=1; A[5][6]=9; A[6][6]=9; 
    
    		int i,x,y;
    		short inhalt;
    		
    		for (i=0;i<32;i++)
    			{
    			for (int j=0;j<7;j++)
    				{
    				for (int k=0;k<7;k++)
    					{
    					loesung[i][j][k]=0;
    					}
    				}
    			}
    		
    	speichern(A,0);
    
    	soli(A,0);		
    
    	if (zeichnen)
    	
    	{
    	for (i=0;i<32;i++)
    		
    	{
    	for (y=0;y<7;y++)
    		{
    		for (x=0;x<7;x++)
    			{
    			inhalt=loesung[i][x][y];
    		
    			if (inhalt == 0)
    				{
    				g.setColor(Color.WHITE);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    				}
    		
    			else if(inhalt == 1)
    				{
    				g.setColor(Color.GREEN);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    
    				}
    
    			}
    		}
    	
    	try {
    		Thread.sleep(2000);
    	} catch (InterruptedException e) {
    		// TODO Auto-generated catch block
    		e.printStackTrace();
    	}
    	
    	}
    }
    	
    zeichnen=false;		
    	
    		
    				
    	 }
    
    	
    	static boolean oben(short A[][], short x, short y)
    	{
    
    	if(y>1) 
    		{
    		if(A[x][y]==1 && A[x][y-1]==1 && A[x][y-2]==0) return true;
    		}
    	return false;
    	}
    
    	static boolean unten(short A[][], short x, short y)
    	{
    
    	if(y<5) 
    		{
    		if(A[x][y]==1 && A[x][y+1]==1 && A[x][y+2]==0) return true;
    		}
    	return false;
    	}
    
    	static boolean links(short A[][], short x, short y)
    	{
    
    	if(x>1) 
    		{
    		if(A[x][y]==1 && A[x-1][y]==1 && A[x-2][y]==0) return true;
    		}
    	return false;
    	}
    
    	static boolean rechts(short A[][], short x, short y)
    	{
    
    	if(x<5)
    		{
    		if(A[x][y]==1 && A[x+1][y]==1 && A[x+2][y]==0) return true;
    		}
    	return false;
    	}
    
    	static void speichern(short A[][], int i)
    		{
    		for(int y=0;y<7;y++)
    			{
    			for(int x=0;x<7;x++)
    				{
    				loesung[i][x][y]=A[x][y];
    				}
    			}
    		}
    
    	static int  soli (short A[][], int i)
    	{
    		int ergebnis=0;
    	if (i<31) 
    		{
    		i++;
    		for (short y=0;y<7;y++)
    			{
    			for (short x=0;x<7;x++)
    				{
    				if(oben(A,x,y)) 
    					{
    					A[x][y]=0; A[x][y-1]=0; A[x][y-2]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if (ergebnis==-2)
    						{
    						A[x][y]=1; A[x][y-1]=1; A[x][y-2]=0;
    						}
    					}
    
    				if(unten(A,x,y))
    					{
    					A[x][y]=0; A[x][y+1]=0; A[x][y+2]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if(ergebnis==-2)
    						{
    						A[x][y]=1; A[x][y+1]=1; A[x][y+2]=0;
    						}
    					}
    				
    				if(links(A,x,y))
    					{
    					A[x][y]=0; A[x-1][y]=0; A[x-2][y]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if (ergebnis==-2)
    						{
    						A[x][y]=1; A[x-1][y]=1; A[x-2][y]=0;
    						}
    					}
    				
    				if(rechts(A,x,y)) 
    					{
    					A[x][y]=0; A[x+1][y]=0; A[x+2][y]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if (ergebnis==-2)
    						{
    						A[x][y]=1; A[x+1][y]=1; A[x+2][y]=0;
    						}
    					}
    				}
    			}
    		i--;
    		return -2;
    		}
    	else	
    		{
    		return -1;
    		}
    
    	}
    
    	public static void main(String[] args)
    	{
    		
    	Solit f= new Solit();	
    	f.setSize(1000, 1000);
    	f.setVisible(true);
    		
           }
    
    }
    Die Berechnung geht verdammt schnell. Hab das erst ohne Grafikausgabe gemacht, sondern lediglich auf Konsole, da hat es nur wenige Sekunden gedauert. War erstaunt, da es einfach nur jede Möglichkeit durchgeht, also die Methode Brute Force nutzt. Immerhin sind es 31 Züge, die es in die Tiefe rechnen muss.
    Geändert von Sergej Petrow (27.12.2016 um 21:19 Uhr)

  5. #5 Zitieren
    Pretty Pink Pony Princess  Avatar von Multithread
    Registriert seit
    Jun 2010
    Ort
    Crystal Empire
    Beiträge
    11.228
    Berechnungen in der Paint Methode: ganz schlecht.

    Eigentlich ist das das dümmste was man machen kann, denn die Grafische Ausgabe ist Zeitkritisch für das 'look and Feel' der Software.

    Kannst du mal deinen Versuch der Aufteilung Posten. Oder gar das ganze Packet, dann kann Ich mal schauen wie man das Aufteilen könnte. Vielleicht hast du nur einen Überlegungsfehler gemacht bei der Implementation.
    [Bild: AMD_Threadripper.png] Bei Hardware gibt es keine eigene Meinung, bei Hardware zählen nur die Fakten.


    Probleme mit der Haarpracht? Starres Haar ohne Glanz? TressFX schafft Abhilfe. Ja, TressFX verhilft auch Ihnen zu schönem und Geschmeidigen Haar.
    [Bild: i6tfHoa3ooSEraFH63.png]
    Multithread ist gerade online

  6. #6 Zitieren
    Sergej Petrow
    Gast
    Das Problem ist einfach, dass die Grafikerneuerung quasi eine Schleife durchlaufen muss.

    Code:
    if (zeichnen)
    	
    	{
    	for (i=0;i<32;i++)
    		
    	{
    	for (y=0;y<7;y++)
    		{
    		for (x=0;x<7;x++)
    			{
    			inhalt=loesung[i][x][y];
    		
    			if (inhalt == 0)
    				{
    				g.setColor(Color.WHITE);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    				}
    		
    			else if(inhalt == 1)
    				{
    				g.setColor(Color.GREEN);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    
    				}
    
    			}
    		}
    	
    	try {
    		Thread.sleep(2000);
    	} catch (InterruptedException e) {
    		// TODO Auto-generated catch block
    		e.printStackTrace();
    	}
    Das ist der Bereich, in dem gezeichnet wird. Dafür habe ich mir für meine vorherigen Versuche x,y und Inhalt als Klassenvariablen erstellt.

    Code:
    {
    			inhalt=loesung[i][x][y];
    		
    			if (inhalt == 0)
    				{
    				g.setColor(Color.WHITE);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    				}
    		
    			else if(inhalt == 1)
    				{
    				g.setColor(Color.GREEN);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    
    				}
    
    			}
    Hier hatte ich dann hinter der geschweiften Klammer ein validate(); und ein repaint(); dran gehängt.
    Da passierte aber nichts. Selbst in der Beschreibung steht bei repaint(); dass lediglich versucht wird, so schnell wie möglich zu zeichnen.
    Das hilft aber nicht viel, weil er quasi nach jeden Schleifendurchlauf was zeichnen muss. Hm, ich habe jetzt gerade eine Idee, wie ich ihn vielleicht doch zum Zeichnen bringe, ohne dass ich die ganze Berechnung in paint(Graphics g) habe.

    Das muss ich heute abend mal ausprobieren. Aber vielleicht hast Du ja schon was, was helfen könnte.

  7. #7 Zitieren
    Knight Commander Avatar von Kellendil
    Registriert seit
    Jul 2009
    Beiträge
    2.093
    So dumm ist das gar nicht, wenn man eine hohe Kontrolle über das zeichnen braucht (z.B. bei Spielen), es gibt aber einen eleganteren Weg:

    Man kann paintImmediatly verwenden, das gibt es genau für sowas. Das blockt aber auch den aktuellen Thread, bis fertig gezeichnet wurde, man gibt damit also (ähnlich wie wenn man den ganzen Code in die paint-Methode packt) das Multi-Threading auf, gewinnt dafürt aber auch mehr Kontrolle und kann dann auch gezielt fps und Input-Event-Abfrage usw. steuern/synchronisieren.
    Kellendil ist offline

  8. #8 Zitieren
    Sergej Petrow
    Gast
    Ich konnte es tatsächlich rausziehen.

    Code:
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    
    import javax.swing.JFrame;
    
    public class Solit extends JFrame
    {
    
    	static short [][][] loesung= new short[32][7][7];
    	static boolean zeichnen=true;
    	
    	public Solit() 
    	{
    		super(); 
            setDefaultCloseOperation(EXIT_ON_CLOSE);       
    	}
    	
    	
    	public void paint(Graphics gs) 
    	{ // @Override ermöglicht dem Compiler die Kontrolle
    		
    	Graphics2D g=(Graphics2D)gs;
    
    	int i,x,y;
    	short inhalt;
    	if (zeichnen)
    	
    	{
    	for (i=0;i<32;i++)
    		
    	{
    	for (y=0;y<7;y++)
    		{
    		for (x=0;x<7;x++)
    			{
    			inhalt=loesung[i][x][y];
    		
    			if (inhalt == 0)
    				{
    				g.setColor(Color.WHITE);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    				g.setColor(Color.BLACK);
    				g.drawOval(x*100+150, y*100+150, 30, 30);
    
    				}
    		
    			else if(inhalt == 1)
    				{
    				g.setColor(Color.GREEN);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    
    				}
    
    			}
    		}
    	
    	try {
    		Thread.sleep(2000);
    	} catch (InterruptedException e) {
    		// TODO Auto-generated catch block
    		e.printStackTrace();
    	}
    	
    	}
    	}
    	
    zeichnen=false;		
    	
     }
    
    	
    	static boolean oben(short A[][], short x, short y)
    	{
    
    	if(y>1) 
    		{
    		if(A[x][y]==1 && A[x][y-1]==1 && A[x][y-2]==0) return true;
    		}
    	return false;
    	}
    
    	static boolean unten(short A[][], short x, short y)
    	{
    
    	if(y<5) 
    		{
    		if(A[x][y]==1 && A[x][y+1]==1 && A[x][y+2]==0) return true;
    		}
    	return false;
    	}
    
    	static boolean links(short A[][], short x, short y)
    	{
    
    	if(x>1) 
    		{
    		if(A[x][y]==1 && A[x-1][y]==1 && A[x-2][y]==0) return true;
    		}
    	return false;
    	}
    
    	static boolean rechts(short A[][], short x, short y)
    	{
    
    	if(x<5)
    		{
    		if(A[x][y]==1 && A[x+1][y]==1 && A[x+2][y]==0) return true;
    		}
    	return false;
    	}
    
    	static void speichern(short A[][], int i)
    		{
    		for(int y=0;y<7;y++)
    			{
    			for(int x=0;x<7;x++)
    				{
    				loesung[i][x][y]=A[x][y];
    				}
    			}
    		}
    
    	static int  soli (short A[][], int i)
    	{
    		int ergebnis=0;
    	if (i<31) 
    		{
    		i++;
    		for (short y=0;y<7;y++)
    			{
    			for (short x=0;x<7;x++)
    				{
    				if(oben(A,x,y)) 
    					{
    					A[x][y]=0; A[x][y-1]=0; A[x][y-2]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if (ergebnis==-2)
    						{
    						A[x][y]=1; A[x][y-1]=1; A[x][y-2]=0;
    						}
    					}
    
    				if(unten(A,x,y))
    					{
    					A[x][y]=0; A[x][y+1]=0; A[x][y+2]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if(ergebnis==-2)
    						{
    						A[x][y]=1; A[x][y+1]=1; A[x][y+2]=0;
    						}
    					}
    				
    				if(links(A,x,y))
    					{
    					A[x][y]=0; A[x-1][y]=0; A[x-2][y]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if (ergebnis==-2)
    						{
    						A[x][y]=1; A[x-1][y]=1; A[x-2][y]=0;
    						}
    					}
    				
    				if(rechts(A,x,y)) 
    					{
    					A[x][y]=0; A[x+1][y]=0; A[x+2][y]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if (ergebnis==-2)
    						{
    						A[x][y]=1; A[x+1][y]=1; A[x+2][y]=0;
    						}
    					}
    				}
    			}
    		i--;
    		return -2;
    		}
    	else	
    		{
    		return -1;
    		}
    
    	}
    
    	public static void main(String[] args)
    	{
    		short [][] A = new short [7][7];
    		A[0][0]=9; A[1][0]=9; A[2][0]=1; A[3][0]=1; A[4][0]=1; A[5][0]=9; A[6][0]=9;
    		A[0][1]=9; A[1][1]=9; A[2][1]=1; A[3][1]=1; A[4][1]=1; A[5][1]=9; A[6][1]=9; 
    		A[0][2]=1; A[1][2]=1; A[2][2]=1; A[3][2]=1; A[4][2]=1; A[5][2]=1; A[6][2]=1;
    		A[0][3]=1; A[1][3]=1; A[2][3]=1; A[3][3]=0; A[4][3]=1; A[5][3]=1; A[6][3]=1;
    		A[0][4]=1; A[1][4]=1; A[2][4]=1; A[3][4]=1; A[4][4]=1; A[5][4]=1; A[6][4]=1;
    		A[0][5]=9; A[1][5]=9; A[2][5]=1; A[3][5]=1; A[4][5]=1; A[5][5]=9; A[6][5]=9;
    		A[0][6]=9; A[1][6]=9; A[2][6]=1; A[3][6]=1; A[4][6]=1; A[5][6]=9; A[6][6]=9; 
    
    		for (int i=0;i<32;i++)
    			{
    			for (int j=0;j<7;j++)
    				{
    				for (int k=0;k<7;k++)
    					{
    					loesung[i][j][k]=0;
    					}
    				}
    			}
    		
    	speichern(A,0);
    
    	soli(A,0);		
    		
    		
    	Solit f= new Solit();	
    	f.setSize(1000, 1000);
    	f.setVisible(true);
    	}
    
    }
    Jetzt ist nur noch der Teil in Paint drin:

    Code:
    Graphics2D g=(Graphics2D)gs;
    
    	int i,x,y;
    	short inhalt;
    	if (zeichnen)
    	
    	{
    	for (i=0;i<32;i++)
    		
    	{
    	for (y=0;y<7;y++)
    		{
    		for (x=0;x<7;x++)
    			{
    			inhalt=loesung[i][x][y];
    		
    			if (inhalt == 0)
    				{
    				g.setColor(Color.WHITE);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    				g.setColor(Color.BLACK);
    				g.drawOval(x*100+150, y*100+150, 30, 30);
    
    				}
    		
    			else if(inhalt == 1)
    				{
    				g.setColor(Color.GREEN);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    
    				}
    
    			}
    		}
    	
    	try {
    		Thread.sleep(2000);
    	} catch (InterruptedException e) {
    		// TODO Auto-generated catch block
    		e.printStackTrace();
    	}
    	
    	}
    	}
    	
    zeichnen=false;
    Also der Teil, in dem tatsächlich nur gezeichnet wird.

    Warum das jetzt funktioniert, liegt daran, dass ich diesen Teil hier:

    Code:
    	Solit f= new Solit();	
    	f.setSize(1000, 1000);
    	f.setVisible(true);
    in der Main von ganz zu Anfang ans Ende geschoben habe. Mir fiel ein, dass wenn ein JFrame neu erstellt wird, auf jeden Fall paint aufgerufen wird. So funktioniert das dann auch.

  9. #9 Zitieren
    Knight Commander Avatar von Kellendil
    Registriert seit
    Jul 2009
    Beiträge
    2.093
    Da hast du aber immer noch nicht den wichtigsten Teil rausgezogen:

    Das Blockieren innerhalb der paint-Methode durch Thread.sleep().

    Das Konzept der paint-Methode ist es, dass die paint-Methode mehrmals pro Sekunde aufgerufen werden kann, z.B. wenn dass Fenster verschoben wird, seine Größe sich ändert oder eine Benutzer-Eingabe erfolgt.

    Indem du die Ausführung der paint-Methode mit Thread-Sleep und der Schleife quasi bis zum Ende des programms verzögerst, machst du viel Funktionalität kaputt. Zum Beispiel kann das Fenster bei dir nicht geschlossen werden, weil der Render-Thread in deiner paint-Methode festhängt, obwohl er davon ausgeht, dass die Methode im Bruchteil einer Sekunde fertig ist und er sich dann anderen Sachen widmen kann wie dem Schließen des Fensters (ich weiß nicht ob es genau so funktioniert, aber so kann man sich das vostellen).

    Wenn man das richtig implementiert macht man das folgendermaßen:

    Blockierende Sleep()-Schleife kommt in den Hautthread und zählt dort hoch, bei welchem Lösungsschritt man sich gerade befindet (hab das A-setzen weggelassen):
    Code:
    	// so the paint method knows which in which step of the solution we are.
    	static int currentStep = 0;
    
    	public static void main(String[] args) {
    		short[][] A = new short[7][7];
    		// .. set A here
    
    		for (int i = 0; i < 32; i++) {
    			for (int j = 0; j < 7; j++) {
    				for (int k = 0; k < 7; k++) {
    					loesung[i][j][k] = 0;
    				}
    			}
    		}
    
    		speichern(A, 0);
    
    		soli(A, 0);
    
    		Solit f = new Solit();
    		f.setSize(1000, 1000);
    		f.setVisible(true);
    		
    		for (int i = 0; i < 32; i++)
    
    		{
    			currentStep++;
    			f.repaint();
    			try {
    				Thread.sleep(2000);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	}
    Die paint-Methode rendert dann das KOMPLETTE Feld aber nur bis zu dem Lösungsschritt, der durch die neue currentStep Variable angedeutet wird:

    Code:
    	@Override
    	public void paint(Graphics gs) { // @Override ermöglicht dem Compiler die
    										// Kontrolle
    
    		Graphics2D g = (Graphics2D) gs;
    
    		if (zeichnen)
    		{
    			for (int i = 0; i < currentStep; i++)
    
    			{
    				for (int y = 0; y < 7; y++) {
    					for (int x = 0; x < 7; x++) {
    						short inhalt = loesung[i][x][y];
    
    						if (inhalt == 0) {
    							g.setColor(Color.WHITE);
    							g.fillOval(x * 100 + 150, y * 100 + 150, 30, 30);
    							g.setColor(Color.BLACK);
    							g.drawOval(x * 100 + 150, y * 100 + 150, 30, 30);
    
    						}
    
    						else if (inhalt == 1) {
    							g.setColor(Color.GREEN);
    							g.fillOval(x * 100 + 150, y * 100 + 150, 30, 30);
    
    						}
    
    					}
    				}
    			}
    		}
    
    	}
    Nun kann die paint-Methode im Bruchteil einer Sekunde abgearbeitet werden und das Konzept mit dem Render-thread funktiomiert, und das Schließen des Fensters geht auch wieder.

    Edit:
    Was noch fehlt wäre, in der paint-Methode vor dem Zeichnen jedesmal mit fillRect() den Hintergrund weiß zu machen, sonst sieht man beim verändern der Fenstergröße noch Teile der alten paint-Ausführungen, das geht sehr einfach:
    Code:
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, getWidth(), getHeight());
    Edit2:
    Mit diesen Veränderungen könntest du jetzt auch Buttons einbauen um die Ausführung der Anzeige zu pausieren oder zu resetten oder Schrittweise pro Buttondruck durchzuführen. Bei deiner paint-Methode dürfte das unmöglich sein, da das Aktiveren eines Buttons nicht bemerkt werden dürfte (wegen dem Festhängen in der paint-Methode).
    Kellendil ist offline Geändert von Kellendil (28.12.2016 um 17:49 Uhr)

  10. #10 Zitieren
    Sergej Petrow
    Gast
    Hm, ich probiere das mal aus.

    Klar, das Thread.sleep ist natürlich ein Problem. Allerdings ging es mir ja in der Hauptsache um das Problem Solitär und ich wollte die einzelnen Schritte verfolgen. Jedenfalls hat das sehr gut geklappt.

    Ich melde mich, wenn ich das eingebaut habe.

  11. #11 Zitieren
    Sergej Petrow
    Gast
    So, hab das eingebaut.

    Mir schleierhaft, was ich vorher versucht habe. Jetzt scheint f.repaint() zu funktionieren.

    Allerdings ist es jetzt zum Ende hin zu langsam. Das heißt es flimmert etwas und man sieht kurze Zeit wieder die kompletten Felder in grün, wenn er neu zeichnen muss. Das ist so etwa ab dem 27. Zug.

    Jetzt müsste ich wieder diese Doppelbufferung einschalten, damit er jeweils erst fertig zeichnen kann.

    Oder aber ich muss den Grafikalgorithmus ändern. Jetzt zeichnet er ja jeweils das ganze Feld und fragt alle Zustände ab. Hm, mal überlegen. Ich könnte auch nur die Züge abspeichern. Da muss ich erst mal schauen, wie ich das mache.

  12. #12 Zitieren
    Pretty Pink Pony Princess  Avatar von Multithread
    Registriert seit
    Jun 2010
    Ort
    Crystal Empire
    Beiträge
    11.228
    Zitat Zitat von Sergej Petrow Beitrag anzeigen
    Klar, das Thread.sleep ist natürlich ein Problem. Allerdings ging es mir ja in der Hauptsache um das Problem Solitär und ich wollte die einzelnen Schritte verfolgen. Jedenfalls hat das sehr gut geklappt.
    Du kannst das 'Thread.sleep' auch in die Berechenmethode einbauen. Oder, was der bessere Ansatz wäre: die Berechnungsmethode mit einem Timer anstossen.
    Dadurch hast du keinen Thread durch ein Sleep blockiert.

    Um Double Buffering kommst du kaum herum, wenn du kein Flickern möchtest.
    [Bild: AMD_Threadripper.png] Bei Hardware gibt es keine eigene Meinung, bei Hardware zählen nur die Fakten.


    Probleme mit der Haarpracht? Starres Haar ohne Glanz? TressFX schafft Abhilfe. Ja, TressFX verhilft auch Ihnen zu schönem und Geschmeidigen Haar.
    [Bild: i6tfHoa3ooSEraFH63.png]
    Multithread ist gerade online

  13. #13 Zitieren
    Legende Avatar von jabu
    Registriert seit
    Jul 2011
    Beiträge
    7.322
    Aber nur wegen Weihnachten (immer noch ein schlanker Ansatz, immer noch dein Algorithmus (auch etwas beschleunigt))...
    Code:
    import java.awt.Color;
    import java.awt.Graphics;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import java.awt.Dimension;
    
    public class Solit extends JPanel
    {
        private static class Token
        {
            public boolean show;
            public Color color;
            public int x;
            public int y;
        }
        
        private static Token[][][] token = new Token[32][7][7];
        private static short[][][] loesung = new short[32][7][7];
        private static int sn = 0;
        private static boolean isTokensInit = false;
    
        @Override
        public Dimension getPreferredSize()
        {
            return new Dimension(1000,1000);
        }
    
        @Override
        public void paintComponent(Graphics g) {
            //super.paintComponent(g);//wegen leistungsproblems auskommentiert
            g.setColor(new Color(225,225,225));
            g.fillRect(0, 0, getWidth(), getHeight());      
            if (isTokensInit) {					
                for (int y = 0; y < 7; y++) {
                    for (int x = 0; x < 7; x++) {
                        if(token[sn][y][x].show) {
                            g.setColor(token[sn][y][x].color);
                            g.fillOval(token[sn][y][x].x, token[sn][y][x].y, 30, 30);
                        }
                    }
                }
            }		
        }
        
        static void berechnen() { 	
            short[][] A = new short[][]{
                { 9,9,1,1,1,9,9 },
                { 9,9,1,1,1,9,9 },
                { 1,1,1,1,1,1,1 },
                { 1,1,1,0,1,1,1 },
                { 1,1,1,1,1,1,1 },
                { 9,9,1,1,1,9,9 },
                { 9,9,1,1,1,9,9 }		
            };	
            for (int n = 0; n < 32; n++)
                for (int y = 0; y < 7; y++)
                    for (int x = 0; x < 7; x++)
                        loesung[n][y][x] = 0;		
            speichern(A, 0);
            soli(A, 0);		
        }
        
        static void fuelleJeZugEinSpielbrett() {
            for (int n = 0; n < 32; n++) {
                for (int y = 0; y < 7; y++) {
                    for (int x = 0; x < 7; x++) {
                        token[n][y][x] = new Token();
                        final short inhalt = loesung[n][y][x];
                        if (inhalt == 0) {
                            token[n][y][x].show = true;
                            token[n][y][x].color = Color.WHITE;	
                            token[n][y][x].x = x*100+200-15;
                            token[n][y][x].y = y*100+200-15;					
                        } else if (inhalt == 1) {
                            token[n][y][x].show = true;
                            token[n][y][x].color = new Color(0,225,0);
                            token[n][y][x].x = x*100+200-15;
                            token[n][y][x].y = y*100+200-15;		
                        }
                    }
                }
            }
            isTokensInit=true;
        }
    
        private static boolean links(short A[][], int x, int y) {
            return (x>1) && (A[y][x]==1) && (A[y][x-1]==1) && (A[y][x-2]==0);
        }
        private static boolean rechts(short A[][], int x, int y) {
            return (x<5) && (A[y][x]==1) && (A[y][x+1]==1) && (A[y][x+2]==0);
        }
        private static boolean oben(short A[][], int x, int y) {
            return (y>1) && (A[y][x]==1) && (A[y-1][x]==1) && (A[y-2][x]==0);
        }
        private static boolean unten(short A[][], int x, int y) {
            return (y<5) && (A[y][x]==1) && (A[y+1][x]==1) && (A[y+2][x]==0);
        }
    
        private static void speichern(short A[][], int n) {
            for(int y=0; y<7; y++)
                for(int x=0; x<7; x++)
                    loesung[n][y][x] = A[y][x];
        }
    
        static boolean soli(short A[][], int n) {
            if (n==31) return true;	
            n++;		
            for (int y=0; y<7; y++) {
                for (int x=0; x<7; x++) {
                    if (links(A,x,y)) {			
                        A[y][x]=0; A[y][x-1]=0; A[y][x-2]=1;
                        speichern(A,n);
                        if(soli(A,n)) return true;
                        A[y][x]=1; A[y][x-1]=1; A[y][x-2]=0;
                    }
                    if (rechts(A,x,y)) {
                        A[y][x]=0; A[y][x+1]=0; A[y][x+2]=1;
                        speichern(A,n);
                        if(soli(A,n)) return true;
                        A[y][x]=1; A[y][x+1]=1; A[y][x+2]=0;
                    }
                    if (oben(A,x,y)) {
                        A[y][x]=0; A[y-1][x]=0; A[y-2][x]=1;
                        speichern(A,n);
                        if(soli(A,n)) return true;
                        A[y][x]=1; A[y-1][x]=1; A[y-2][x]=0;
                    }		
                    if (unten(A,x,y)) {
                        A[y][x]=0; A[y+1][x]=0; A[y+2][x]=1;
                        speichern(A,n);
                        if(soli(A,n)) return true;	
                        A[y][x]=1; A[y+1][x]=1; A[y+2][x]=0;
                    }		
                }
            }		
            return false;
        }
    
        public static void main(String[] args) {
            JFrame f = new JFrame("Solitaer-Simulator");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(new Solit());
            f.pack();
            f.setVisible(true);
            
            berechnen();
            fuelleJeZugEinSpielbrett();
            
            for (int n = 0; n < 32; n++) {
                sn = n;
                f.repaint();
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
    Es sind zahlreiche Verbesserungen eingeflossen. Doch am besten guckst du erst mal selbst, bevor ich wieder Romane schreibe.

    Viel Spaß!

    PS
    Die 64-Bit-JRE hat bei mir gegenüber der 32-Bit-JRE fast doppeltes Tempo ergeben.
    jabu ist offline Geändert von jabu (28.12.2016 um 20:28 Uhr) Grund: etwas aufgeräumt

  14. #14 Zitieren
    Sergej Petrow
    Gast
    Musste mich erst mal durcharbeiten. Es flackert nichts mehr. Da er pro Zyklus tatsächlich nur den aktuellen Zug zeichnen muss und nicht, wie im meinen Beispiel vom 1. bis zum n. Zug zeichnen muss. Das spart natürlich viel Zeit und so viel zu zeichnen ist dann nicht mehr, dass es nicht mehr zum flackern kommt.
    Das lässt sich natürlich in meinem Beispiel ergänzt durch den Code von Kellendil auch sehr leicht einführen, in dem ich einfach die dritte for Schleife entferne und für das i currentStep einfüge:

    Code:
    	public void paint(Graphics gs) 
    	{ // @Override ermöglicht dem Compiler die Kontrolle
    		
    		Graphics2D g=(Graphics2D)gs;
    
    	int x,y;
    	short inhalt;
    	
    	g.setColor(Color.lightGray);
    	g.fillRect(0, 0, getWidth(), getHeight());
    	
    	for (y=0;y<7;y++)
    		{
    		for (x=0;x<7;x++)
    			{
    			inhalt=loesung[currentStep-1][x][y];
    		
    			if (inhalt == 0)
    				{
    				g.setColor(Color.WHITE);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    				g.setColor(Color.BLACK);
    				g.drawOval(x*100+150, y*100+150, 30, 30);
    
    				}
    		
    			else if(inhalt == 1)
    				{
    				g.setColor(Color.GREEN);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    
    				}
    
    		}
    	}
    	
    	
     }
    Das ist natürlich wesentlich eleganter.

    So dass der gesamte Code jetzt so aussieht:

    i
    Code:
    mport java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    
    import javax.swing.JFrame;
    
    public class Solit extends JFrame
    {
    
    	static short [][][] loesung= new short[32][7][7];
    	//static boolean zeichnen=true;
    	static int currentStep=0;
    	
    	public Solit() 
    	{
    		super(); 
            setDefaultCloseOperation(EXIT_ON_CLOSE);       
    	}
    	
    	
    	public void paint(Graphics gs) 
    	{ // @Override ermöglicht dem Compiler die Kontrolle
    		
    	Graphics2D g=(Graphics2D)gs;
    
    	int x,y;
    	short inhalt;
    	
    	g.setColor(Color.lightGray);
    	g.fillRect(0, 0, getWidth(), getHeight());
    	
    	{
    	for (y=0;y<7;y++)
    		{
    		for (x=0;x<7;x++)
    			{
    			inhalt=loesung[currentStep-1][x][y];
    		
    			if (inhalt == 0)
    				{
    				g.setColor(Color.WHITE);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    				g.setColor(Color.BLACK);
    				g.drawOval(x*100+150, y*100+150, 30, 30);
    
    				}
    		
    			else if(inhalt == 1)
    				{
    				g.setColor(Color.GREEN);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    
    				}
    
    			}
    		}
    	}
     }
    
    	
    	static boolean oben(short A[][], short x, short y)
    	{
    
    	if(y>1) 
    		{
    		if(A[x][y]==1 && A[x][y-1]==1 && A[x][y-2]==0) return true;
    		}
    	return false;
    	}
    
    	static boolean unten(short A[][], short x, short y)
    	{
    
    	if(y<5) 
    		{
    		if(A[x][y]==1 && A[x][y+1]==1 && A[x][y+2]==0) return true;
    		}
    	return false;
    	}
    
    	static boolean links(short A[][], short x, short y)
    	{
    
    	if(x>1) 
    		{
    		if(A[x][y]==1 && A[x-1][y]==1 && A[x-2][y]==0) return true;
    		}
    	return false;
    	}
    
    	static boolean rechts(short A[][], short x, short y)
    	{
    
    	if(x<5)
    		{
    		if(A[x][y]==1 && A[x+1][y]==1 && A[x+2][y]==0) return true;
    		}
    	return false;
    	}
    
    	static void speichern(short A[][], int i)
    		{
    		for(int y=0;y<7;y++)
    			{
    			for(int x=0;x<7;x++)
    				{
    				loesung[i][x][y]=A[x][y];
    				}
    			}
    		}
    	
    	static int  soli (short A[][], int i)
    	{
    		int ergebnis=0;
    	if (i<31) 
    		{
    		i++;
    		for (short y=0;y<7;y++)
    			{
    			for (short x=0;x<7;x++)
    				{
    				if(oben(A,x,y)) 
    					{
    					A[x][y]=0; A[x][y-1]=0; A[x][y-2]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if (ergebnis==-2)
    						{
    						A[x][y]=1; A[x][y-1]=1; A[x][y-2]=0;
    						}
    					}
    
    				if(unten(A,x,y))
    					{
    					A[x][y]=0; A[x][y+1]=0; A[x][y+2]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if(ergebnis==-2)
    						{
    						A[x][y]=1; A[x][y+1]=1; A[x][y+2]=0;
    						}
    					}
    				
    				if(links(A,x,y))
    					{
    					A[x][y]=0; A[x-1][y]=0; A[x-2][y]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if (ergebnis==-2)
    						{
    						A[x][y]=1; A[x-1][y]=1; A[x-2][y]=0;
    						}
    					}
    				
    				if(rechts(A,x,y)) 
    					{
    					A[x][y]=0; A[x+1][y]=0; A[x+2][y]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if (ergebnis==-2)
    						{
    						A[x][y]=1; A[x+1][y]=1; A[x+2][y]=0;
    						}
    					}
    				}
    			}
    		i--;
    		return -2;
    		}
    	else	
    		{
    		return -1;
    		}
    
    	}
    
    	public static void main(String[] args)
    	{
    		short [][] A = new short [7][7];
    		A[0][0]=9; A[1][0]=9; A[2][0]=1; A[3][0]=1; A[4][0]=1; A[5][0]=9; A[6][0]=9;
    		A[0][1]=9; A[1][1]=9; A[2][1]=1; A[3][1]=1; A[4][1]=1; A[5][1]=9; A[6][1]=9; 
    		A[0][2]=1; A[1][2]=1; A[2][2]=1; A[3][2]=1; A[4][2]=1; A[5][2]=1; A[6][2]=1;
    		A[0][3]=1; A[1][3]=1; A[2][3]=1; A[3][3]=0; A[4][3]=1; A[5][3]=1; A[6][3]=1;
    		A[0][4]=1; A[1][4]=1; A[2][4]=1; A[3][4]=1; A[4][4]=1; A[5][4]=1; A[6][4]=1;
    		A[0][5]=9; A[1][5]=9; A[2][5]=1; A[3][5]=1; A[4][5]=1; A[5][5]=9; A[6][5]=9;
    		A[0][6]=9; A[1][6]=9; A[2][6]=1; A[3][6]=1; A[4][6]=1; A[5][6]=9; A[6][6]=9; 
    
    		for (int i=0;i<32;i++)
    			{
    			for (int j=0;j<7;j++)
    				{
    				for (int k=0;k<7;k++)
    					{
    					loesung[i][j][k]=0;
    					}
    				}
    			}
    		
    	speichern(A,0);
    
    	soli(A,0);		
    		
    		
    	Solit f= new Solit();	
    	f.setSize(1000, 1000);
    	f.setVisible(true);
    	
    	for (int i = 0; i < 32; i++)
    
    	{
    		currentStep++;
    		f.repaint();
    		try {
    			Thread.sleep(2000);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    	}
    
    }
    Dein Code ist natürlich noch eleganter. Allerdings ist mir nicht ganz ersichtlich, wozu Du extra die Klasse Token eingeführt hast. Klar, da hast Du alle Daten gespeichert. Aber irgendwie ist doch alles relevante schon in loesung drin. Oder wolltest Du alle Rechenprozesse aus paint raushaben, damit er sofort loszeichnen kann?

    Bei meinem Code muss man berücksichtigen, dass ich den bei der Arbeit ohne Javacompiler das ganze innerhalb kürzester Zeit in dem Windowseditor gehackt habe und zuhause nur ausprobieren wollte, ob es so funktioniert. Hat es, ja. Nur eben ohne grafischen Nachweis. Das Problem Grafik entpuppte sich als größeres Problem, als das Problem Solitär an sich.
    Jedenfalls wenn man das berücksichtigt, verzeihe man mir manche nicht vorhandene elegantere Schreibweise. So wusste ich z.B. nicht mehr genau, wie ich direkt die Daten ins Array A eintragen konnte und habe mich dann für die sichere Methode entschieden. War ja auch nur ein kopieren von 7 Zeilen, wo ich nur die Werte austauschen musste.

    Wie schnell ist er bei dir für die Lösung?

    EDIT:
    Bei mir 1.793 Sekunden.

    Ich erinnere mich dunkel an meinen Atari1040 ST. Da hab ich das damals (so um die 1985) in Omnicrombasic geschrieben. Da hat die Berechnung mehr als einen Tag gedauert. [Bild: igitt.gif]
    Was sich bis heute getan hat, ist wirklich unglaublich. Als mir das vor ein paar Tagen wieder einfiel, wollte ich wissen, wie lange sich wohl meine Mühle heute damit beschäftigen muss.

    EDIT2:
    Falls jemand gerade einen Zeitmesser braucht und nicht selbst schreiben möchte. Den hier habe ich mal vor ein paar Jahren geschrieben. Denke, der tut seinen Dienst:

    Code:
    /*stellt eine Stoppuhr zur Verfügung
     * - startZeitmessung(i) startet die Stoppuhr(i)
     * - getZeitmessung(i) zeigt die bisher vergangene Zeit von Stoppuhr(i)
     *   wenn Stoppuhr i nicht gestartet wurde, gibt es -1 zurück.
     * - stopZeitmessung(i) stoppt Stoppuhr(i). 
     * - messe(i) liefert true zurück, wenn Stoppuhr (i) läuft, false, wenn nicht   
     */
    public class Zeitmesser {
    
    private final static int TURNIERE=10; 	
    	
    static long []start=new long[TURNIERE];
    static boolean []messe=new boolean[TURNIERE];
    
    public Zeitmesser()
    {
    	
    }
    
    public static void startZeitmessung(int i)
    	{start[i]=System.currentTimeMillis();
    	 messe[i]=true;}
    
    public static long getZeitmessung(int i)
    	{if(messe[i])
    		{return System.currentTimeMillis()-start[i];}
    	else 
    		{return -1;}
    	}
    
    public static void stopZeitmessung(int i)
    	{messe[i]=false;}
    
    public static boolean messe(int i)
    	{return messe[i];}
    }//end class
    Geändert von Sergej Petrow (28.12.2016 um 21:18 Uhr)

  15. #15 Zitieren
    Pretty Pink Pony Princess  Avatar von Multithread
    Registriert seit
    Jun 2010
    Ort
    Crystal Empire
    Beiträge
    11.228
    Mal so ganz am Rande: Wieso verwendest du Java, benutzt aber nicht einen einzigen Ansatz der Objekt Orientierten Programmierung?

    Ich würde als Ansatz folgende Klassen wählen:
    Code:
        public class Spielfeld
        {
            public Spielfeld(int x, int y)
            {
                _x = x;
                _y = y;
    
                InizialisiereFelder();
            }
    
            /// <summary>
            /// Inizialisieren der Felder.
            /// </summary>
            private void InizialisiereFelder()
            {
                short[,] A = new short[,]{
                { 9,9,1,1,1,9,9 },
                { 9,9,1,1,1,9,9 },
                { 1,1,1,1,1,1,1 },
                { 1,1,1,0,1,1,1 },
                { 1,1,1,1,1,1,1 },
                { 9,9,1,1,1,9,9 },
                { 9,9,1,1,1,9,9 } };
    
                Felder = new Feld[_x, _y];
                for (int y = 0; y < _y; y++)
                {
                    for (int x = 0; x < _x; x++)
                    {
                        Felder[x, y] = new Feld();
                        Felder[x, y].Wert[0] = A[x, y];
                        //Elemente Verlinken
                        if (x > 0)
                        {
                            Felder[x, y].Links = Felder[x - 1, y];
                            Felder[x - 1, y].Rechts = Felder[x, y];
                        }
                        if (y > 0)
                        {
                            Felder[x, y].Darüber = Felder[x, y - 1];
                            Felder[x, y - 1].Darunter = Felder[x, y];
                        }
                    }
                }
            }
    
            private int _x;
            private int _y;
    
            public Feld[,] Felder { get; set; }
    
    
            private bool links(Feld A, int n)
            {
                return (A.Wert[n] == 1) && (A.Links?.Wert[n] == 1) && (A.Links?.Links?.Wert[n] == 0);
            }
            private bool rechts(Feld A, int n)
            {
                return (A.Wert[n] == 1) && (A.Rechts?.Wert[n] == 1) && (A.Rechts?.Rechts?.Wert[n] == 0);
            }
            private bool oben(Feld A, int n)
            {
                return (A.Wert[n] == 1) && (A.Darüber?.Wert[n] == 1) && (A.Darüber?.Darüber?.Wert[n] == 0);
            }
            private bool unten(Feld A, int n)
            {
                return (A.Wert[n] == 1) && (A.Darunter?.Wert[n] == 1) && (A.Darunter?.Darunter?.Wert[n] == 0);
            }
    
            public int soli(int n)
            {
                if (n > 30) return -1;
                n++;
    
                //Wert übernehmen
                for (int y = 0; y < _y; y++)
                {
                    for (int x = 0; x < _x; x++)
                    {
                        var tmpFeld = Felder[x, y];
                        tmpFeld.Wert[n] = tmpFeld.Wert[n - 1];
                    }
                }
    
                //Ergebnis Prüfen
                var ergebnis = 0;
                for (int y = 0; y < _y; y++)
                {
                    for (int x = 0; x < _x; x++)
                    {
                        var tmpFeld = Felder[x, y];
                        if (oben(tmpFeld, n))
                        {
                            tmpFeld.Wert[n] = 0; tmpFeld.Darüber.Wert[n] = 0; tmpFeld.Darüber.Darüber.Wert[n] = 1;
                            speichern(x, y, n);
                            ergebnis = soli(n);
                            if (ergebnis == -1)
                            {
                                return -1;
                            }
                            else if (ergebnis == -2)
                            {
                                tmpFeld.Wert[n] = 1; tmpFeld.Darüber.Wert[n] = 1; tmpFeld.Darüber.Darüber.Wert[n] = 0;
                            }
                        }
    
                        if (unten(tmpFeld, n))
                        {
                            tmpFeld.Wert[n] = 0; tmpFeld.Darunter.Wert[n] = 0; tmpFeld.Darunter.Darunter.Wert[n] = 1;
                            speichern(x, y, n);
                            ergebnis = soli(n);
                            if (ergebnis == -1)
                            {
                                return -1;
                            }
                            else if (ergebnis == -2)
                            {
                                tmpFeld.Wert[n] = 1; tmpFeld.Darunter.Wert[n] = 1; tmpFeld.Darunter.Darunter.Wert[n] = 0;
                            }
                        }
    
                        if (links(tmpFeld, n))
                        {
                            tmpFeld.Wert[n] = 0; tmpFeld.Links.Wert[n] = 0; tmpFeld.Links.Links.Wert[n] = 1;
                            speichern(x, y, n);
                            ergebnis = soli(n);
                            if (ergebnis == -1)
                            {
                                return -1;
                            }
                            else if (ergebnis == -2)
                            {
                                tmpFeld.Wert[n] = 1; tmpFeld.Links.Wert[n] = 1; tmpFeld.Links.Links.Wert[n] = 0;
                            }
                        }
    
                        if (rechts(tmpFeld, n))
                        {
                            tmpFeld.Wert[n] = 0; tmpFeld.Rechts.Wert[n] = 0; tmpFeld.Rechts.Rechts.Wert[n] = 1;
                            speichern(x, y, n);
                            ergebnis = soli(n);
                            if (ergebnis == -1)
                            {
                                return -1;
                            }
                            else if (ergebnis == -2)
                            {
                                tmpFeld.Wert[n] = 1; tmpFeld.Rechts.Wert[n] = 1; tmpFeld.Rechts.Rechts.Wert[n] = 0;
                            }
                        }
                    }
                }
                return -2;
            }
    
            private void speichern(int x, int y, int n)
            {
                //Was müsste Ich hier machen?  bzw. welchen Status fragst du ab?
            }
    
            /// <summary>
            /// Exportieren des aktuellen Feldstatus;
            /// </summary>
            /// <returns></returns>
            public short[,] ExportiereResultate()
            {
                var tmpShort = new short[_x, _y];
    
                for (int y = 0; y < _y; y++)
                {
                    for (int x = 0; x < _x; x++)
                    {
                        tmpShort[x, y] = (short)Felder[x, y].Wert[1];
                    }
                }
                return tmpShort;
            }
        }
    
        //Ein einzelnes Feld
        public class Feld
        {
            public Feld Links { get; set; }
            public Feld Rechts { get; set; }
            public Feld Darunter { get; set; }
            public Feld Darüber { get; set; }
    
            public int[] Wert { get; set; } = new int[32];
        }
    Um diesen Code dann per
    Code:
                Spielfeld _feld = new Spielfeld(7, 7);
                _feld.soli(0);
    zu Inizialisieren und Starten.

    Ich komme mit meinem Code auf >6 Sekunden.
    Bei mir geht er jede Prüfunktion ca. 375 719 885 Durch, das erscheint mir etwas viel.
    Ich will auch gar nicht erst behaupten den Code verstanden zu haben (Auf Mathematisch logischer ebene).

    Mir ist auch nicht klar, wo und wann du die einzelnen Stufen für das Zeichnen herausarbeiten kannst. Mir erscheint es als ob der Code zuerst durchläuft und du danach nur noch die einzelnen Ebenen anzeigst.

    Der Code ist zwar C#, dürfte aber beinahe 1:1 in Java übernehmbar sein.
    [Bild: AMD_Threadripper.png] Bei Hardware gibt es keine eigene Meinung, bei Hardware zählen nur die Fakten.


    Probleme mit der Haarpracht? Starres Haar ohne Glanz? TressFX schafft Abhilfe. Ja, TressFX verhilft auch Ihnen zu schönem und Geschmeidigen Haar.
    [Bild: i6tfHoa3ooSEraFH63.png]
    Multithread ist gerade online Geändert von Multithread (28.12.2016 um 22:25 Uhr)

  16. #16 Zitieren
    Sergej Petrow
    Gast
    Es war einfach nicht nötig, Schema objektorientiert zu durchlaufen.

    Es geht ja bei der Objektorientierung darum, einen deutlicheren Code zu schreiben. Ich denke, der Code ist kurz und mMn auch sehr lesbar geschrieben, so dass es eigentlich keine weiteren tieferen Erklärungen braucht. Java deshalb, weil ich es zur Hand hab und weil ich es einigermaßen beherrsche. Hätten aber auch andere Sprachen sein können.

    Bei mir geht er jede Prüfunktion ca. 375 719 885 Durch, das erscheint mir etwas viel.
    Ich will auch gar nicht erst behaupten den Code verstanden zu haben (Auf Mathematisch logischer ebene).
    Das kann durchaus sein. Es geht immerhin 31 Züge tief, die per Brute Force ermittelt werden.

    Das Kernstück ist das hier:

    Code:
    static int  soli (short A[][], int i)
    	{
    		int ergebnis=0;
    	if (i<31) 
    		{
    		i++;
    		for (short y=0;y<7;y++)
    			{
    			for (short x=0;x<7;x++)
    				{
    				if(oben(A,x,y)) 
    					{
    					A[x][y]=0; A[x][y-1]=0; A[x][y-2]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if (ergebnis==-2)
    						{
    						A[x][y]=1; A[x][y-1]=1; A[x][y-2]=0;
    						}
    					}
    
    				if(unten(A,x,y))
    					{
    					A[x][y]=0; A[x][y+1]=0; A[x][y+2]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if(ergebnis==-2)
    						{
    						A[x][y]=1; A[x][y+1]=1; A[x][y+2]=0;
    						}
    					}
    				
    				if(links(A,x,y))
    					{
    					A[x][y]=0; A[x-1][y]=0; A[x-2][y]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if (ergebnis==-2)
    						{
    						A[x][y]=1; A[x-1][y]=1; A[x-2][y]=0;
    						}
    					}
    				
    				if(rechts(A,x,y)) 
    					{
    					A[x][y]=0; A[x+1][y]=0; A[x+2][y]=1;
    					speichern(A,i);
    					ergebnis=soli(A,i);
    					if(ergebnis==-1) 
    						{
    						return -1;
    						}
    					else if (ergebnis==-2)
    						{
    						A[x][y]=1; A[x+1][y]=1; A[x+2][y]=0;
    						}
    					}
    				}
    			}
    		i--;
    		return -2;
    		}
    	else	
    		{
    		return -1;
    		}
    
    	}
    Das ist eine rekursive Methode, die als erstes erst einmal die Lösung ermittelt. Die Lösung ist erreicht, wenn 31 Sprünge erfolgt sind => 32 Steine, pro Sprung wird einer eliminiert und am Ende muss ein Stein übrig bleiben = 31 Sprünge.
    Die Methode startet damit, ob ein bestimmter Sprung (oben, unten, rechts, links) möglich ist. Ist er möglich, wird diese Stellung im Array loesung gespeichert incl. der Anzahl der bisherigen Sprünge. Danach wird genau diese Stellung neu übergeben in Soli und er prüft wieder den möglichen Sprung und speichert die Pos und springt weiter.

    Es gibt zwei Abbruchmöglichkeiten. Die erste Abbruchmöglichkeit ist, wenn n= 32 ist. Ist dies erreicht, haben wir die Lösung, da wir 31. Sprünge geschafft haben und nur noch ein Stein übrig sein kann. Wenn das passiert, kommt der Return -1. Da hüpft er dann nur noch zurück bis zum ersten Aufruf und beendet die Methode.
    Nun haben wir alle Stellungen bis zum 31. Sprung gespeichert und können uns an die Ausgabe machen. loesung[sprung][x][y]. Rufe ich beispielsweise loesung [5][4][3] auf, bekomme ich den Inhalt der Stellung nach dem 5 Sprung (0 ist die Grundstellung) bei der Position x=4 und y=3 (0 für kein Stein, 1 für ein Stein).

    Es gibt aber noch eine zweite Abbruchmöglichkeit. Die kommt dann auf das Tablett, wenn in der angegebenen Stellung kein Zug mehr möglich ist und noch keine 31 Sprünge absolviert wurden. Dann springt er um einen zurück, schreibt die ursprünglichen Werte, die wir überschrieben hatten, wieder ein und versucht dann, ob die anderen Sprünge unten, links, rechts möglich sind. Wenn nicht, geht er noch einen zurück, usw. D.h. er geht dabei soweit zurück, bis er wieder eine Stellung erreicht, wo noch ein weiterer Zug möglich ist und dann geht es wieder vorwärts. Die zweite Abbruchmöglichkeit habe ich mit -2 deklariert und sorgt eben dafür, dass der vorherige Aufruf von soli einfach weiter abgearbeitet wird.

    Das schöne ist dann, dass wenn der 31. Zug geschafft wird, tatsächlich alle nötigen Daten zusammengetragen sind und wirklich einzeln abgerufen werden können.
    Soweit klar?

    EDIT:
    Ich habe mir gerade mal deinen Code angeschaut. Irgendwie kommt mir das so lang vor. Du machst da irgendwie viel mehr, als ich. Vielleicht kommt die zeitliche Verzögerung ja dadurch?!? Gerade weil es ja ne rekursive Methode ist. Wobei man natürlich schauen muss, was da für Rechner überhaupt dran sind. Aber ich denke, dass deine Hardware deutlich besser ist, als meine, da hätte ich dann eher eine niedrigere Zeit erwartet.
    Hast Du denn die gleiche Lösung? Ich sehe irgendwie nicht, wo Du die einzelnen Stellungen speicherst.
    Geändert von Sergej Petrow (28.12.2016 um 23:16 Uhr)

  17. #17 Zitieren
    Knight Commander Avatar von Kellendil
    Registriert seit
    Jul 2009
    Beiträge
    2.093
    Zitat Zitat von Sergej Petrow Beitrag anzeigen
    Musste mich erst mal durcharbeiten. Es flackert nichts mehr. Da er pro Zyklus tatsächlich nur den aktuellen Zug zeichnen muss und nicht, wie im meinen Beispiel vom 1. bis zum n. Zug zeichnen muss. Das spart natürlich viel Zeit und so viel zu zeichnen ist dann nicht mehr, dass es nicht mehr zum flackern kommt.
    Jup, das hätte ich eigentlich sehen müssen.


    So, ich hab jetzt den verbesserten Code von Sergey genommen und ihn
    - schöner
    - allgemeiner/abstrakter
    - kürzer und
    - schneller gemacht.

    Er läuft beim ersten Durchlauf in ca. 150ms durch, 100 Durchläufe haben eine Durchschnittszeit von 72ms (auf meinem 5 Jahre alten Laptop mit i5). Keine Ahnung warum der so schnell geworden ist, der Original-Code war sehr viel langsamer. Vlt. mess ich ja auch falsch (Messung ist im Code enthalten).

    Ziel war es auch, mit dem Code andere Formen rechnen zu können (z.B. 9x9 mit 3x3 Ecken anstatt 7x7 mit 2x2 Ecken). Man kann das auch einstellen, aber dann hängt er sich in ner Endlosschleife fest. Wer Lust hat, kann das ja debuggen : D

    Code:
    Code:
    package test;
    
    import static test.Solit.Spot.FREE;
    import static test.Solit.Spot.FULL;
    import static test.Solit.Spot.NO_SPOT;
    
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    
    import javax.swing.JFrame;
    
    public class Solit {
    
    	public enum Spot {
    		FULL,
    		FREE,
    		NO_SPOT // für ecken
    	}
    	
    	private final boolean zeichnen = true;
    	
    	private final int fieldSize; // z.B. 7: wie viele Stellen/Spots es in jede Richtung gibt
    	private final int edgeSize; // z.B. 2: wie viele Stellen/Spots bei jeder Ecke frei bleiben (in jede Richtung)
    	
    	private Spot[][][] loesung; // pro step pro x pro y
    	
    	public Solit(int fieldSize, int edgeSize, Point freeStartSpotCoords) {
    		this.fieldSize = fieldSize;
    		this.edgeSize = edgeSize;
    		
    		int numberOfSpots = (fieldSize * fieldSize) - (edgeSize * edgeSize * 4) - 1;
    		
    		long totalTime = 0;
    		int tests = 100;
    		for (tests = 0; tests < 100; tests++) {
    			long startTime = System.currentTimeMillis();
    			Spot[][] field = initField(edgeSize, freeStartSpotCoords);
    			
    			loesung = new Spot[numberOfSpots][fieldSize][fieldSize];
    			loesung[0] = field;
    			soli(field, 0);
    			long time = System.currentTimeMillis() - startTime;
    			System.out.println("Time: " + time);
    			totalTime += time;
    		}
    		System.out.println("Average: " + totalTime/tests);
    
    		if (zeichnen) {
    			SolitViewerFrame frame = new SolitViewerFrame(loesung[0]);
    			for (int i = 0; i < numberOfSpots; i++)
    			{
    				frame.field = loesung[i];
    				frame.repaint();
    				try {
    					Thread.sleep(1000);
    				} catch (InterruptedException e) {}
    			}
    		}
    	}
    	
    	private Spot[][] initField(int edgeSize, Point startFieldIndex) {
    		
    		// Spielfeld bestehend aus "Löchern"(Spots), siehe FieldSpot enum
    		Spot[][] field = new Spot[fieldSize][fieldSize];
    		
    		// felder besetzten, ecken entfernen
    		for (int x = 0; x < field.length; x++) {
    			for (int y = 0; y < field[x].length; y++) {
    				field[x][y] = isEdgeSpot(new Point(x, y)) ? NO_SPOT : FULL;
    			}
    		}
    		// startfeld
    		field[startFieldIndex.x][startFieldIndex.y] = FREE;
    		
    		return field;
    	}
    	
    	boolean isEdgeSpot(Point p) {
    		return p.x < edgeSize && (p.y < edgeSize || p.y >= fieldSize-edgeSize)
    			|| p.x >= fieldSize - edgeSize && (p.y < edgeSize || p.y >= fieldSize-edgeSize);
    	}
    	
    	boolean jump(Spot[][] field, Point from, Point dir, boolean reverse) {
    		Point over = new Point(from.x + dir.x, from.y + dir.y);
    		Point to = new Point(over.x + dir.x, over.y + dir.y);
    		boolean inBounds = !isEdgeSpot(over) &&
    				dir.y == -1 ? to.y >= 0 : dir.y == 1 ? to.y < fieldSize :
    				dir.x == -1 ? to.x >= 0 : dir.x == 1 ? to.x < fieldSize : false;
    		boolean canJump = inBounds
    			&& field[from.x][from.y] == FULL
    			&& field[over.x][over.y] == FULL
    			&& field[to.x][to.y] == FREE;
    		if (inBounds && (canJump || reverse)) {
    			field[from.x][from.y] = reverse ? FULL : FREE;
    			field[over.x][over.y] = reverse ? FULL : FREE;
    			field[to.x][to.y] = reverse ? FREE : FULL;
    		}
    		return canJump;
    	}
    	
    	private void speichern(Spot[][] field, int step) {
    		Spot[][] result = field.clone();
    		for (int i = 0; i < result.length; i++) {
    			result[i] = result[i].clone();
    		}
    		loesung[step] = result;
    	}
    
    	private int soli(Spot[][] field, int step) {
    		int ergebnis = 0;
    		if (step < loesung.length - 1) {
    			step++;
    			for (int x = 0; x < field.length; x++) {
    				for (int y = 0; y < field[x].length; y++) {
    					// try all 4 directions for jumping
    					final Point currentCoord = new Point(x, y);
    					final Point[] directions =
    						{ new Point(0,-1), new Point(0,1), new Point(-1,0), new Point(1,0) };
    					for (final Point dir : directions) {
    						if (jump(field, currentCoord, dir, false)) {
    							ergebnis = soli(field, step);
    							if (ergebnis == -1) {
    								speichern(field, step);
    								jump(field, currentCoord, dir, true);
    								return -1;
    							} else if (ergebnis == -2) {
    								jump(field, currentCoord, dir, true);
    							}
    						}
    					}
    				}
    			}
    			step--;
    			return -2;
    		} else {
    			return -1;
    		}
    	}
    	
    	@SuppressWarnings("serial")
    	private static class SolitViewerFrame extends JFrame {
    		
    		public Spot[][] field;
    		
    		public SolitViewerFrame(Spot[][] first) {
    			super();
    			this.field = first;
    			setDefaultCloseOperation(EXIT_ON_CLOSE);
    			setSize(field.length * 100, field[0].length * 100);
    			setVisible(true);
    		}
    
    		@Override
    		public void paint(Graphics gs) {
    			Graphics2D g = (Graphics2D) gs;
    			g.setColor(Color.WHITE);
    		    g.fillRect(0, 0, getWidth(), getHeight());
    
    			for (int x = 0; x < field.length; x++) {
    				for (int y = 0; y < field[x].length; y++) {
    					Spot inhalt = field[x][y];
    					
    					if (inhalt == FREE) {
    						g.setColor(Color.WHITE);
    						g.fillOval(x * 60 + 150, y * 60 + 150, 30, 30);
    						g.setColor(Color.BLACK);
    						g.drawOval(x * 60 + 150, y * 60 + 150, 30, 30);
    					}
    					else if (inhalt == FULL) {
    						g.setColor(Color.GREEN);
    						g.fillOval(x * 60 + 150, y * 60 + 150, 30, 30);
    					}
    				}
    			}
    		}
    	}
    	
    	public static void main(String[] args) {
    		new Solit(7, 2, new Point(3, 3));
    //		new Solit(9, 3, new Point(4, 4));
    	}
    }
    Falls mal jemand Code für Solitair braucht, wird er hier eine wahre Fundgrube finden
    Kellendil ist offline Geändert von Kellendil (29.12.2016 um 00:41 Uhr)

  18. #18 Zitieren
    Sergej Petrow
    Gast
    ^^uff,uff. Da muss ich jetzt erst mal durchsteigen. Da verstehe ich so erst mal nur die Hälfte von.
    Kleiner Hinweis für unliebsame Überraschungen. Das Spiel muss nicht immer aufgehen. Es ist also auch möglich, dass mehr als ein Stein übrig bleibt, je nach Eingangsvoraussetzungen. So haben die das jedenfalls oben im verlinkten Wikitext geschrieben.

    EDIT:
    Er kommt bei mir mit den ersten drei imports nicht klar und hat dementsprechend auch im späteren Verlauf Fehler.
    import static test.Solit.Spot.FREE;
    import static test.Solit.Spot.FULL;
    import static test.Solit.Spot.NO_SPOT;
    Geändert von Sergej Petrow (29.12.2016 um 10:43 Uhr)

  19. #19 Zitieren
    Knight Commander Avatar von Kellendil
    Registriert seit
    Jul 2009
    Beiträge
    2.093
    Mach vlt. mal das "package test;" und die "test." bei den folgenden imports weg.

    Wenn du es lässt, musst du das auch als package kompilieren (code muss im Unterordner "test" liegen und Main-Klasse beim Kompilieren ist dann "test.Solit"). Manuell kompilieren ist mit packages glaub ich etwas nervig.

    Edit:
    Ich hab in dem Code mehr oder weniger nur alle nackten Zahlen durch sinnvoll benannte Variablen ausgetauscht, außerdem die 4 Sprung-Methoden (oben, unten, rechts, links) zu einer einzigen namens "jump" zusammengefasst, Das Spielfeld speichert jetzt ein enum mit FULL (vorher 1), FREE (vorher 0) und NO-SPOT (vorher 9?), die Ecken-Stellen werden dynamisch ausgerechnet (ebenso wie die Anzahl der maximalen Schritte, also 31 bei 7x7) und das ganze ist ein bisschen umstrukturiert.

    Edit2:
    Achja, es gibt 2 grundlegende Änderungen am Algorithmus: Es wird geprüft, ob in eine ungültige Ecke gesprungen wird. Das ist bei 7x7 reduntant, bei 9x9 aber nötig denke ich.
    Wichtiger:
    Das Feld wird nicht mehr bei jedem MÖGLICHEN Zug in die Lösung geschrieben, sondern nur noch bei jedem KORREKTEN Zug, also 31 mal, und zwar dann, wenn die Rekursion nach dem 31. Zug rückwärts läuft. Das mache ich, in dem ich vor jedem return den Zug wieder rückgängig mache, so erhalte ich die alten Züge. Das ist vlt. der Grund, warum es so schnell ist.
    Kellendil ist offline Geändert von Kellendil (29.12.2016 um 18:13 Uhr)

  20. #20 Zitieren
    Sergej Petrow
    Gast
    Hm, es läuft bei mir immer noch nicht. Selbst wenn ich das rausnehme, werden Errors angezeigt? Mir noch nicht ganz klar, warum er es nicht macht.

    Dafür hab ich auch was neues. Auf deine Zeit komme ich zwar nicht, was mir ein Rätsel ist, weil ich immerhin einen i7 drin habe. Aber ich komme jetzt auf 1.4 Sekunden. Und zwar wird jetzt nur noch der Zug gespeichert. Dazu braucht es nur drei Werte, die gespeichert werden müssen: Die Position, also x und y und die Richtung. Alles weitere ergibt sich ja aus der Regel. Beim Zeichnen später dann wird einmal die Grundstellung gezeichnet und dann nur noch die einzelnen Züge.

    Bei deinem Code muss ich noch ein wenig nachdenken. So richtig verstehe ich ihn noch nicht. Mag an den englischen Bezeichnern liegen Aber da komme ich noch durch, wenn ich ihn erst mal zum laufen bekomme.

    Code:
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    
    
    import javax.swing.JFrame;
    
    public class Solit extends JFrame
    {
    
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = -4382011225551225106L;
    	
    	final static int OBEN=1;
    	final static int UNTEN=2;
    	final static int LINKS=3;
    	final static int RECHTS=4;
    	
    	static short [][][] loesung= new short[1][7][7];
    	static Zug [] zug=new Zug[32];
    	static int currentStep=0;
    	static boolean zeichnen=false;
    	static boolean zugzeichnen=false;
    	
    	public Solit() 
    	{
    		super(); 
            setDefaultCloseOperation(EXIT_ON_CLOSE);  
            
            for (int i=0;i<32;i++)
            {
            	zug[i]= new Zug();
            }		
    
    	}
    	
    	
    	public void paint(Graphics gs) 
    	{ // @Override ermöglicht dem Compiler die Kontrolle
    		
    	Graphics2D g=(Graphics2D)gs;
    
    	int x,y;
    	short inhalt;
    
    	if(zeichnen)
    	{
    	g.setColor(Color.lightGray);
    	g.fillRect(0, 0, getWidth(), getHeight());
    	
    	{
    	for (y=0;y<7;y++)
    		{
    		for (x=0;x<7;x++)
    			{
    			inhalt=loesung[currentStep-1][x][y];
    		
    			if (inhalt == 0)
    				{
    				g.setColor(Color.WHITE);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    				g.setColor(Color.BLACK);
    				g.drawOval(x*100+150, y*100+150, 28, 28);
    
    				}
    		
    			else if(inhalt == 1)
    				{
    				g.setColor(Color.GREEN);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    
    				}
    
    			}
    		}
    	}
    	}
    	
    	if(zugzeichnen)
    	{
    		switch (zug[currentStep-1].richtung)
    		{
    		case OBEN:
    			g.setColor(Color.WHITE);
    			g.fillOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.fillOval(zug[currentStep-1].x*100+150, (zug[currentStep-1].y-1)*100+150, 30, 30);			
    			g.setColor(Color.BLACK);
    			g.setColor(Color.lightGray);
    			g.drawOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.drawOval(zug[currentStep-1].x*100+150, (zug[currentStep-1].y-1)*100+150, 30, 30);			
    			g.setColor(Color.GREEN);
    			g.fillOval(zug[currentStep-1].x*100+150, (zug[currentStep-1].y-2)*100+150, 30, 30);			
    			break;
    			
    		case UNTEN:
    			g.setColor(Color.WHITE);
    			g.fillOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.fillOval(zug[currentStep-1].x*100+150, (zug[currentStep-1].y+1)*100+150, 30, 30);			
    			g.setColor(Color.BLACK);
    			g.drawOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.drawOval(zug[currentStep-1].x*100+150, (zug[currentStep-1].y+1)*100+150, 30, 30);			
    			g.setColor(Color.GREEN);
    			g.fillOval(zug[currentStep-1].x*100+150, (zug[currentStep-1].y+2)*100+150, 30, 30);			
    			break;
    
    		case LINKS:
    			g.setColor(Color.WHITE);
    			g.fillOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.fillOval((zug[currentStep-1].x-1)*100+150, zug[currentStep-1].y*100+150, 30, 30);			
    			g.setColor(Color.BLACK);
    			g.drawOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.drawOval((zug[currentStep-1].x-1)*100+150, zug[currentStep-1].y*100+150, 30, 30);			
    			g.setColor(Color.GREEN);
    			g.fillOval((zug[currentStep-1].x-2)*100+150, zug[currentStep-1].y*100+150, 30, 30);			
    			break;
    
    		case RECHTS:
    			g.setColor(Color.WHITE);
    			g.fillOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.fillOval((zug[currentStep-1].x+1)*100+150, zug[currentStep-1].y*100+150, 30, 30);			
    			g.setColor(Color.BLACK);
    			g.drawOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.drawOval((zug[currentStep-1].x+1)*100+150, zug[currentStep-1].y*100+150, 30, 30);			
    			g.setColor(Color.GREEN);
    			g.fillOval((zug[currentStep-1].x+2)*100+150, zug[currentStep-1].y*100+150, 30, 30);			
    			break;
    			
    		default:
    
    		}
    	}
     }
    
    	
    	static boolean oben(short A[][], short x, short y)
    	{
    
    	if(y>1 && A[x][y]==1 && A[x][y-1]==1 && A[x][y-2]==0) return true;
    		
    	return false;
    	}
    
    	static boolean unten(short A[][], short x, short y)
    	{
    
    	if(y<5 && A[x][y]==1 && A[x][y+1]==1 && A[x][y+2]==0) return true;
    		
    	return false;
    	}
    
    	static boolean links(short A[][], short x, short y)
    	{
    
    	if(x>1 && A[x][y]==1 && A[x-1][y]==1 && A[x-2][y]==0) return true;
    		
    	return false;
    	}
    
    	static boolean rechts(short A[][], short x, short y)
    	{
    
    	if(x<5 && A[x][y]==1 && A[x+1][y]==1 && A[x+2][y]==0) return true;
    		
    	return false;
    	}
    
    	static void speichern(short A[][], int i)
    		{
    		for(int y=0;y<7;y++)
    			{
    			  for(int x=0;x<7;x++)
    				{
    				loesung[i][x][y]=A[x][y];
    				}
    			}
    		
    		}
    	
    	static void zug_speichern(int x, int y, int richtung, int zug)
    	{
    		Solit.zug[zug].x=x;
    		Solit.zug[zug].y=y;
    		Solit.zug[zug].richtung=richtung;
    	}
    	
    	static boolean  soli (short A[][], int i)
    	{
    	boolean inhalt;	
    	if (i<31) 
    		{
    		i++;
    		for (short y=0;y<7;y++)
    			{
    			for (short x=0;x<7;x++)
    				{
    				if(oben(A,x,y)) 
    					{
    					A[x][y]=0; A[x][y-1]=0; A[x][y-2]=1;
    					inhalt=soli(A,i);
    					if(inhalt) {
    						zug_speichern(x,y,OBEN,i);
    						return true;
    					}
    					else {A[x][y]=1; A[x][y-1]=1; A[x][y-2]=0;}						
    					}
    
    				if(unten(A,x,y))
    					{
    					A[x][y]=0; A[x][y+1]=0; A[x][y+2]=1;
    					inhalt=soli(A,i);
    					if(inhalt) {
    						zug_speichern(x,y,UNTEN,i);
    						return true;
    					}
    					else {A[x][y]=1; A[x][y+1]=1; A[x][y+2]=0;}
    					}
    				
    				if(links(A,x,y))
    					{
    					A[x][y]=0; A[x-1][y]=0; A[x-2][y]=1;
    					inhalt=soli(A,i);
    					if(inhalt) {
    						zug_speichern(x,y,LINKS,i);
    						return true;
    					}
    					else {A[x][y]=1; A[x-1][y]=1; A[x-2][y]=0;}
    					}
    				
    				if(rechts(A,x,y)) 
    					{
    					A[x][y]=0; A[x+1][y]=0; A[x+2][y]=1;
    					inhalt=soli(A,i);
    					if(inhalt) {
    						zug_speichern(x,y,RECHTS,i);
    						return true;
    					}
    					else {A[x][y]=1; A[x+1][y]=1; A[x+2][y]=0;}
    					}
    				}
    			}
    		i--;
    		return false;
    		}
    	else	
    		{
    		return true;
    		}
    }
    
    
    	public static void main(String[] args)
    	{
    		Solit f= new Solit();	
    		f.setSize(1000, 1000);
    		f.setVisible(true);
    
    		
    		short [][] A = new short [][]{
                { 9,9,1,1,1,9,9 },
                { 9,9,1,1,1,9,9 },
                { 1,1,1,1,1,1,1 },
                { 1,1,1,0,1,1,1 },
                { 1,1,1,1,1,1,1 },
                { 9,9,1,1,1,9,9 },
                { 9,9,1,1,1,9,9 }		
            };	
    
    
    			speichern(A,0);
    
    	Zeitmesser.startZeitmessung(1);
    	soli(A,0);		
    	System.out.println(Zeitmesser.getZeitmessung(1)/1000.0);
    	Zeitmesser.stopZeitmessung(1);	
    
    	zeichnen=true;
    		currentStep++;
    		f.repaint();
    		try {
    			Thread.sleep(2000);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	zeichnen=false;	
    	
    	zugzeichnen=true;
    	for (int i=1;i<32;i++)
    	{
    		currentStep++;
    		f.repaint();
    		try {
    			Thread.sleep(2000);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    	
    	
    class Zug
    	{
    int x,y;
    int richtung;
    
    public Zug()
    	{
    	x=0;
    	y=0;
    	richtung=0;
    	}
    
    	}
    
    }
    EDIT:
    Hab deine Idee mal übernommen, statt immer sofort zu speichern, nur einmal auf dem Rückweg zu speichern. Unglaublich. Obwohl es nur noch drei Werte waren, die gespeichert werden, ist er von 1.4etwas auf 1.1 etwas schneller geworden. dreizehntel Sekunden. Der Hammer. Natürlich noch sehr weit weg von 72 milisekunden. Aber wenn Du nur noch einen Jumpaufruf brauchst, leuchtet das schon irgendwie ein. Nur hab ich noch nicht genau verstanden, wie Du das gemacht hast.

    EDIT2:
    Ich glaube, deine Zeitmessung stimmt nicht. Habe das auch mal mit 100 mal gemacht und hatte auf einmal die gleiche Zeit, war sogar noch etwas schneller, als bei dir. Das kam mir sehr spanisch vor.
    Das Problem ist, dass das ursprüngliche Array nicht mehr passt. Man übergibt zwar das Array, aber es wird mit Aufruf trotzdem alle Änderungen haben, die die Methode ermittelt hat. Am Ende ist also im Array A nur noch ein Stein vorhanden. Und dieses Array mit dem einen Stein wird dann über die Zeit Ermittlungsschleife gejagt. Da es da aber keinen Zug mehr gibt, wird Soli sofort beendet. Weiß nicht mehr genau, wie das heißt, wenn ein Array übergeben wird. Da wird quasi nicht ein neues Array aufgemacht, sondern es wird nur die Adresse übergeben. Ein Point war das nicht, das war noch ein anderer Begriff. EDIT3: Referenzen war das Wort, welches ich suchte. Ich habe das jetzt jedenfalls mal probiert, in dem ich jedes Mal das Array wieder neu erstellt habe auf die Ausgangsstellung und dann passt es auch. 117,455 Sekunden /100 ergibt 1,17455 Sekunden pro Versuch.

    EDIT3:
    Was da noch alles möglich ist...
    Habe jetzt in der Methode soli bevor es zum Prüfen geht, noch eine Vorabprüfung eingebaut. Eigentlich braucht man ja nur prüfen, wenn x,y überhaupt ein Stein ist. Erst dann macht es Sinn. Dazu wird einfach noch eine If-Abfrage mit if (A[x][y]==1) eingeführt.
    Das hat die Zeit drastisch gesenkt. Jetzt komme ich auf 0.6 Sekunden. Also fast die Zeit zum Lösung halbiert. Wahnsinn.


    Code:
    	static boolean  soli (short A[][], int i)
    	{
    	boolean inhalt;	
    	if (i<31) 
    		{
    		i++;
    		for (short y=0;y<7;y++)
    			{
    			for (short x=0;x<7;x++)
    				{
                                    if(A[x][y]==1)
                                    {
    				if(oben(A,x,y)) 
    					{
    					A[x][y]=0; A[x][y-1]=0; A[x][y-2]=1;
    					inhalt=soli(A,i);
    					if(inhalt) {
    						zug_speichern(x,y,OBEN,i);
    						return true;
    					}
    					else {A[x][y]=1; A[x][y-1]=1; A[x][y-2]=0;}						
    					}
    
    				if(unten(A,x,y))
    					{
    					A[x][y]=0; A[x][y+1]=0; A[x][y+2]=1;
    					inhalt=soli(A,i);
    					if(inhalt) {
    						zug_speichern(x,y,UNTEN,i);
    						return true;
    					}
    					else {A[x][y]=1; A[x][y+1]=1; A[x][y+2]=0;}
    					}
    				
    				if(links(A,x,y))
    					{
    					A[x][y]=0; A[x-1][y]=0; A[x-2][y]=1;
    					inhalt=soli(A,i);
    					if(inhalt) {
    						zug_speichern(x,y,LINKS,i);
    						return true;
    					}
    					else {A[x][y]=1; A[x-1][y]=1; A[x-2][y]=0;}
    					}
    				
    				if(rechts(A,x,y)) 
    					{
    					A[x][y]=0; A[x+1][y]=0; A[x+2][y]=1;
    					inhalt=soli(A,i);
    					if(inhalt) {
    						zug_speichern(x,y,RECHTS,i);
    						return true;
    					}
    					else {A[x][y]=1; A[x+1][y]=1; A[x+2][y]=0;}
    					}
    				}
                             }
    			}
    		i--;
    		return false;
    		}
    	else	
    		{
    		return true;
    		}
    }
    Das ganze also jetzt:

    Code:
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    
    
    import javax.swing.JFrame;
    
    public class Solit extends JFrame
    {
    
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = -4382011225551225106L;
    	
    	final static int OBEN=1;
    	final static int UNTEN=2;
    	final static int LINKS=3;
    	final static int RECHTS=4;
    	
    	final static int STEIN=1;
    	
    	static short [][][] loesung= new short[1][7][7];
    	static Zug [] zug=new Zug[32];
    	static int currentStep=0;
    	static boolean zeichnen=false;
    	static boolean zugzeichnen=false;
    	static long zaehler=0;
    	
    	public Solit() 
    	{
    		super(); 
            setDefaultCloseOperation(EXIT_ON_CLOSE);  
            
            for (int i=0;i<32;i++)
            {
            	zug[i]= new Zug();
            }		
    
    	}
    	
    	
    	public void paint(Graphics gs) 
    	{ // @Override ermöglicht dem Compiler die Kontrolle
    		
    	Graphics2D g=(Graphics2D)gs;
    
    	int x,y;
    	short inhalt;
    
    	if(zeichnen)
    	{
    	g.setColor(Color.lightGray);
    	g.fillRect(0, 0, getWidth(), getHeight());
    	
    	{
    	for (y=0;y<7;y++)
    		{
    		for (x=0;x<7;x++)
    			{
    			inhalt=loesung[currentStep-1][x][y];
    		
    			if (inhalt == 0)
    				{
    				g.setColor(Color.WHITE);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    				g.setColor(Color.BLACK);
    				g.drawOval(x*100+150, y*100+150, 28, 28);
    
    				}
    		
    			else if(inhalt == 1)
    				{
    				g.setColor(Color.GREEN);
    				g.fillOval(x*100+150, y*100+150, 30, 30);
    
    				}
    
    			}
    		}
    	}
    	}
    	
    	if(zugzeichnen)
    	{
    		switch (zug[currentStep-1].richtung)
    		{
    		case OBEN:
    			g.setColor(Color.WHITE);
    			g.fillOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.fillOval(zug[currentStep-1].x*100+150, (zug[currentStep-1].y-1)*100+150, 30, 30);			
    			g.setColor(Color.BLACK);
    			g.setColor(Color.lightGray);
    			g.drawOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.drawOval(zug[currentStep-1].x*100+150, (zug[currentStep-1].y-1)*100+150, 30, 30);			
    			g.setColor(Color.GREEN);
    			g.fillOval(zug[currentStep-1].x*100+150, (zug[currentStep-1].y-2)*100+150, 30, 30);			
    			break;
    			
    		case UNTEN:
    			g.setColor(Color.WHITE);
    			g.fillOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.fillOval(zug[currentStep-1].x*100+150, (zug[currentStep-1].y+1)*100+150, 30, 30);			
    			g.setColor(Color.BLACK);
    			g.drawOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.drawOval(zug[currentStep-1].x*100+150, (zug[currentStep-1].y+1)*100+150, 30, 30);			
    			g.setColor(Color.GREEN);
    			g.fillOval(zug[currentStep-1].x*100+150, (zug[currentStep-1].y+2)*100+150, 30, 30);			
    			break;
    
    		case LINKS:
    			g.setColor(Color.WHITE);
    			g.fillOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.fillOval((zug[currentStep-1].x-1)*100+150, zug[currentStep-1].y*100+150, 30, 30);			
    			g.setColor(Color.BLACK);
    			g.drawOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.drawOval((zug[currentStep-1].x-1)*100+150, zug[currentStep-1].y*100+150, 30, 30);			
    			g.setColor(Color.GREEN);
    			g.fillOval((zug[currentStep-1].x-2)*100+150, zug[currentStep-1].y*100+150, 30, 30);			
    			break;
    
    		case RECHTS:
    			g.setColor(Color.WHITE);
    			g.fillOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.fillOval((zug[currentStep-1].x+1)*100+150, zug[currentStep-1].y*100+150, 30, 30);			
    			g.setColor(Color.BLACK);
    			g.drawOval(zug[currentStep-1].x*100+150, zug[currentStep-1].y*100+150, 30, 30);
    			g.drawOval((zug[currentStep-1].x+1)*100+150, zug[currentStep-1].y*100+150, 30, 30);			
    			g.setColor(Color.GREEN);
    			g.fillOval((zug[currentStep-1].x+2)*100+150, zug[currentStep-1].y*100+150, 30, 30);			
    			break;
    			
    		default:
    
    		}
    	}
     }
    
    	
    	static boolean oben(short A[][], short x, short y)
    	{
    
    	if(y>1 && A[x][y]==1 && A[x][y-1]==1 && A[x][y-2]==0) return true;
    		
    	return false;
    	}
    
    	static boolean unten(short A[][], short x, short y)
    	{
    
    	if(y<5 && A[x][y]==1 && A[x][y+1]==1 && A[x][y+2]==0) return true;
    		
    	return false;
    	}
    
    	static boolean links(short A[][], short x, short y)
    	{
    
    	if(x>1 && A[x][y]==1 && A[x-1][y]==1 && A[x-2][y]==0) return true;
    		
    	return false;
    	}
    
    	static boolean rechts(short A[][], short x, short y)
    	{
    
    	if(x<5 && A[x][y]==1 && A[x+1][y]==1 && A[x+2][y]==0) return true;
    		
    	return false;
    	}
    
    	static void speichern(short A[][], int i)
    		{
    		for(int y=0;y<7;y++)
    			{
    			  for(int x=0;x<7;x++)
    				{
    				loesung[i][x][y]=A[x][y];
    				}
    			}
    		
    		}
    	
    	static void zug_speichern(int x, int y, int richtung, int zug)
    	{
    		Solit.zug[zug].x=x;
    		Solit.zug[zug].y=y;
    		Solit.zug[zug].richtung=richtung;
    	}
    	
    	static boolean  soli (short A[][], int i)
    	{
    	boolean inhalt;	
    	zaehler++;
    	if (i<31) 
    		{
    		i++;
    		for (short y=0;y<7;y++)
    			{
    			for (short x=0;x<7;x++)
    				{
    				if(A[x][y]==STEIN)
    					{
    					if(oben(A,x,y)) 
    						{
    						A[x][y]=0; A[x][y-1]=0; A[x][y-2]=1;
    						inhalt=soli(A,i);
    						if(inhalt) {
    							zug_speichern(x,y,OBEN,i);
    							return true;
    						}
    					else {A[x][y]=1; A[x][y-1]=1; A[x][y-2]=0;}						
    						}
    
    					if(unten(A,x,y))
    						{
    						A[x][y]=0; A[x][y+1]=0; A[x][y+2]=1;
    						inhalt=soli(A,i);
    						if(inhalt) {
    							zug_speichern(x,y,UNTEN,i);
    							return true;
    						}
    					else {A[x][y]=1; A[x][y+1]=1; A[x][y+2]=0;}
    						}
    				
    					if(links(A,x,y))
    						{
    						A[x][y]=0; A[x-1][y]=0; A[x-2][y]=1;
    						inhalt=soli(A,i);
    						if(inhalt) {
    							zug_speichern(x,y,LINKS,i);
    							return true;
    						}
    					else {A[x][y]=1; A[x-1][y]=1; A[x-2][y]=0;}
    						}
    				
    					if(rechts(A,x,y)) 
    						{
    						A[x][y]=0; A[x+1][y]=0; A[x+2][y]=1;
    						inhalt=soli(A,i);
    						if(inhalt) {
    						zug_speichern(x,y,RECHTS,i);
    						return true;
    						}
    					else {A[x][y]=1; A[x+1][y]=1; A[x+2][y]=0;}
    						}
    					}
    				}
    			}
    		i--;
    		return false;
    		}
    	else	
    		{
    		return true;
    		}
    
    	}
    
    	public static void main(String[] args)
    	{
    		Solit f= new Solit();	
    		f.setSize(1000, 1000);
    		f.setVisible(true);
    
    		
    		short [][] A = new short [][]{
                { 9,9,1,1,1,9,9 },
                { 9,9,1,1,1,9,9 },
                { 1,1,1,1,1,1,1 },
                { 1,1,1,0,1,1,1 },
                { 1,1,1,1,1,1,1 },
                { 9,9,1,1,1,9,9 },
                { 9,9,1,1,1,9,9 }		
            };	
    
    
    			speichern(A,0);
    
    	Zeitmesser.startZeitmessung(1);
    	soli(A,0);
    	
    	System.out.println(Zeitmesser.getZeitmessung(1)/1000.0);
    	Zeitmesser.stopZeitmessung(1);
    	System.out.println();
    	System.out.println(zaehler);
    
    
    	zeichnen=true;
    		currentStep++;
    		f.repaint();
    		try {
    			Thread.sleep(2000);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	zeichnen=false;	
    	
    	zugzeichnen=true;
    	for (int i=1;i<32;i++)
    	{
    		currentStep++;
    		f.repaint();
    		try {
    			Thread.sleep(2000);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    	
    	
    class Zug
    	{
    int x,y;
    int richtung;
    
    public Zug()
    	{
    	x=0;
    	y=0;
    	richtung=0;
    	}
    
    
    	
    	}
    
    }
    Geändert von Sergej Petrow (30.12.2016 um 18:24 Uhr)

Seite 1 von 2 12 Letzte »

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •