4

I'm having trouble coding the 8 queens problem. I've coded a class to help me solve it, but for some reason, I'm doing something wrong. I kind of understand what's supposed to happen.

Also, we have to use recursion to solve it but I have no clue how to use the backtracking I've read about, so I just used it in the methods checking if a position is legitimate.

My board is String [] [] board = { { "O", "O"... etc etc with 8 rows and 8 columns. If I'm getting anything wrong conceptually or making a grave Java mistake, please say so :D Thanks!

public void solve () {
    int Queens = NUM_Queens - 1;
    while (Queens > 0) {
        for (int col = 0; col < 8; col++) {
            int row = -1;
            boolean c = false;
            while (c  = false && row < 8) {
                row ++;
                c = checkPos (row, col);
            }
            if (c == true) {
                board[row][col] = "Q";
                Queens--;
            }
            else 
                System.out.println("Error");
        }
    }
    printBoard ();
}

// printing the board
public void printBoard () {
    String ret = "";
    for (int i = 0; i < 8; i++) {
        for (int a = 0; a < 8; a++)
            ret += (board[i][a] + ", ");
        ret += ("\n");
    }
    System.out.print (ret);
}

// checking if a position is a legitimate location to put a Queen
public boolean checkPos (int y, int x) {
    boolean r = true, d = true, u = true, co = true;
    r = checkPosR (y, 0);
    co = checkPosC (0, x);
    int col = x;
    int row = y;
    while (row != 0 && col != 0 ) { //setting up to check diagonally downwards
        row--;
        col--;
    }
    d = checkPosDD (row, col);
    col = x;
    row = y;
    while (row != 7 && col != 0 ) { //setting up to check diagonally upwards
        row++;
        col--;
    }
    d = checkPosDU (row, col);
    if (r = true && d = true && u = true && co = true)
        return true;
    else
        return false;
}

// checking the row
public boolean checkPosR (int y, int x) {
    if (board[y][x].contentEquals("Q"))
            return false;
    else if (board[y][x].contentEquals("O") && x == 7)
        return true;
    else //if (board[y][x].contentEquals("O"))  
        return checkPosR (y, x+1);
}

// checking the column
public boolean checkPosC (int y, int x) {
    if (board[y][x].contentEquals("Q"))
            return false;
    else if (board[y][x].contentEquals("O") && y == 7)
        return true;
    else //if (board[y][x].contentEquals("O"))  
        return checkPosR (y+1, x);
}

// checking the diagonals from top left to bottom right
public boolean checkPosDD (int y, int x) {
    if (board[y][x].contentEquals("Q"))
        return false;
    else if (board[y][x].contentEquals("O") && (x == 7 || y == 7))
        return true;
    else //if (board[y][x].contentEquals("O"))  
        return checkPosR (y+1, x+1);
}

 // checking the diagonals from bottom left to up right
public boolean checkPosDU (int y, int x) {
    if (board[y][x].contentEquals("Q"))
        return false;
    else if (board[y][x].contentEquals("O") && (x == 7 || y == 0))
        return true;
    else //if (board[y][x].contentEquals("O"))  
        return checkPosR (y-1, x+1);
    }
}
Tlazolteotl
  • 41
  • 1
  • 5
  • 3
    Since there can only be one queen per row, represent your board as `int[8]`, where each entry is the column position of that row's queen. That'll simplify things a lot. – NPE Mar 05 '13 at 08:44
  • 2
    what is the output/error you are getting? – Aashray Mar 05 '13 at 08:46
  • 1
    Are you facing any issues with the code. What is the expected output and what is the actual output your are getting? – Jayamohan Mar 05 '13 at 08:46
  • @Aashray I put in the `Error` line if no position was found for the Queen, and it keeps printing this Error. So the progra can't find a place to put a queen. @Jayamohan The problem is that my program isn't finding places to put a Queen – Tlazolteotl Mar 05 '13 at 08:58
  • 1
    Your while loop is assigning `c` to `false`, I imagine that's unintended behaviour. – Quetzalcoatl Mar 05 '13 at 10:23

2 Answers2

1

As this is homework, the solution, but not in code.

Try to write a method that only handles what needs to happen on a single column; this is where you are supposed to use recursion. Do backtracking by checking if a solution exists, if not, undo your last change (i.e. change the queen position) and try again. If you only focus on one part of the problem (one column), this is much easier than thinking about all columns at the same time.

And as Quetzalcoatl points out, you are assigning false to your variable in the first loop. You probably do not want to do that. You should always enable all warnings in your compiler (run javac with -Xlint) and fix them.

wds
  • 31,873
  • 11
  • 59
  • 84
-1

You are trying some kind of brute-force, but, as you already mentioned, you have no recursion. Your programs tries to put a queen on the first possible position. But at the end no solution is found. It follows that your first assumption (the position of your first queen) is invalid. You have to go back to this state. And have to assume that your checkPos(x,y) is false instead of true.

Now some hints:

  1. As mentioned before by NPE int[N] queens is more suitable representation.
  2. sum(queens) have to be 0+1+2+3+4+5+6+7=28, since a position has to be unique.
  3. Instead of checking only the position of the new queen, you may check a whole situation. It is valid if for all (i,j) \in N^2 with queen(i) = j, there exists no (k,l) != (i,j) with abs(k-i) == abs(l-j)
wds
  • 31,873
  • 11
  • 59
  • 84
gnod
  • 407
  • 3
  • 9
  • I'm slightly confused what you mean with checking the whole situation. Would you mind writing some of the code so I could get an idea? – Tlazolteotl Mar 05 '13 at 14:00
  • Sorry, but from "there is no solution" it does **not** follow that the position of the **first** queen is wrong. – Ingo Mar 05 '13 at 14:30
  • Right, you have to invalidate the last assumption at first in case of invalidation. – gnod Mar 05 '13 at 19:13