diff --git a/app/src/main/java/sudoku/io/ConsoleInterface.java b/app/src/main/java/sudoku/io/ConsoleInterface.java index 0c14e16..bebc621 100644 --- a/app/src/main/java/sudoku/io/ConsoleInterface.java +++ b/app/src/main/java/sudoku/io/ConsoleInterface.java @@ -11,8 +11,13 @@ import java.util.List; import java.util.Scanner; public class ConsoleInterface { - public Scanner reader = new Scanner(System.in); + private final Scanner reader = new Scanner(System.in); + /** + * Début de la séquence console, affiche un message de bienvenue et les crédits du projet + * puis donne à l'utilisateur le choix de récupérer un doku sauvegardé + * ou d'en créer un nouveau. + */ public void welcome() { System.out.println("Welcome to our Sudoku Solver!"); System.out.println("This is the project of Melvyn Bauvent, Lilas Grenier and Simon Pribylski."); @@ -24,9 +29,13 @@ public class ConsoleInterface { } } + /** + * Demande à l'utilisateur un fichier de sauvegarde et le laisse jouer au MultiDoku. + * qui y est sauvegardé + */ private void useSavedDoku() { System.out.println("What save should we use? Please enter the save number."); - MultiDoku md = saveChoice(); + MultiDoku md = getSavedDoku(); int blockWidth = md.getSubGrid(0).getBlockWidth(); int blockHeight = md.getSubGrid(0).getBlocks().getFirst().getCells().size() / blockWidth; List listSymbols = pickSymbols(blockWidth * blockHeight); @@ -38,7 +47,10 @@ public class ConsoleInterface { congrats(); } - public void createDoku() { + /** + * Demande à l'utilisateur les paramètres du doku à générer. + */ + private void createDoku() { System.out.println("First of all, you need to tell me the size of the sudoku you want to generate."); int width = getBlockWidth(); int height = getBlockHeight(); @@ -58,7 +70,7 @@ public class ConsoleInterface { System.out.println("Your sudoku will look like this:"); showMultidoku(doku, listSymbols, width, height); System.out.println( - "You can now manually fill this sudoku ('fill'), or generate a playable one ('generate', default):"); + "You can now manually fill this sudoku ('fill'), or generate a playable one from this template ('generate', default):"); if (reader.next().equalsIgnoreCase("fill")) { findSolution(doku, listSymbols, width, height); } else { @@ -66,6 +78,14 @@ public class ConsoleInterface { } } + /** + * Remplit un doku vide en fonction de la difficulté que l'utilisateur renseigne, + * et le laisse jouer. + * @param doku MultiDoku, MultiDoku vide à remplir + * @param listSymbols List, liste des symboles à utiliser + * @param width int, largeur d'un bloc du sudoku + * @param height int, hauteur d'un bloc du sudoku + */ private void playableDoku(MultiDoku doku, List listSymbols, int width, int height) { System.out.println("We will now fill this sudoku."); System.out.println("What level of difficulty would you like?" + @@ -86,6 +106,14 @@ public class ConsoleInterface { } } + /** + * Permet à l'utilisateur de remplir manuellement un sudoku vide, et de le remplir + * quand souhaité. + * @param doku MultiDoku, MultiDoku vide à remplir + * @param listSymbols List, liste des symboles à utiliser + * @param width int, largeur d'un bloc du sudoku + * @param height int, hauteur d'un bloc du sudoku + */ private void findSolution(MultiDoku doku, List listSymbols, int width, int height){ do { turn(doku, listSymbols, width, height); @@ -93,15 +121,22 @@ public class ConsoleInterface { System.out.println("This doku can be solved like this :"); showMultidoku(doku, listSymbols, width, height); exit(); - } + /** + * Message de félicitation quand l'utilisateur a rempli son doku. + */ private void congrats() { System.out.println("Congrats! You've solved this sudoku! We hope this was fun! Let's play together again!"); System.exit(0); } - private MultiDoku saveChoice() { + /** + * Renvoie un MultiDoku préenregistré, dont le numéro de sauvegarde est renseigné + * par l'utilisateur. + * @return Mutidoku, multidoku enregistré à la sauveagrde de numéro donné. + */ + private MultiDoku getSavedDoku() { int nbSave; MultiDoku md = null; do { @@ -115,7 +150,11 @@ public class ConsoleInterface { return md; } - public int getBlockWidth() { + /** + * Demande à l'utilisateur la largeur d'un bloc du sudoku à générer. + * @return int, largeur d'un bloc du sudoku + */ + private int getBlockWidth() { System.out.println("Width of a block: "); int widthBlock = reader.nextInt(); checkValidSize(widthBlock); @@ -127,7 +166,11 @@ public class ConsoleInterface { return widthBlock; } - public int getBlockHeight() { + /** + * Demande à l'utilisateur la hauteur d'un bloc du sudoku à générer. + * @return int, hauteur d'un bloc du sudoku + */ + private int getBlockHeight() { System.out.println("Height of a block: "); int heightBlock = reader.nextInt(); checkValidSize(heightBlock); @@ -139,10 +182,20 @@ public class ConsoleInterface { return heightBlock; } + /** + * Vérifie si la taille passée en paramètres est une taille valide. + * @param size int, longueur à vérifier + * @return true si size>0, false sinon. + */ private Boolean checkValidSize(int size) { return (size > 0); } + /** + * Permet à l'utilisateur de choisir les symboles qu'il souhaite utiliser pour l'affichage. + * @param numberOfSymbols int, nombre de symboles à choisir + * @return LIst, liste des symboles à utiliser + */ private List pickSymbols(int numberOfSymbols) { System.out.println("Would you like to pick the " + numberOfSymbols + " symbols from the sudoku? (y/n, default 'no')"); @@ -171,6 +224,10 @@ public class ConsoleInterface { } } + /** + * Permet à l'utilisateur de choisir les contraintes qu'il souhaite utiliser pour son sudoku. + * @return List, liste des contraintes à utiliser + */ private List getListConstraints() { List listConstraints = SudokuFactory.DEFAULT_CONSTRAINTS; System.out.println( @@ -181,6 +238,11 @@ public class ConsoleInterface { return listConstraints; } + /** + * Remplit un sudoku selon la difficulté passée en paramètre. + * @param doku MultiDoku, doku vide à remplir selon la difficulté. + * @param difficultyName String, difficulté de résolution du doku à remplir. + */ private void generatePartialDoku(MultiDoku doku, String difficultyName) { Difficulty difficulty; switch (difficultyName) { @@ -200,18 +262,41 @@ public class ConsoleInterface { } } + /** + * Remplit entièrement le doku passé en paramètre. + * @param doku MultiDoku, doku à remplir + */ private void generateFullDoku(MultiDoku doku) { new RandomSolver().solve(doku); } + /** + * Affiche le doku passé en paramètre. + * @param doku MultiDoku, MultiDoku à afficher + * @param listSymbols List, liste des symboles à utiliser + * @param width int, largeur d'un bloc du sudoku + * @param height int, hauteur d'un bloc du sudoku + */ private void showMultidoku(MultiDoku doku, List listSymbols, int width, int height) { showMultiDoku(RenderableMultidoku.fromMultidoku(doku), listSymbols, width, height); } + /** + * Affiche le doku passé en paramètre. + * @param doku RenderableMultiDoku, MultiDoku à afficher + * @param listSymbols List, liste des symboles à utiliser + * @param width int, largeur d'un bloc du sudoku + * @param height int, hauteur d'un bloc du sudoku + */ private void showMultiDoku(RenderableMultidoku doku, List listSymbols, int width, int height) { SudokuPrinter.printMultiDokuWithIndex(doku, listSymbols, width, height); } + /** + * Permet à l'utilisateur de sauvegarder l'état de son doku, soit dans un nouveau fichier + * de sauvegarde, soit en écrasant une sauvegarde précédente. + * @param doku MultiDoku, MultiDoku à sauvegarder + */ private void saveMultiDoku(MultiDoku doku) { System.out.println("Number of the file to overwrite ('-1' or unused save file number to create a new save) :"); int n = reader.nextInt(); @@ -219,6 +304,16 @@ public class ConsoleInterface { System.out.println("The path to your save is:" + path); } + /** + * Tour de jeu de l'utilisateur, présenté avec les choix de remplir une case du doku, + * de sauvegarder son état actuel dans un fichier de sauvegarde, + * de le résoudre tel qu'il est, + * ou de quitter l'application. + * @param doku MultiDoku, MultiDoku actuel + * @param listSymbols List, liste des symboles à utiliser + * @param width int, largeur d'un bloc du sudoku + * @param height int, hauteur d'un bloc du sudoku + */ private void turn(MultiDoku doku, List listSymbols, int width, int height) { System.out.println( "You can now put a number in a cell ('play', default), save the state of the doku ('save'), show a solution ('solution') or exit the program ('exit')."); @@ -238,10 +333,23 @@ public class ConsoleInterface { } } + /** + * Applique l'étape passée en paramètre. + * @param step SolverStep, étape à appliquer + */ private void applyStep(SolverStep step) { step.getCell().setSymbolIndex(step.getNewValue()); } + /** + * Permet d'afficher une étape de résolution du doku complété. + * @param doku MultiDoku, MultiDoku actuel + * @param listSymbols List, liste des symboles à utiliser + * @param width int, largeur d'un bloc du sudoku + * @param height int, hauteur d'un bloc du sudoku + * @param step SolverStep, étape de résolution à afficher + * @return + */ private boolean showStep(MultiDoku doku, List listSymbols, int width, int height, SolverStep step) { System.out.println("Here is the step : \n"); showMultidoku(doku, listSymbols, width, height); @@ -252,20 +360,32 @@ public class ConsoleInterface { return reader.next().equals("y"); } + /** + * Permet d'afficher les étapes de résolution du doku complété si l'utilisateur le souhaite. + * @param doku MultiDoku, MultiDoku actuel + * @param listSymbols List, liste des symboles à utiliser + * @param width int, largeur d'un bloc du sudoku + * @param height int, hauteur d'un bloc du sudoku + * @param steps List, liste des étapes de résolution + */ private void showSolveSteps(MultiDoku doku, List listSymbols, int width, int height, List steps) { System.out.println("Would you like to see the steps of the solver ? (y/n, default n)"); doku.getStateManager().popState(); - switch (reader.next()) { - case "y": - int stepCount = 0; - while(stepCount < steps.size() && showStep(doku, listSymbols, width, height, steps.get(stepCount))){stepCount++;} - break; - - default: - break; + if (reader.next().equalsIgnoreCase("y")){ + int stepCount = 0; + while(stepCount < steps.size() && showStep(doku, listSymbols, width, height, steps.get(stepCount))){ + stepCount++; + } } } + /** + * Résout le doku en fonction du solver que choisit l'utilisateur. + * @param doku MultiDoku, MultiDoku actuel + * @param listSymbols List, liste des symboles à utiliser + * @param width int, largeur d'un bloc du sudoku + * @param height int, hauteur d'un bloc du sudoku + */ private void solve(MultiDoku doku, List listSymbols, int width, int height){ System.out.println("Pick a solver to use : random ('random', default), human ('human') or mixed solver ('mixed')."); List steps = new ArrayList<>(); @@ -284,6 +404,14 @@ public class ConsoleInterface { showSolveSteps(doku, listSymbols, width, height, steps); } + /** + * Remplissage d'une Cell du doku en fonction des coordonnées et du symboles que + * l'utilisateur choisit. + * @param doku MultiDoku, MultiDoku actuel + * @param listSymbols List, liste des symboles à utiliser + * @param width int, largeur d'un bloc du sudoku + * @param height int, hauteur d'un bloc du sudoku + */ private void play(MultiDoku doku, List listSymbols, int width, int height) { int x, y; RenderableMultidoku rdoku = RenderableMultidoku.fromMultidoku(doku); @@ -304,22 +432,47 @@ public class ConsoleInterface { showMultiDoku(rdoku, listSymbols, width, height); } + /** + * Vérifie que la Cell identifiée par les coordonées x et y dans le RenderableMultiDOku fourni + * existe et est modifiable. + * @param doku RenderableMultiDoku, MultiDoku actuel + * @param width int, largeur d'un bloc du sudoku + * @param height int, hauteur d'un bloc du sudoku + * @param x int, abscisse de la Cell à vérifier + * @param y int, ordonnée de la Cell à vérifier + * @return Boolean true si la Cell aux coordonéees données peut être modifiée, false sinon + */ private boolean isValidCoordinates(RenderableMultidoku doku, int width, int height, int x, int y) { - if (doku.getCell(x, y) != null) { + Cell cell = doku.getCell(x, y); + if ((cell != null) && cell.isMutable()) { return true; } return false; } + /** + * Renvoie l'index du symbole passé en paramètre. + * @param symbol String, symbole dont on veut l'index + * @param listSymbols List, liste des symboles possibles + * @param nbSymbols int, nombre de symboles possibles + * @return int, index du symbole si celui-ci est valide, Cell.NOSYMBOL sinon. + */ private int indexOfSymbol(String symbol, List listSymbols, int nbSymbols) { for (int i = 0; i < nbSymbols; i++) { if (listSymbols.get(i).equals(symbol)) { return i; } } - return -1; + return Cell.NOSYMBOL; } + /** + * Vérifie que le symbol passé en paramètre est valide. + * @param symbol String, symbole dont on vérifie la validité + * @param listSymbols List, liste des symboles possibles + * @param size int, nombre de symboles possibles + * @return boolean, valant true si le symbole est valide, false sinon. + */ private boolean isValidSymbol(String symbol, List listSymbols, int size) { for (int i = 0; i < size; i++) { if (listSymbols.get(i).equals(symbol)) { @@ -329,6 +482,9 @@ public class ConsoleInterface { return false; } + /** + * Affiche un message d'aurevoir et ferme l'application. + */ private void exit() { System.out.println("Thank you for playing!"); System.exit(0);