# Schiebepuzzle Array Zufallszahlen Problem



## killer3d (13. Apr 2011)

Guten Tag,

ich möchte ein Schiebepuzzle Programmieren.

Ich benötige ein Array mit Zufallszahlen wobei jeder Arrayeintrag nur einmal vorhanden sein soll

Zufallszahl: 1-15
array = [11] [4] [6] [14] [9] [2] [1] usw

ich habe bis jetzt folgenden Code:


```
java.util.Random zufall = new java.util.Random();
		int[] genZahlen = new int[16];
		for (int z = 0; z<=15; z++) {
			int zZahl = zufall.nextInt(15)+1;
			
			if (Arrays.asList(genZahlen).contains(zZahl) == false) {
				genZahlen[z] = zZahl;
				
            }
			System.out.println(genZahlen[z]);
		}
```

Leider werden manche Zahlen immernoch Doppelt in das Array eingetragen.

Könnt ihr mir helfen ?

Mit freundlichen Grüßen
Dennis


----------



## JensArpe (13. Apr 2011)

Das liegt daran, daß die Methode contains als Parameter nen Object hat, deine Daten aber Integer sind.


```
java.util.Random zufall = new java.util.Random();
        Object[] genZahlen = new Object[16];        
        for (int z = 0; z<=15; z++) {
            int zZahl = zufall.nextInt(15)+1;
            
            if (Arrays.asList(genZahlen).contains(zZahl) == false) {           	
                genZahlen[z] = zZahl;                 
                
            }
            System.out.println(genZahlen[z]);
        }
```

so klappts z.B. aber es beleiben halt manche Felder leer. Was aber wohl so sein soll!?


----------



## Peter W. Marth (14. Apr 2011)

Hallo,

es sollen vermutlich alle Zahlen von 1 - 15 in zufälliger Reihenfolge erzeugt werden, z.B. so:

```
import java.util.LinkedList;
import java.util.Random;

public class Puzzle {

    /**
     * @param args
     */
    public static void main( String[] args ) {
        LinkedList<Integer> list = new LinkedList<Integer>();
        Random rand = new Random();
        while( list.size() < 15 ) {
            Integer i = rand.nextInt( 15 ) + 1;
            if( !list.contains( i ) ) {
                list.add( i );
            }
        }
        for( Integer i : list.toArray( new Integer[] {} ) ) {
            System.out.println( "i=" + i );
        }
    }

}
```


----------



## Landei (14. Apr 2011)

Viel zu umständlich!


```
List<Integer> list = new ArrayList<Integer>();
for(int i = 1; i <= 15; i++) list.add(i);
java.util.Collections.shuffle(list);
//mit Liste weiterarbeiten oder in Array "umfüllen"
```


----------



## killer3d (19. Apr 2011)

Vielen Dank für die Lösungen... ich habe es nun endlich hinbekommen.


```
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Random;

//Grid layout 4*4

public class Prak2 {
	JButton[][] knopf = new JButton[4][4];
	
	public Prak2() {
		JFrame frm = new JFrame("Schiebepuzzle");
		Panel pane = new Panel();
		pane.setLayout(new GridLayout(4, 4));
		
		LinkedList<Integer> list = new LinkedList<Integer>();
        Random rand = new Random();
        while( list.size() < 16 ) {
            Integer i = rand.nextInt( 16 ) + 1;
            if( !list.contains( i ) ) {
                list.add( i );
            }
        }  
        Integer genZahlen[] = list.toArray( new Integer[] {} );
        
		int durchlauf = 0;
		for (int j = 0; j<=3; j++) {
			for (int i = 0; i<=3; i++) {
				durchlauf+=1;
				if (durchlauf != 16) {
					knopf[j][i] = new JButton("" + genZahlen[durchlauf-1]);
					knopf[j][i].addActionListener(new Pressed());
					pane.add(knopf[j][i]);
				}
			}
		}
		
		
		frm.add(pane);
		frm.setVisible(true);
	}
	
	private class Pressed implements ActionListener {
		public void actionPerformed(ActionEvent ae) {
			System.out.println(ae.getActionCommand());
		}		
	}
	
	public static void main(String[] args) {
		new Prak2();
	}
	
}
```

Gibt es jetzt noch die Möglichkeit eine Komponennte im Gridlayout zu ersetzen ?


----------



## Peter W. Marth (20. Apr 2011)

Hallo,

eine Möglichkeit wäre, sich die Buttons zusätzlich in einem 4x4-Array zu merken und dann einfach nur bei Bedarf mit setText() ihre Beschriftung zu ändern. Damit müssen keine Components im GridLayout ausgetauscht werden.


----------



## L-ectron-X (20. Apr 2011)

Eines meiner ersten AWT-Applets, die ich mal geschrieben habe, war so ein Schiebefax mit ganz normalen Buttons. 
Der Code ist ziemlich alt. Es ist nicht schön und nicht perfekt, aber es macht das, wofür es geschrieben wurde.
Ich habs mal rausgekramt und hier mal unverändert abgebildet.

