I recently created this for a coursework assignment. I am always looking to learn and would like some feedback on my code. Is there any OO principles I'm going against or anything irritating I'm doing?Search Class: import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Map; /** * Represents the A* algorithm * * @author Paymon Sattarzadeh * @date 27/11/2014 * @time 16:19 */ public class Search {/** * Active instance of <code>Board</code> */private Board board;/** * Active instance of <code>Board</code> representing the goal state */private Board goalBoard;/** * g value */private int g = 0;/** * Is the search complete */private boolean searchComplete = false;/** * f values for the set of nodes currently being considered */ArrayList<Integer> nodeFValues = new ArrayList();/** * Tiles for the set of nodes currently being considered */ArrayList<Tile> nodeTiles = new ArrayList<>();/** * The last move */private int lastMove = 0;/** * Construct the <code>Search</code> instance * * @param board *      The board */public Search(Board board, Board goalBoard){    this.board = board;    this.goalBoard = goalBoard;    searchAlgo();}/** * Main search algorithm */private void searchAlgo() {    /* If there are no tiles out of place then you are at goal state */    if (tilesOutOfPlaceHeuristic(board) == 0) {        System.out.println(Complete);        board.print();        searchComplete = true;        return;    }    /* Checks if the puzzle is solvable */    if (isSolvable())        nodeManager();    else {        System.out.println(This puzzle is not solvable);        return;    }    ArrayList<Tile> listt = new ArrayList();    /* Adds all the tiles with equal f values to the listt arraylist */    for (int value : nodeFValues) {        if (value == Collections.min(nodeFValues))            listt.add(nodeTiles.get(nodeFValues.indexOf(value)));    }    /*    * If there are nodes with the same f value as the min,    * clear the nodeFValues list and get new f value(with complement of h2)    */    if (listt.size() > 1) {        nodeFValues.clear();        nodeTiles.clear();        for (Tile tile : listt) {            nodeFValues.add(node(tile, true));            nodeTiles.add(tile);        }    }    /* Gets the minimum fringe */    int minFValueIndex = nodeFValues.indexOf(Collections.min(nodeFValues));    /* Goes to the node with the lowest f value. */    board.moveTile(board.findTile(0),            nodeTiles.get(minFValueIndex).getXPosition(),            nodeTiles.get(minFValueIndex).getYPosition());    lastMove = nodeTiles.get(minFValueIndex).getNumber();    g += 1;    /* Clears the data from the previous node */    nodeFValues.clear();    nodeTiles.clear();    /* If search is incomplete, it recursively calls itself */    if (!searchComplete)        searchAlgo();}/** * Manages the nodes and adds the values/tiles to the respective list */private void nodeManager(){    /* Stores all the f values for the nodes in the fringe */    for(Tile tile: board.checkNeighbouringTiles(board.findTile(0))){        if(lastMove != tile.getNumber()) {            nodeFValues.add(node(tile, false));            nodeTiles.add(tile);            node(tile, false);        }    }}/** * Represents each node * * @param tile *      The tile to be moved in the node * @param useSecondHeuristic *      flag to consider whether to use the 2nd heuristic * @return *      f value */private int node(Tile tile, Boolean useSecondHeuristic){    /** Initialises new board object */    Board nodeBoard = new Board(board.getTiles());    nodeBoard.moveTile(nodeBoard.findTile(0), tile.getXPosition(), tile.getYPosition());    int h1 = tilesOutOfPlaceHeuristic(nodeBoard);    int h2 = manhattanHeuristic(nodeBoard);    int f;    if(!useSecondHeuristic)        f = g + h1;    else        f = g + h1 + h2;    return f;}/** * Calculates horizontal and vertical distances of tiles from their proper places. * Admissible Heuristic. * * @param board *      The board that needs reviewing * @return *      Sum of horizontal and vertical distances of tiles from their proper places. */public int manhattanHeuristic(Board board) {    int sum = 0;    ArrayList<Tile> tiles = board.getTiles();    Tile goalState;    int goalX;    int goalY;    int differenceX;    int differenceY;    for(Tile tile: tiles){        if(tile.getNumber() != 0) {            goalState = goalBoard.findTile(tile.getNumber());            goalX = goalState.getXPosition();            goalY = goalState.getYPosition();            differenceX = goalX - tile.getXPosition();            differenceY = goalY - tile.getYPosition();            sum += Math.abs(differenceX) + Math.abs(differenceY);        }    }    return sum;}/** * Calculates number of tiles out of place. Admissible Heuristic. * * @param board *      The board that needs reviewing * @return *      Number of tiles out of place */public int tilesOutOfPlaceHeuristic(Board board) {    int tilesInWrongPlace = 0;    ArrayList<Tile> tiles = board.getTiles();    for(Tile tile: tiles){        if(tile.getNumber() != 0) {            if ((tile.getXPosition() != goalBoard.findTile(tile.getNumber()).getXPosition())                    || (tile.getYPosition() != goalBoard.findTile(tile.getNumber()).getYPosition())){                tilesInWrongPlace += 1;            }        }    }    return tilesInWrongPlace;}/** * Checks if the board is solvable. * * @return *      is solvable? */private boolean isSolvable() {    int numberOfInversions = 0;    for(Tile i: board.getTiles()) {        for (Tile j : board.getTiles()) {            /* If the tile j is after(has a greater index) then tile i. */            if (board.getTiles().indexOf(i) < board.getTiles().indexOf(j)) {                if (i.getNumber() != 0 && j.getNumber() != 0) {                    /* If j's number is lower then i's */                    if (i.getNumber() > j.getNumber())                        numberOfInversions += 1;                }            }        }    }    /* If the grid width is odd, then the number of inversions in a solvable situation is even.*/    if((Main.COLUMNS % 2 == 1) && (numberOfInversions % 2 == 1))        return false;    /* If the grid width is even, and the blank is on an even row counting from the bottom (second-last, fourth-last etc),       then the number of inversions in a solvable situation is odd.*/    if(((Main.COLUMNS % 2 == 0) && (board.findTile(0).getYPosition() % 2 == 0))            && (numberOfInversions % 2 == 1))        return false;    /* If the grid width is even, and the blank is on an odd row counting from the bottom (last, third-last, fifth-last etc)       then the number of inversions in a solvable situation is even. */    if(((Main.COLUMNS % 2 == 0) && (board.findTile(0).getYPosition() % 2 == 1))            && (numberOfInversions % 2 == 0))        return false;    return true;}}Board Class: import java.util.ArrayList; /** * The board where the game is played. * * @author Paymon Sattarzadeh * @date 27/11/2014 * @time 12:20 */ public class Board {/** * The board */private ArrayList<Tile> board;/** * Constructs a <code>Board</code> instance and fills * it with <code>Tile</code> instances */public Board(ArrayList<Tile> tiles) {   this.board = tiles;}/** * @return *      Tiles in board */public ArrayList<Tile> getTiles(){    return board;}/** * Moves the specified <code>Tile</code> to the specified position. * Swaps positions with <code>Tile</code> at that position. * * @param tile *      <code>Tile</code> to be moved * @param x *      The horizontal position you want <code>Tile</code> to move to. * @param y *      The vertical position you want <code>Tile</code> to move to. */public void moveTile(Tile tile, int x, int y) {    int _x = tile.getXPosition();    int _y = tile.getYPosition();    Tile tileToBeMoved = board.get(board.indexOf(tile));    Tile tileAtPosition;    if(findTile(x, y) != null) {        tileAtPosition = findTile(x, y);    } else {        System.out.println(No tile exists at that position);        return;    }    /* Move tileToBeMoved to chosen position */    tileToBeMoved.setPosition(x, y);    /* swap*/    tileAtPosition.setPosition(_x, _y);}/** * Checks if neighbouring <code>Tile</code>s exist, if so, it returns the <code>Tile</code> * * @param tile *      Current <code>Tile</code> * @return *      Set of <code>Tile</code>s */public ArrayList<Tile> checkNeighbouringTiles(Tile tile){    ArrayList<Tile> neighbouringTiles = new ArrayList<>();    int x = tile.getXPosition();    int y = tile.getYPosition();    /* Neighbour to the right of tile */    int rightNeighbourX = x + 1;    int rightNeighbourY = y;    /* Neighbour to the left of tile */    int leftNeighbourX = x - 1;    int leftNeighbourY = y;    /* Neighbour to the top of tile */    int topNeighbourX = x;    int topNeighbourY = y - 1;    /* Neighbour to the bottom of tile */    int bottomNeighbourX = x;    int bottomNeighbourY = y + 1;    for(Tile t: board) {        if ((t.getXPosition() == rightNeighbourX) && (t.getYPosition() == rightNeighbourY)) {            neighbouringTiles.add(t);        } else if((t.getXPosition() == leftNeighbourX) && (t.getYPosition() == leftNeighbourY)){            neighbouringTiles.add(t);        } else if((t.getXPosition() == topNeighbourX) && (t.getYPosition() == topNeighbourY)){            neighbouringTiles.add(t);        } else if((t.getXPosition() == bottomNeighbourX) && (t.getYPosition() == bottomNeighbourY)){            neighbouringTiles.add(t);        }    }    return neighbouringTiles;}/** * Finds a <code>Tile</code> with matching position * * @param x *      The horizontal position * @param y *      The vertical position * @return *      matching <code>Tile</code> */public Tile findTile(int x, int y){    for(Tile t: board) {        if(t.getXPosition() == x && t.getYPosition() == y)            return t;    }    return null;}/** * Finds a <code>Tile</code> with matching number * * @param number *      The number on the <code>Tile</code> * @return *      matching <code>Tile</code> */public Tile findTile(int number){    for(Tile t: board) {        if(t.getNumber() == number)            return t;    }    return null;}/** *Prints the board */public void print() {    System.out.println(*=====*);    for(int j = 0; j < Main.ROWS; j++){        System.out.print(||);        for(int i = 0; i < Main.COLUMNS; i++){            if(findTile(i, j).getNumber() == 0)                System.out.print( );            else if(findTile(i, j) != null)                System.out.print(findTile(i, j).getNumber());        }        System.out.println(||);    }    System.out.println(*=====*);}}Tile Class: /*** Represents a single tile on a board* * @author Paymon Sattarzadeh* @date 27/11/2014* @time 02:27*/public class Tile {/** * Number on Tile */private int number;/** * Horizontal position of tile */private int x;/** * Vertical position of tile */private int y;/** * Constructs a <code>Tile</code> instance with a number and position. * * @param number *      The number for the <code>Tile</code>. * @param x *      The Horizontal position for the <code>Tile</code>. */public Tile(int number, int x, int y){    this.number = number;    this.x = x;    this.y = y;}/** * @param x *      Horizontal position for the <code>Tile</code> * @param y *      Vertical position for the <code>Tile</code> */public void setPosition(int x, int y){    this.x = x;    this.y = y;}/** * @return *      Current horizontal position of <code>Tile</code> */public int getXPosition(){    return x;}/** * @return *      Current vertical position of <code>Tile</code> */public int getYPosition(){    return y;}/** * @param number *      Number on Tile */public void setNumber(int number){    this.number = number;}/** * @return *      Current number on tile */public int getNumber(){    return number;}}
8 Puzzle solver A* search
java;search