So I am working on this 3x3 game, where you are given a current state, for example:
1 5 6
3 7 b
2 8 4
and you want to reach the goal state of:
b 1 2
3 4 5
6 7 8
So I have written all the other methods in my code which I posted below. The problem I am having now is in my actual A* search. I want to use two heuristics, one which checks how many pieces are in the wrong location (so for instance the heuristic function would show that the current state has H=8 pieces in the wrong place) and another heuristic which will calculate how far away the total sum of pieces is (so for my current state, piece one is 1 move away, piece two is 3 moves away, etc. and the sum of all that will be my H value). So I am recording my gameBoard
in an array of strings.
So now to my actual problem. Everything but my A* is working right now as seen below.
First I call setFinalGoalState()
which makes the variable finalGoalState
so I can compare my current state to the goal state.
Then I make a priorityQueue
which should be an ArrayList
of Node
s, where each node will have an G value (G being how far it is in the tree), H value, reference to parent, and the current state.
So first I call an initial huesticOneHValue()
to get the H value of my first state. I then run an if
statement for the "h1" (which is just my first heuristic method, as I said I'll add another one later). It should then make an initial node Root
which will be my first node in the tree, and add this to the priority queue.
Then it should run through the priority queue. It will take the current node as the first element in the priorityQueue
, and then remove it from the queue. It sets my actual gameBoard
as the same state of the gameBoard
that the current node is. Then it creates an ArrayList
of possible moves (this calls isValidMoves()
, which checks to see if you can actually move up,down,left,or right, and then puts it in a list). I then make a for loop to run through the size of my possible moves, and then I do the actual moving by calling the move()
method (so the first call for int i = 0
would call move "up" since you can move b up in my current state) Then it should create a Node
child containing the gValue
of where I am (it should equal 1), the new H value (in some cases this might stay same, but it should be working towards lowering the H values), its parent (which I think should just be currentNode
?), and then the state of the currentNode
(what the board looks like).
Then the next for loop checks to see where it should place it in the priority queue. Nodes with lesser g+h
values should go in the front of the queue because we want to check them first to see if they reach goal state. So I set an initial condition if the queue is empty to add it to the front, else it checks to see if the priorityQueue
at j
is a larger g+h
than the childs, and if it is, the child gets added to the index of j
(and everything else should shift over I think?) Lastly, after all the moves are done, it checks to see if the priorityQueue
's front node's state is equal to our goal state, and if its not, it goes back to the front of the while loop and runs again.
I think ultimately I am screwing up something with my nodes. When I ran debugging I found that every time I make a child, the parent node's state gets updated to that of the childs, which shouldn't happen because the child should be a certain move of the parents (either up, down, left, or right). I think I messed up something making either my node class or the way that I am creating the nodes and adding them into a queue. I also get an indexOutOfBounds when I try adding my child into the priorityQueue
at
else if((priorityQueue.get(j).getG()+priorityQueue.get(j).getH()) > (child.getG()+child.getH())){
The rest of my code is below:
EightPuzzle Class
public class EightPuzzle{
static String[][] gameBoard = new String[3][3];
static String[][] finalGoalState = new String[3][3];
static int[] bLocation = new int[2];
String board;
String dir;
/*public void ReadFromTxt(String file) throws FileNotFoundException, IOException {
String read;
FileReader f = new FileReader(file);
int i = 0;
int j;
BufferedReader b = new BufferedReader(f);
System.out.println("Loading puzzle from file...");
while((read = b.readLine())!=null){
if(read.length()==3){
for(j=0;j<3;j++){
board[i][j] = (int)(read.charAt(j)-48);
}
}
i++;
}
b.close();
System.out.println("Puzzle loaded!");
}*/
public void setState(String board){
gameBoard[0][0] = board.substring(0,1);
gameBoard[0][1] = board.substring(1,2);
gameBoard[0][2] = board.substring(2,3);
gameBoard[1][0] = board.substring(4,5);
gameBoard[1][1] = board.substring(5,6);
gameBoard[1][2] = board.substring(6,7);
gameBoard[2][0] = board.substring(8,9);
gameBoard[2][1] = board.substring(9,10);
gameBoard[2][2] = board.substring(10,11);
System.out.println(Arrays.deepToString(gameBoard));
}
public static void setFinalGoalState(){
finalGoalState[0][0] = "b";
finalGoalState[0][1] = "1";
finalGoalState[0][2] = "2";
finalGoalState[1][0] = "3";
finalGoalState[1][1] = "4";
finalGoalState[1][2] = "5";
finalGoalState[2][0] = "6";
finalGoalState[2][1] = "7";
finalGoalState[2][2] = "8";
}
public static void setGoalState(){
gameBoard[0][0] = "b";
gameBoard[0][1] = "1";
gameBoard[0][2] = "2";
gameBoard[1][0] = "3";
gameBoard[1][1] = "4";
gameBoard[1][2] = "5";
gameBoard[2][0] = "6";
gameBoard[2][1] = "7";
gameBoard[2][2] = "8";
bLocation[0] = 0;
bLocation[1] = 0;
}
public void randomizeState(int numMoves){
setGoalState();
for(int i=0;i<numMoves;i++){
ArrayList<String> validMoves3 = isValidMove();
Random r = new Random();
int mIndex = r.nextInt(validMoves3.size());
String choice = validMoves3.get(mIndex);
move(choice);
System.out.println(Arrays.deepToString(gameBoard));
}
}
public ArrayList<String> isValidMove(){
ArrayList<String> validMoves = new ArrayList<String>();
if(bLocation[0] != 0){
//can move up
validMoves.add("up");
}
if(bLocation[0] != 2){
//can move down
validMoves.add("down");
}
if(bLocation[1] != 0){
//can move left
validMoves.add("left");
}
if(bLocation[1] != 2){
//can move right
validMoves.add("right");
}
return validMoves;
}
public void move(String dir){
ArrayList<String> validMoves2 = isValidMove();
if(validMoves2.contains("up") && dir.equals("up")){
String temp1 = new String();
temp1 = gameBoard[bLocation[0]-1][bLocation[1]];
gameBoard[bLocation[0]][bLocation[1]] = temp1;
gameBoard[bLocation[0]-1][bLocation[1]] = "b";
bLocation[0] = bLocation[0]-1;
}
else if(validMoves2.contains("down") && dir.equals("down")){
String temp2 = new String();
temp2 = gameBoard[bLocation[0]+1][bLocation[1]];
gameBoard[bLocation[0]][bLocation[1]] = temp2;
gameBoard[bLocation[0]+1][bLocation[1]] = "b";
bLocation[0] = bLocation[0]+1;
}
else if(validMoves2.contains("left") && dir.equals("left")){
String temp3 = new String();
temp3 = gameBoard[bLocation[0]][bLocation[1]-1];
gameBoard[bLocation[0]][bLocation[1]] = temp3;
gameBoard[bLocation[0]][bLocation[1]-1] = "b";
bLocation[1] = bLocation[1]-1;
}
else if(validMoves2.contains("right") && dir.equals("right")){
String temp4 = new String();
temp4 = gameBoard[bLocation[0]][bLocation[1]+1];
gameBoard[bLocation[0]][bLocation[1]] = temp4;
gameBoard[bLocation[0]][bLocation[1]+1] = "b";
bLocation[1] = bLocation[1]+1;
}
}
public static void printState(){
System.out.println(Arrays.deepToString(gameBoard));
}
public void getbLocation(){
for(int i=0; i<gameBoard.length; i++){
for(int j=0; j<gameBoard[i].length; j++){
if(gameBoard[i][j].equals("b"))
{
bLocation[0] = i;
bLocation[1] = j;
break;
}
}
}
System.out.println(Arrays.toString(bLocation));
}
public int heuristicOneHValue(){
int hValue = 0;
if(!gameBoard[0][0].equals("b")){
hValue++;
}
if(!gameBoard[0][1].equals("1")){
hValue++;
}
if(!gameBoard[0][2].equals("2")){
hValue++;
}
if(!gameBoard[1][0].equals("3")){
hValue++;
}
if(!gameBoard[1][1].equals("4")){
hValue++;
}
if(!gameBoard[1][2].equals("5")){
hValue++;
}
if(!gameBoard[2][0].equals("6")){
hValue++;
}
if(!gameBoard[2][1].equals("7")){
hValue++;
}
if(!gameBoard[2][2].equals("8")){
hValue++;
}
return hValue;
}
public void solveAstar(String heuristic){
setFinalGoalState();
ArrayList<Node> priorityQueue = new ArrayList<Node>();
int h = heuristicOneHValue();
if(heuristic.equalsIgnoreCase("h1"))
{
Node root = new Node(0,h,null,gameBoard);
priorityQueue.add(root);
while(priorityQueue != null){
Node currentNode = priorityQueue.get(0);
priorityQueue.remove(0);
gameBoard = currentNode.state;
ArrayList<String> moves = isValidMove();
for(int i = 0; i < moves.size(); i++){
move(moves.get(i));
Node child = new Node(currentNode.getG(),heuristicOneHValue(),currentNode,currentNode.getState());
for(int j = 0; j <= priorityQueue.size(); j++){
if(priorityQueue.size() == 0){
priorityQueue.add(0, child);
}
else if((priorityQueue.get(j).getG()+priorityQueue.get(j).getH()) > (child.getG()+child.getH())){
priorityQueue.add(j, child);
}
}
}
if(priorityQueue.get(0).getState() == finalGoalState){
priorityQueue = null;
}
}
}
//h2 here
}
public static void main (String[]args){
EightPuzzle b1=new EightPuzzle();
b1.setState("156 37b 284");
b1.getbLocation();
b1.solveAstar("h1");
}
}
Node Class
class Node {
public String[][] state;
public Node parent;
public int g;
public int h;
public Node(int g, int h, Node parent, String[][] state){
this.g = g;
this.h = h;
this.parent = parent;
this.state = state;
}
public String[][] getState(){
return state;
}
public int getG(){;
return g;
}
public int getH(){
return h;
}
public Node getParent(){
return parent;
}
public void setState(String[][] state){
this.state = state;
}
public void setG(int g){
this.g = g;
}
public void setH(int h){
this.h = h;
}
public void setParent(Node parent){
this.parent = parent;
}
}