```
import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class JPuzzleApplet extends Applet implements ActionListener {
   private Panel numbersPanel, functionPanel;
   private Label l_moves, l_empty;
   private Font buttonFont;
   private Button[][] buttons;
   private Button b_toMix, b_toReset;
   private int numberOfButtons;
   private int size = 4;
   private int movesCounter;

   public void init() {
      numberOfButtons = size * size;

      this.setLayout(new BorderLayout());

      buttonFont = new Font("Arial", 0, 30);

      numbersPanel = new Panel();
      numbersPanel.setLayout(new GridLayout(size, size));
      numbersPanel.setBackground(Color.lightGray);

      l_moves = new Label();
      l_moves.setAlignment(Label.CENTER);
      l_moves.setForeground(Color.white);
      l_empty = new Label();

      initNumberButtons();

      b_toMix = new Button("Mischen");
      b_toMix.addActionListener(this);
      b_toReset = new Button("Sortieren");
      b_toReset.addActionListener(this);
      functionPanel = new Panel();
      functionPanel.setLayout(new GridLayout(1, 4));
      functionPanel.setBackground(Color.gray);
      functionPanel.add(l_moves);
      functionPanel.add(b_toMix);
      functionPanel.add(b_toReset);
      functionPanel.add(l_empty);

      this.add(numbersPanel, BorderLayout.CENTER);
      this.add(functionPanel, BorderLayout.SOUTH);

      System.out.println("JPuzzle-Applet von L-ectron-X");
   }

   public void actionPerformed(ActionEvent e) {
      Object obj = e.getSource();

      if(obj == b_toMix)
         mixNumberButtons();

      else if(obj == b_toReset)
         initNumberButtons();

      else
         moveNumberButton(e);
   }

   private void mixNumberButtons() {
      Button b1, b2;
      int[] r = new int[4]; //Zufallszahlen (Koordinaten für 2 Buttons)

      for(int i = 0; i < numberOfButtons; i++) { //Durchläufe

         for(int j = 0; j < r.length; j++) { //Zufallszahlen
            //Zufallszahlen ermitteln
            r[j] = (int) (Math.random() * size);
         }

         //Zufalls-Buttons ermitteln
         b1 = buttons[r[0]][r[1]];
         b2 = buttons[r[2]][r[3]];

         //Plätze der Buttons vertauschen
         buttons[r[2]][r[3]] = b1;
         buttons[r[0]][r[1]] = b2;
      }

      drawButtons();

      movesCounter = 0;
      setMovesCounter();
   }

   private void initNumberButtons() {
      Button[][] b = new Button[size][size];
      int z = 1;

      for(int i = 0; i < size; i++) {

         for(int j = 0; j < size; j++) {
            b[i][j] = new Button(String.valueOf(z));
            b[i][j].addActionListener(this);
            b[i][j].setFont(buttonFont);
            z += 1;
         }
      }

      buttons = b;

      //letzten Button unsichtbar machen
      buttons[size-1][size-1].setVisible(false);
      drawButtons();

      movesCounter = 0;
      setMovesCounter();
   }

   private void moveNumberButton(ActionEvent e) {
      Button b = (Button)e.getSource();
      String label = b.getLabel();
      //Koordinaten von Buttons im zweidimensionalen Array
      int xb1 = 0, yb1 = 0, xb2 = 0, yb2 = 0; //b1 = geklickter Button, b2 = unsichtbarer Button

      //Postition des geklickten Buttons im zweidimensionalen Array ermitteln
      for(int i = 0; i < size; i++) {
         for(int j = 0; j < size; j++) {

            //Koordinaten des geklickten Buttons speichern
            if(buttons[i][j].getLabel().equals(label)) {
               xb1 = i;
               yb1 = j;
            }

            //Koordinaten des unsichtbaren Buttons
            if(buttons[i][j].getLabel().equals(String.valueOf(numberOfButtons))) {
               xb2 = i;
               yb2 = j;
            }
         }
      }

      //  links neben dem Button          rechts neben dem Button
      if((xb2 == xb1-1 && yb2 == yb1) || (xb2 == xb1+1 && yb2 == yb1) ||
      //  über dem Button                   unter dem Button
         (yb2 == yb1-1 && xb2 == xb1) || (yb2 == yb1+1 && xb2 == xb1)) {

         Button bt1 = buttons[xb1][yb1];
         Button bt2 = buttons[xb2][yb2];
         buttons[xb2][yb2] = bt1;
         buttons[xb1][yb1] = bt2;
         drawButtons();
      }
   }

   private void drawButtons() {
      numbersPanel.removeAll();

      for(int i = 0; i < size; i++) {
         for(int j = 0; j < size; j++) {
            numbersPanel.add(buttons[i][j]);
         }
      }

      validate();
      setMovesCounter();
   }

   private void setMovesCounter() {
      l_moves.setText("Züge: "+Integer.toString(movesCounter++));
   }
}
```


----------



## AlexSpritze (20. Apr 2011)

Nicht jedes beliebig durcheinander gemischte Schiebepuzzel ist aber lösbar. Hatte mein Prof. damals in Lineare Algebra bewiesen... bzw. lässt sich mathematisch beweisen


----------



## Quaxli (20. Apr 2011)

Aber das läßt sich ja ganz einfach umgehen:
1. geordnetes Schiebepuzzle erstellen
2. mit x Zügen durcheinander bringen


----------

