/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* @author Yannick
*/
package a.star.special;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.util.Random;
import java.util.Vector;
public class AStarSpecial
{
static private Random r = new Random();
// Die Map
static private Map map = new Map(20, 18);
static private Vector<Line> lines = new Vector<Line>();
// Fenster erstellen
static private JFrame frame = new JFrame("A-Star-Special");
static private Vector<Open> offen = new Vector<Open>();
static private Vector<Closed> gesch = new Vector<Closed>();
static private Vector<Coord> hindernisse = new Vector<Coord>();
public static void main(String args[])
{
int wall;
for(int i = 0; i < map.get_x_size(); i++)
{
for(int j = 0; j < map.get_y_size(); j++)
{
wall = (r.nextInt(3) == 0)? 1 : 0;
map.set(i, j, wall);
if(wall != 0)
{
hindernisse.add(new Coord(i, j));
}
}
}
Coord start = new Coord(r.nextInt(map.get_x_size()), r.nextInt(map.get_y_size()));
Coord ziel = new Coord(r.nextInt(map.get_x_size()), r.nextInt(map.get_y_size()));
start = new Coord(0, 0); //Manuelle Festlegung
ziel = new Coord(map.get_x_size() - 1, map.get_y_size() - 1);
map.set(start.x, start.y, 2); // Start
map.set(ziel.x, ziel.y, 3); // Ziel
hindernisse.remove(start);
hindernisse.remove(ziel);
// Das Erzeugen des GUIs muss auf dem
// Event-Dispatch-Thread ausgeführt
// werden:
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
Coord cur_pos = start;
offen.add(new Open(start, start, 0.0, ziel));
int size, j;
Open best, cur;
Closed geschlossen;
do
{
try
{
Thread.sleep(3000);
}
catch (InterruptedException e)
{
}
size = offen.size();
j = 0;
best = offen.get(0);
for(int i = 1; i < size; i++)
{
cur = offen.get(i);
if(cur.calc_way() < best.calc_way())
{
best = cur;
j = i;
}
if((cur.pos.x == ziel.x) && (cur.pos.y == ziel.y))
{
best = cur;
j = i;
break;
}
}
geschlossen = offen.remove(j).toClosed();
gesch.add(geschlossen);
removeLineAt(geschlossen.pos);
lines.add(new Line(
new Color(0, 128, 0),
geschlossen.from.x, geschlossen.from.y, geschlossen.pos.x, geschlossen.pos.y, true
));
cur_pos = geschlossen.pos;
if(map.read(cur_pos) == 4)
{
map.set(cur_pos, 5);
}
if(map.read(cur_pos) == 3)
{
update(1);
size = 1;
break;
}
for(int i = 0; i < map.get_x_size(); i++)
{
for(j = 0; j < map.get_y_size(); j++)
{
int x = i;
int y = j;
Coord pos = new Coord(x, y);
if(checkForWall(cur_pos, pos))
{
int tmp = map.read(x, y);
if((0 == tmp) || (3 == tmp))
{
offen.add(new Open(pos, cur_pos, geschlossen.calc_way(), ziel));
lines.add(new Line(
new Color(128, 255, 128),
cur_pos.x, cur_pos.y, pos.x, pos.y, true
));
if(tmp == 0)
{
map.set(pos, 4);
}
}
if(tmp == 4)
{
Open alt = findAtPos(pos);
Open neu = new Open(pos, cur_pos, geschlossen.calc_way(), ziel);
if(neu.calc_way() < alt.calc_way())
{
offen.remove(alt);
removeLineAt(pos);
offen.add(neu);
lines.add(new Line(
new Color(128, 255, 128),
cur_pos.x, cur_pos.y, pos.x, pos.y, true
));
}
}
}
}
}
size = offen.size();
update();
} while((map.read(cur_pos) != 3) && (size != 0));
if(size == 0)
{
update(-1);
}
else
{
Closed ob = gesch.lastElement();
Vector<Closed> way = new Vector<Closed>();
while(!((ob.pos.x == start.x) && (ob.pos.y == start.y)))
{
way.add(ob);
lines.add(new Line(
new Color(255, 20, 20),
ob.pos.x, ob.pos.y, ob.from.x, ob.from.y, false));
ob = findClosedAtPos(ob.from);
update(1);
try
{
Thread.sleep(300);
}
catch (InterruptedException e)
{
}
}
}
}
// Erzeugt ein Fenster, das ein PaintPanel enthält,
// und macht das Fenster sichtbar
private static void createAndShowGUI()
{
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// PaintPanel erstellen und in das Fenster legen
PaintPanel paintPanel = new PaintPanel(map, lines, offen, gesch, 0);
paintPanel.setPreferredSize(new Dimension(map.get_x_size() * 52 + 200 + 2, map.get_y_size() * 52 + 2));
frame.getContentPane().add(paintPanel);
// Fenster zentrieren und anzeigen
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
/**
* Aktualisiert das Fenster
*/
private static void update(int i)
{
// PaintPanel erstellen und in das Fenster legen
PaintPanel paintPanel = new PaintPanel(map, lines, offen, gesch, i);
paintPanel.setPreferredSize(new Dimension(map.get_x_size() * 52, map.get_y_size() * 52));
frame.getContentPane().add(paintPanel);
// Fenster zentrieren und anzeigen
frame.setVisible(true);
}
private static void update()
{
update(0);
}
private static Open findAtPos(Coord pos)
{
int size = offen.size();
for(int i = 0; i < size; i++)
{
Coord pos_offen = offen.get(i).pos;
if((pos_offen.x == pos.x) && (pos_offen.y == pos.y))
{
return offen.get(i);
}
}
return null;
}
private static Closed findClosedAtPos(Coord pos)
{
int size = gesch.size();
for(int i = 0; i < size; i++)
{
Coord pos_gesch = gesch.get(i).pos;
if((pos_gesch.x == pos.x) && (pos_gesch.y == pos.y))
{
return gesch.get(i);
}
}
return null;
}
private static void removeLineAt(Coord pos)
{
int size = lines.size();
for(int i = 0; i < size; i++)
{
Line line = lines.get(i);
if((line.finish_x == pos.x) && (line.finish_y == pos.y))
{
lines.remove(line);
return;
}
}
}
private static boolean checkForWall(Coord pos1, Coord pos2)
{
int size = hindernisse.size();
for(int i = 0; i < size; i++)
{
Coord cur = hindernisse.get(i);
double distance = dist(pos1, pos2, cur);
if((distance < 1) && inRange(pos1, pos2, cur, distance))
{
return false;
}
}
return true;
}
private static double modulu(double divident, double divisor)
{
return divident - (divisor * ((double)((int)(divident / divisor))));
}
private static double dist(Coord P, Coord Q, Coord X)
{
double l = X.distance(P);
double alpha;
Coord x = new Coord(X.x - P.x, X.y - P.y);
Coord q = new Coord(Q.x - P.x, Q.y - P.y);
alpha = Math.acos(((x.x * q.x) + (x.y * q.y)) / (x.distance() * q.distance()));
return l * Math.sin(alpha);
}
private static boolean inRange(Coord P, Coord Q, Coord X, double dist)
{
double dist_1 = P.distance(Q);
double dist_2 = P.distance(X);
double dist_3 = X.distance(Q);
dist_2 *= dist_2; //Quadrieren
dist_3 *= dist_3;
dist *= dist;
return dist_1 == (Math.sqrt(dist_2 - dist) + Math.sqrt(dist_3 - dist));
}
}