GUI pathfinder change location of start + end 'tiles'

I’m making an A* pathfinding application with a GUI. I have:

  • an enum TileType
START(Color.GREEN), WALL(Color.BLACK), BLANK(new Color(240, 240, 240)), END(Color.RED);
  • a Grid class
public class Grid extends JPanel {

private final Color lineColour = new Color(200, 200, 200);
private Color defaultColour;
private final int pixelsPerTile;
private final int rows;
private final int columns;
private TileType[][] tiles;

public Grid(int rows, int columns, int pixelsPerTile) {
    this.pixelsPerTile = pixelsPerTile;
    this.rows = rows;
    this.columns = columns;
    this.tiles = new TileType[rows][columns];
    this.setPreferredSize(new Dimension(rows * pixelsPerTile, columns * pixelsPerTile));
    setTile(rows / 2 - 5, columns / 2, TileType.START);
            setTile(rows / 2 + 5, columns / 2, TileType.END);

}

public void resetBoard() {
    for (int i = 0; i < tiles.length; i++) {
        for (int j = 0; j < tiles[0].length; j++) {
            if (getTile(i, j) != TileType.START && getTile(i, j) != TileType.END) {
                tiles[i][j] = null;
            }
        }
    }
}

public void removeTile(int x, int y) {
    tiles[x][y] = TileType.BLANK;
}

public TileType getTile(int x, int y) {
    return tiles[x][y];
}

public Point getTile(boolean start) {
    for (int x = 0; x < tiles.length; x++) {
        for (int y = 0; y < tiles[0].length; y++) {
            if (tiles[x][y] == (start ? TileType.START : TileType.END)) {
                return new Point(x, y);
            }
        }
    }
    return null;
}

public void setTile(int x, int y, TileType tile) {
    if (getTile(x, y) != TileType.START && getTile(x, y) != TileType.END) {
        tiles[x][y] = tile;
    }
}

@Override
public void paint(Graphics g1) {
    Graphics2D g = (Graphics2D) g1;
    for (int x = 0; x < columns; x++) {
        for (int y = 0; y < columns; y++) {
            if (getTile(x, y) != null) {
                g.setColor(getTile(x, y).getColour());
                g.fillRect(x * pixelsPerTile, y * pixelsPerTile, pixelsPerTile, pixelsPerTile);
            }
        }
    }
    // have the grid appear on top of blank tiles
    g.setColor(lineColour);
    for (int x = 0; x < columns; x++) {
        for (int y = 0; y < rows; y++) {
            g.drawLine(x * pixelsPerTile, 0, x * pixelsPerTile, getHeight());
            g.drawLine(0, y * pixelsPerTile, getWidth(), y * pixelsPerTile);
        }
    }
}

public int getPixelsPerTile() {
    return pixelsPerTile;
}

public int getRows() {
    return rows;
}

public int getColumns() {
    return columns;
}
}

  • a Frame class
public class Frame extends JFrame {

private Grid grid;

public Frame() {
    grid = new Grid(33, 33, 15); // odd so there is a definitive middle point
    this.setAutoRequestFocus(true);
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    this.setTitle("A* Path finder");
    this.setBounds(new Rectangle((grid.getRows()) * grid.getPixelsPerTile(),
            (grid.getColumns() + 2) * grid.getPixelsPerTile()));
    this.setResizable(true);
    this.add(grid);
    this.setVisible(true);
    this.getContentPane().addMouseListener(new MouseLsntr()); // fixes alignment problems
    ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(5);
    se.scheduleAtFixedRate(new RedrawGrid(), 0L, 20L, TimeUnit.MILLISECONDS);
}

private class RedrawGrid implements Runnable {

    @Override
    public void run() {
        grid.repaint();
    }
}

private class MouseLsntr implements MouseListener {

    @Override
    public void mouseClicked(MouseEvent me) {
        int x = me.getX() / grid.getPixelsPerTile();
        int y = me.getY() / grid.getPixelsPerTile();
        switch (me.getButton()) {
            case MouseEvent.BUTTON1:
                if (grid.getTile(x, y) != TileType.WALL) {
                    grid.setTile(x, y, TileType.WALL);
                    System.out.println(String.format("(%d, %d) (%d, %d) wall", x, y, x, y));
                } else {
                    grid.removeTile(x, y);
                    System.out.println(String.format("(%d, %d) (%d, %d) blank", x, y, x, y));
                }
                break;
        }
    }

    @Override
    public void mousePressed(MouseEvent me) {
    }

    @Override
    public void mouseReleased(MouseEvent me) {
    }

    @Override
    public void mouseEntered(MouseEvent me) {
    }

    @Override
    public void mouseExited(MouseEvent me) {
    }        
}
}
  • and obviously a main class which calls Frame()

When the user left clicks on a grid, they make a WALL at that location. If it’s already a WALL, it becomes BLANK. I want the user to be able to move the START and END tile by clicking on it and then dragging to the location they want to stop at, which I’m having trouble doing. Any help would be appreciated since I’ve been stumped about this for a while now :L

On mouse press calculate the tile {x1,y1}, and on mouse release calculate it again {x2, y2}. If it’s different, set the start to {x1,y1} and the end to {x2,y2}.

If you’re talking also about implementing A*, here’s a fun tutorial:

http://wiki.gamegardens.com/Path_Finding_Tutorial

And here’s a JS interactive webpage with A* and a few others:

http://qiao.github.io/PathFinding.js/visual/

Have fun!