Алгоритм 8 неатакующих ферзей с рекурсией

У меня проблемы с кодированием задачи с 8 ферзями. Я закодировал класс, чтобы помочь мне решить эту проблему, но по какой-то причине я делаю что-то не так. Я вроде понимаю, что должно произойти.

Кроме того, мы должны использовать рекурсию, чтобы решить эту проблему, но я понятия не имею, как использовать откат, о котором я читал, поэтому я просто использовал его в методах, проверяющих, является ли позиция законной.

Моя доска String [] [] board = { { "O", "O"... и т. д. и т. д. с 8 строками и 8 столбцами. Если я концептуально ошибаюсь или делаю серьезную ошибку в Java, так и скажите :D Спасибо!

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);
    }
}

person Tlazolteotl    schedule 05.03.2013    source источник
comment
Поскольку в каждом ряду может быть только один ферзь, представьте свою доску как int[8], где каждая запись представляет собой позицию столбца ферзя в этом ряду. Это сильно упростит дело.   -  person NPE    schedule 05.03.2013
comment
какой вывод/ошибку вы получаете?   -  person Aashray    schedule 05.03.2013
comment
У вас возникли проблемы с кодом. Каков ожидаемый результат и каков фактический результат, который вы получаете?   -  person Jayamohan    schedule 05.03.2013
comment
@Aashray Я добавляю строку Error, если для королевы не найдена позиция, и она продолжает выводить эту ошибку. Так вот програ не находит куда поставить ферзя. @Jayamohan Проблема в том, что моя программа не находит места для размещения королевы.   -  person Tlazolteotl    schedule 05.03.2013
comment
Ваш цикл while присваивает c false, я полагаю, что это непреднамеренное поведение.   -  person Quetzalcoatl    schedule 05.03.2013


Ответы (2)


Поскольку это домашнее задание, решение, но не в коде.

Попробуйте написать метод, который обрабатывает только то, что должно произойти в одном столбце; здесь вы должны использовать рекурсию. Сделайте возврат, проверив, существует ли решение, если нет, отмените последнее изменение (т.е. измените положение ферзя) и повторите попытку. Если вы сосредоточитесь только на одной части проблемы (одной колонке), это будет намного проще, чем думать обо всех колонках одновременно.

И, как указывает Кетцалькоатль, вы присваиваете false своей переменной в первом цикле. Вы, вероятно, не хотите этого делать. Вы всегда должны включать все предупреждения в своем компиляторе (запускать javac с параметром -Xlint) и исправлять их.

person wds    schedule 05.03.2013

Вы пытаетесь выполнить какой-то брутфорс, но, как вы уже сказали, у вас нет рекурсии. Ваша программа пытается поставить ферзя на первую возможную позицию. Но в итоге решение не найдено. Отсюда следует, что ваше первое предположение (положение вашего первого ферзя) неверно. Вы должны вернуться в это состояние. И нужно предположить, что ваш checkPos (x, y) является ложным, а не истинным.

Теперь несколько советов:

  1. Как упоминалось ранее, NPE int[N] queens является более подходящим представлением.
  2. сумма(ферзей) должна быть 0+1+2+3+4+5+6+7=28, так как позиция должна быть уникальной.
  3. Вместо проверки только положения нового ферзя вы можете проверить всю ситуацию. Это справедливо, если для всех (i,j) \in N^2 с королевой(i) = j не существует (k,l) != (i,j) с abs(k-i) == abs(l-j)
person gnod    schedule 05.03.2013
comment
Я немного смущен тем, что вы имеете в виду под проверкой всей ситуации. Не могли бы вы написать немного кода, чтобы я мог получить представление? - person Tlazolteotl; 05.03.2013
comment
Извините, но из отсутствия решения не следует, что положение первого ферзя неправильное. - person Ingo; 05.03.2013
comment
Правильно, вы должны сначала аннулировать последнее предположение в случае аннулирования. - person gnod; 05.03.2013