2024-05-04 00:13:44 +02:00
|
|
|
import java.util.Random;
|
|
|
|
|
2024-05-04 17:56:30 +02:00
|
|
|
/**
|
|
|
|
* Cette classe génère une grille de Sudoku aléatoire.
|
|
|
|
*/
|
2024-05-04 00:13:44 +02:00
|
|
|
public class GenerateGrid {
|
|
|
|
private static final int GRID_SIZE = 9;
|
|
|
|
private static final int EMPTY_CELL = 0;
|
|
|
|
private static final int MINIMUM_CLUES = 25; // Modifier ce nombre en fonction du nombre de clues désiré
|
|
|
|
|
2024-05-04 17:56:30 +02:00
|
|
|
/**
|
|
|
|
* Méthode principale pour tester la génération d'une grille ( Seulement pour le debug ).
|
|
|
|
* @param args Arguments de la ligne de commande (non utilisés).
|
|
|
|
*/
|
2024-05-04 00:13:44 +02:00
|
|
|
public static void main(String[] args) {
|
2024-05-04 17:56:30 +02:00
|
|
|
Grid grid = generateSudokuGrid();
|
2024-05-04 00:13:44 +02:00
|
|
|
printGrid(grid);
|
|
|
|
}
|
|
|
|
|
2024-05-04 17:56:30 +02:00
|
|
|
/**
|
|
|
|
* Génère une grille de Sudoku.
|
|
|
|
* @return La grille de Sudoku générée.
|
|
|
|
*/
|
|
|
|
public static Grid generateSudokuGrid() {
|
2024-05-04 00:13:44 +02:00
|
|
|
Grid grid = new Grid();
|
|
|
|
solveSudoku(grid);
|
|
|
|
removeNumbers(grid);
|
|
|
|
return grid;
|
|
|
|
}
|
|
|
|
|
2024-05-04 17:56:30 +02:00
|
|
|
/**
|
|
|
|
* Résout la grille de Sudoku donnée.
|
|
|
|
* @param grid La grille de Sudoku à résoudre.
|
|
|
|
* @return True si la grille a été résolue avec succès, sinon False.
|
|
|
|
*/
|
2024-05-04 00:13:44 +02:00
|
|
|
private static boolean solveSudoku(Grid grid) {
|
|
|
|
return solveSudokuHelper(grid, 0, 0);
|
|
|
|
}
|
|
|
|
|
2024-05-04 17:56:30 +02:00
|
|
|
/**
|
|
|
|
* Méthode auxiliaire récursive pour résoudre la grille de Sudoku.
|
|
|
|
* @param grid La grille de Sudoku à résoudre.
|
|
|
|
* @param row L'indice de ligne actuel.
|
|
|
|
* @param col L'indice de colonne actuel.
|
|
|
|
* @return True si la grille a été résolue avec succès, sinon False.
|
|
|
|
*/
|
2024-05-04 00:13:44 +02:00
|
|
|
private static boolean solveSudokuHelper(Grid grid, int row, int col) {
|
|
|
|
if (row == GRID_SIZE) {
|
|
|
|
row = 0;
|
|
|
|
if (++col == GRID_SIZE) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (grid.getCell(row, col).getValue() != EMPTY_CELL) {
|
|
|
|
return solveSudokuHelper(grid, row + 1, col);
|
|
|
|
}
|
|
|
|
|
|
|
|
Random random = new Random();
|
|
|
|
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9};
|
|
|
|
shuffleArray(numbers, random);
|
|
|
|
|
|
|
|
for (int num : numbers) {
|
|
|
|
if (isValidMove(grid, row, col, num)) {
|
|
|
|
grid.getCell(row, col).setValue(num);
|
|
|
|
if (solveSudokuHelper(grid, row + 1, col)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
grid.getCell(row, col).setValue(EMPTY_CELL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-05-04 17:56:30 +02:00
|
|
|
/**
|
|
|
|
* Vérifie si un mouvement donné est valide.
|
|
|
|
* @param grid La grille de Sudoku.
|
|
|
|
* @param row L'indice de ligne.
|
|
|
|
* @param col L'indice de colonne.
|
|
|
|
* @param num Le nombre à placer.
|
|
|
|
* @return True si le mouvement est valide, sinon False.
|
|
|
|
*/
|
2024-05-04 00:13:44 +02:00
|
|
|
private static boolean isValidMove(Grid grid, int row, int col, int num) {
|
|
|
|
for (int i = 0; i < GRID_SIZE; i++) {
|
|
|
|
if (grid.getCell(row, i).getValue() == num || grid.getCell(i, col).getValue() == num) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int boxRow = row - row % 3;
|
|
|
|
int boxCol = col - col % 3;
|
|
|
|
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
for (int j = 0; j < 3; j++) {
|
|
|
|
if (grid.getCell(boxRow + i, boxCol + j).getValue() == num) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-05-04 17:56:30 +02:00
|
|
|
/**
|
|
|
|
* Mélange les éléments d'un tableau.
|
|
|
|
* @param array Le tableau à mélanger.
|
|
|
|
* @param random L'instance de Random à utiliser.
|
|
|
|
*/
|
2024-05-04 00:13:44 +02:00
|
|
|
private static void shuffleArray(int[] array, Random random) {
|
|
|
|
for (int i = array.length - 1; i > 0; i--) {
|
|
|
|
int index = random.nextInt(i + 1);
|
|
|
|
int temp = array[index];
|
|
|
|
array[index] = array[i];
|
|
|
|
array[i] = temp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-04 17:56:30 +02:00
|
|
|
/**
|
|
|
|
* Supprime les nombres de la grille pour créer une énigme de Sudoku.
|
|
|
|
* @param grid La grille de Sudoku.
|
|
|
|
*/
|
2024-05-04 00:13:44 +02:00
|
|
|
public static void removeNumbers(Grid grid) {
|
|
|
|
Random random = new Random();
|
|
|
|
|
|
|
|
while (countClues(grid) > MINIMUM_CLUES) {
|
|
|
|
int row = random.nextInt(GRID_SIZE);
|
|
|
|
int col = random.nextInt(GRID_SIZE);
|
|
|
|
int value = grid.getCell(row, col).getValue();
|
|
|
|
grid.getCell(row, col).setValue(EMPTY_CELL);
|
|
|
|
|
|
|
|
Grid tempGrid = new Grid();
|
|
|
|
if (!solveSudoku(tempGrid)) {
|
|
|
|
grid.getCell(row, col).setValue(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-04 17:56:30 +02:00
|
|
|
/**
|
|
|
|
* Compte le nombre de "clues" dans la grille.
|
|
|
|
* @param grid La grille de Sudoku.
|
|
|
|
* @return Le nombre de "clues" dans la grille.
|
|
|
|
*/
|
2024-05-04 00:13:44 +02:00
|
|
|
private static int countClues(Grid grid) {
|
|
|
|
int count = 0;
|
|
|
|
for (int row = 0; row < GRID_SIZE; row++) {
|
|
|
|
for (int col = 0; col < GRID_SIZE; col++) {
|
|
|
|
if (grid.getCell(row, col).getValue() != EMPTY_CELL) {
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2024-05-04 17:56:30 +02:00
|
|
|
/**
|
|
|
|
* Affiche la grille de Sudoku dans la console.
|
|
|
|
* @param grid La grille de Sudoku à afficher.
|
|
|
|
*/
|
2024-05-04 00:13:44 +02:00
|
|
|
public static void printGrid(Grid grid) {
|
|
|
|
for (int row = 0; row < GRID_SIZE; row++) {
|
|
|
|
for (int col = 0; col < GRID_SIZE; col++) {
|
|
|
|
System.out.print(grid.getCell(row, col).getValue() + " ");
|
|
|
|
}
|
|
|
|
System.out.println();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|