import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;

public class EightQueens extends Application {
  public static final int SIZE = 8; // Wielkość szachownicy
    // Hetmany są umieszczane na polach (i, queens[i])
    // –1 oznacza, że w i-tym rzędzie jeszcze nie umieszczono hetmana
    // Początkowo umieść hetmana na polu (0, 0) w zerowym rzędzie
  private int[] queens = {-1, -1, -1, -1, -1, -1, -1, -1}; 

  @Override // Przesłanianie metody start z klasy Application
  public void start(Stage primaryStage) {
    search(); // Wyszukiwanie rozwiązania
        
    // Wyświetlanie szachownicy
    GridPane chessBoard = new GridPane();
    chessBoard.setAlignment(Pos.CENTER);
    Label[][] labels = new Label[SIZE][SIZE];
    for (int i = 0; i < SIZE; i++)
      for (int j = 0; j < SIZE; j++) {
        chessBoard.add(labels[i][j] = new Label(), j, i);
        labels[i][j].setStyle("-fx-border-color: black");
        labels[i][j].setPrefSize(55, 55);
      }

    // Wyświetlanie hetmanów
    Image image = new Image("image/queen.jpg");
    for (int i = 0; i < SIZE; i++)
      labels[i][queens[i]].setGraphic(new ImageView(image));
      
    // Tworzenie sceny i umieszczanie jej w oknie
    Scene scene = new Scene(chessBoard, 55 * SIZE, 55 * SIZE);
    primaryStage.setTitle("EightQueens"); // Ustawianie nagłówka okna
    primaryStage.setScene(scene); // Umieszczanie sceny w oknie
    primaryStage.show(); // Wyświetlanie okna
  }

  /** Szukanie rozwiązania */
  private boolean search() {
    // k – 1 to liczba już rozmieszczonych hetmanów
    // Kod szuka pozycji dla hetmana w k-tym rzędzie
    int k = 0;
    while (k >= 0 && k < SIZE) {
      // Szukanie pozycji dla hetmana w k-tym rzędzie
      int j = findPosition(k);
      if (j < 0) {
        queens[k] = -1;
        k--; // Nawrót do poprzedniego rzędu
      } else {
        queens[k] = j;
        k++;
      }
    }
    
    if (k == -1)
      return false; // Brak rozwiązania
    else
      return true; // Znaleziono rozwiązanie
  }

  public int findPosition(int k) {
    int start = queens[k] + 1; // Szukanie nowego miejsca dla hetmana

    for (int j = start; j < SIZE; j++) {
      if (isValid(k, j))
        return j; // (k, j) to miejsce, w którym należy umieścić hetmana
    }

    return -1;
  }
  
  /** Zwraca true, jeśli hetmana można umieścić na polu (row, column) */
  public boolean isValid(int row, int column) {
    for (int i = 1; i <= row; i++)
      if (queens[row - i] == column // Sprawdzanie kolumny
        || queens[row - i] == column - i // Sprawdzanie przekątnej malejącej w prawo
        || queens[row - i] == column + i) // Sprawdzanie przekątnej rosnącej w prawo
        return false; // Możliwość ataku hetmana
    return true; // Bez możliwości ataku
  }

  /**
   * Metoda main jest potrzebna tylko w środowiskach IDE z ograniczoną obsługą platformy JavaFX.
   * Nie jest potrzebna przy uruchamianiu kodu w wierszu poleceń.
   */
  public static void main(String[] args) {
    launch(args);
  }
}
