I\'m trying to build an A* solver for a 15-square puzzle.
The goal is to re-arrange the tiles so that they appear in their natural positions. You can only sli
What I learned
check this
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.Object;
class Puzzle extends JPanel implements ActionListener
{
JButton[] b = new JButton[16];
Puzzle()
{
b[0] = new JButton("4");
b[1] = new JButton("11");
b[2] = new JButton("5");
b[3] = new JButton("9");
b[4] = new JButton("1");
b[5] = new JButton("10");
b[6] = new JButton("12");
b[7] = new JButton("13");
b[8] = new JButton("15");
b[9] = new JButton("14");
b[10] = new JButton("3");
b[11] = new JButton("2");
b[12] = new JButton("7");
b[13] = new JButton("8");
b[14] = new JButton("6");
b[15] = new JButton("");
GridLayout grid = new GridLayout(4,4);
setLayout(grid);
for(int i=0;i<16;i++)
add(b[i]);
for(int i=0;i<16;i++)
b[i].addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
/*if(e.getSource()==b[11])
{
if(b[15].getText()=="")
{
b[15].setText("");
}
}
else if(e.getSource()==b[3])
{
if(b[2].getText()=="")
{
b[2].setText("");
}
}*/
for(int i=0;i<16;i++)
{
System.out.println(e.getSource());
if(e.getSource()==b[i])
{
if(i==5 || i==6 || i==9 || i==10)
{
if(b[i-1].getText()=="")
{
b[i-1].setText(b[i].getText());
b[i].setText("");
}
else if(b[i+1].getText()=="")
{
b[i+1].setText(b[i].getText());
b[i].setText("");
}
else if(b[i-4].getText()=="")
{
b[i-4].setText(b[i].getText());
b[i].setText("");
}
else if(b[i+4].getText()=="")
{
b[i+4].setText(b[i].getText());
b[i].setText("");
}
}
else if(i==4 || i==8)
{
if(b[i+1].getText()=="")
{
b[i+1].setText(b[i].getText());
b[i].setText("");
}
else if(b[i-4].getText()=="")
{
b[i-4].setText(b[i].getText());
b[i].setText("");
}
else if(b[i+4].getText()=="")
{
b[i+4].setText(b[i].getText());
b[i].setText("");
}
}
else if(i==7 || i==11)
{
if(b[i-1].getText()=="")
{
b[i-1].setText(b[i].getText());
b[i].setText("");
}
else if(b[i-4].getText()=="")
{
b[i-4].setText(b[i].getText());
b[i].setText("");
}
else if(b[i+4].getText()=="")
{
b[i+4].setText(b[i].getText());
b[i].setText("");
}
}
if(i==0)
{
if(b[i+1].getText()=="")
{
b[i+1].setText(b[i].getText());
b[i].setText("");
}
else if(b[i+4].getText()=="")
{
b[i+4].setText(b[i].getText());
b[i].setText("");
}
}
if(i==3)
{
if(b[i-1].getText()=="")
{
b[i-1].setText(b[i].getText());
b[i].setText("");
}
else if(b[i+4].getText()=="")
{
b[i+4].setText(b[i].getText());
b[i].setText("");
}
}
if(i==15)
{
if(b[i-1].getText()=="")
{
b[i-1].setText(b[i].getText());
b[i].setText("");
}
else if(b[i-4].getText()=="")
{
b[i-4].setText(b[i].getText());
b[i].setText("");
}
else if(b[i+4].getText()=="")
{
b[i+4].setText(b[i].getText());
b[i].setText("");
}
}
if(i==12)
{
if(b[i+1].getText()=="")
{
b[i+1].setText(b[i].getText());
b[i].setText("");
}
else if(b[i-4].getText()=="")
{
b[i-4].setText(b[i].getText());
b[i].setText("");
}
}
if(i==1 || i==2)
{
if(b[i+1].getText()=="")
{
b[i+1].setText(b[i].getText());
b[i].setText("");
}
else if(b[i-1].getText()=="")
{
b[i-1].setText(b[i].getText());
b[i].setText("");
}
else if(b[i+4].getText()=="")
{
b[i+4].setText(b[i].getText());
b[i].setText("");
}
}
if(i==13 || i==14)
{
if(b[i+1].getText()=="")
{
b[i+1].setText(b[i].getText());
b[i].setText("");
}
else if(b[i-1].getText()=="")
{
b[i-1].setText(b[i].getText());
b[i].setText("");
}
else if(b[i-4].getText()=="")
{
b[i-4].setText(b[i].getText());
b[i].setText("");
}
}
}
}
//System.out.println(e.getActionCommand());
}
public static void main(String[] args)
{
JFrame frame = new JFrame("15-Puzzle");
//frame.setContentPane(panel);
JComponent newContentPane = new Puzzle();
//newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//panel.add(button);
frame.setSize(400,400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I have programmed such an algorithm once (windowsApp) and I have the following experience
1) it is most fun to see the robot in action if it uses an (near) optimal solution. (For the human observer it is impossible to understand how the robot "thinks" and the transaction from chaos to order is sudden)
2) if you like to find the optimal solution your h() function must underestimate true distance. If you overestimate it you will not find the optimum.
3) The potential state-space is huge, 15!/2 (10^12). If you use a bad heuristic function your data sets will grow far beyond the size of your main-memory and every data access will require multiple disc-accesses. If this happens the execution time will be "infinite".
Maybe it will converge quicker if you shoot for intermediate goals first. For instance, only score the top and right rows. It shouldn't take very long to get those rows in place, then you can solve the remaining 3x3.
Use IDA* instead of A*. You need much less memory. As a heuristics, the "Walking distance" developed by Ken'ichiro Takahashi is much more effective, though using only 25 kB of memory.
Here and here is English translation.
Yes, that's how I've heard of this problem being done. g(x) is the number of tile slides that have taken place, and h(x) is the total distance that all tiles are from their required squares. I hadn't seen anything used but this approach (the Manhattan heuristic) before today, but just found this so-called diagonal shortcut -- you might want to check it out.