Compare commits

..

17 commits
v0.1.1 ... main

Author SHA1 Message Date
136e4a8e69 commit 2024-03-29 15:42:21 +01:00
5016c1a888 commit 2024-03-29 11:20:32 +01:00
ae86967b79 commit 2024-03-29 10:56:13 +01:00
6c65f8d551 commit 2024-03-28 23:39:05 +01:00
bb09c5afca bug resolution 2024-03-28 23:33:35 +01:00
42746ad5b0 commit 2024-03-28 18:15:42 +01:00
2f51df0d82 commit 2024-03-28 15:31:02 +01:00
9afffd4297 very major improvements 2024-03-28 14:00:57 +01:00
3068c5ba94 major improvements 2024-03-28 12:00:57 +01:00
fc18dea7f4 improvements 2024-03-27 14:24:27 +01:00
491cd35136 commit 2024-03-27 13:42:19 +01:00
29ce62150e commit 2024-03-27 11:54:38 +01:00
b05b7cd13c hell + gui 2024-03-26 21:59:12 +01:00
4a63c7c01e added a new save 2024-03-23 22:26:01 +01:00
8dce30c382 commit 2024-03-23 22:25:48 +01:00
02e5e9c6c9 improvements 2024-03-20 11:58:16 +01:00
556869ebb8 commit 2024-03-13 11:57:49 +01:00
31 changed files with 1849 additions and 599 deletions

View file

@ -9,297 +9,315 @@ import java.util.Set;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import userInterface.UserInterface;
import universe.Universe;
import universe.Stack;
import universe.Situation;
public class AppLaser { public class AppLaser {
public static void main(String [] args) { public static void main(String [] args) {
boolean cli = false, optimize_duration = false; boolean cli = false, optimize_duration = false;
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++) {
switch (args[i]) { switch (args[i]) {
case "-cli": case "-cli":
cli = true; cli = true;
break; break;
case "--optimize-duration": case "--optimize-duration":
optimize_duration = true; optimize_duration = true;
break; break;
default: default:
System.out.println("Unknown argument " + args[i]); System.out.println("Unknown argument " + args[i]);
System.exit(0); System.exit(0);
} }
} }
int universe_width = 3;
int universe_height = 3;
int start_i = 0;
int start_j = 0;
int start_dir = 11;
int firstState_i = start_i;
int firstState_j = start_j;
int universe_width = 3; if (start_dir == 10) firstState_i = start_i - 1;
int universe_height = 3; else if (start_dir == 11) firstState_i = start_i + 1;
int start_i = 0; else if (start_dir == 12) firstState_j = start_j + 1;
int start_j = 0; else if (start_dir == 13) firstState_j = start_j - 1;
int start_dir = 11;
int firstState_i = start_i;
int firstState_j = start_j;
if (start_dir == 10) firstState_i = start_i - 1; if (cli == true) {
else if (start_dir == 11) firstState_i = start_i + 1; Stack <Situation> stack = new Stack <Situation>();
else if (start_dir == 12) firstState_j = start_j + 1; Universe universe = new Universe(universe_width + 2, universe_height + 2, start_i + 1, start_j + 1, start_dir);
else if (start_dir == 13) firstState_j = start_j - 1; Situation currentState = new Situation(firstState_i + 1, firstState_j + 1, start_dir, 0);
Scanner scanner = new Scanner(System.in);
if (cli == true) { int choice;
Stack <Situation> stack = new Stack <Situation>(); do {
Universe universe = new Universe(universe_width + 2, universe_height + 2, start_i + 1, start_j + 1, start_dir); // clear screen
Situation currentState = new Situation(firstState_i + 1, firstState_j + 1, start_dir, 0);
Scanner scanner = new Scanner(System.in); System.out.print("\033[H\033[2J");
System.out.flush();
System.out.print("\033[?25h");
int choice; // print the universe
do { Universe.print(universe.getGrid(), universe_width + 2, universe_height + 2, 2, 4);
// clear screen
System.out.print("\033[H\033[2J"); // print the menu
System.out.flush();
System.out.print("\033[?25h");
// print the universe System.out.println("\n1 - Resize universe");
System.out.println("2 - Change start position");
System.out.println("3 - Add obstacle");
System.out.println("4 - Reset universe");
System.out.println("5 - Reset obstacles");
System.out.println("6 - Save universe");
System.out.println("7 - Load universe");
System.out.println("8 - Resolve");
System.out.println("0 - Exit");
universe.print(2, 4); // prompt the user
// print the menu System.out.print("\nChoice : ");
choice = scanner.nextInt();
System.out.println("\n1 - Resize universe"); switch (choice) {
System.out.println("2 - Change start position");
System.out.println("3 - Add obstacle");
System.out.println("4 - Reset universe");
System.out.println("5 - Reset obstacles");
System.out.println("6 - Save universe");
System.out.println("7 - Load universe");
System.out.println("8 - Resolve");
System.out.println("0 - Exit");
// prompt the user case 1:
System.out.print("Enter the width of the universe : ");
universe_width = scanner.nextInt();
System.out.print("Enter the length of the universe : ");
universe_height = scanner.nextInt();
System.out.print("\nChoice : "); universe.changeUniverseDim(universe_width + 2, universe_height + 2);
choice = scanner.nextInt();
switch (choice) { break;
case 1: case 2:
System.out.print("Enter the width of the universe : "); System.out.print("Enter the position of the start point in the first axis : ");
universe_width = scanner.nextInt(); start_i = scanner.nextInt();
System.out.print("Enter the length of the universe : "); System.out.print("Enter the position of the start point in the seccond axis : ");
universe_height = scanner.nextInt(); start_j = scanner.nextInt();
System.out.print("Enter the direction of the start point : ");
start_dir = scanner.nextInt();
universe.changeUniverseDim(universe_width + 2, universe_height + 2); firstState_i = start_i;
firstState_j = start_j;
break; if (start_dir == 10) firstState_i = start_i - 1;
else if (start_dir == 11) firstState_i = start_i + 1;
else if (start_dir == 12) firstState_j = start_j + 1;
else if (start_dir == 13) firstState_j = start_j - 1;
case 2: currentState = new Situation(firstState_i + 1, firstState_j + 1, start_dir, 0);
System.out.print("Enter the position of the start point in the first axis : ");
start_i = scanner.nextInt();
System.out.print("Enter the position of the start point in the seccond axis : ");
start_j = scanner.nextInt();
System.out.print("Enter the direction of the start point : ");
start_dir = scanner.nextInt();
firstState_i = start_i; universe.changeUniverseStart(start_i + 1, start_j + 1, start_dir);
firstState_j = start_j;
if (start_dir == 10) firstState_i = start_i - 1; break;
else if (start_dir == 11) firstState_i = start_i + 1;
else if (start_dir == 12) firstState_j = start_j + 1;
else if (start_dir == 13) firstState_j = start_j - 1;
currentState = new Situation(firstState_i + 1, firstState_j + 1, start_dir, 0); case 3:
int firstPos_i, firstPos_j, seccondPos_i, seccondPos_j;
universe.changeUniverseStart(start_i + 1, start_j + 1, start_dir); System.out.print("\nFirst position of the obstacle i : ");
firstPos_i = scanner.nextInt();
System.out.print("First position of the obstacle j : ");
firstPos_j = scanner.nextInt();
System.out.print("Seccond position of the obstacle i : ");
seccondPos_i = scanner.nextInt();
System.out.print("Seccond position of the obstacle j : ");
seccondPos_j = scanner.nextInt();
break; for (int i = firstPos_i + 1; i < seccondPos_i + 2; i++) {
for (int j = firstPos_j + 1; j < seccondPos_j + 2; j++) {
universe.addObstacle(i, j);
}
}
case 3: break;
int firstPos_i, firstPos_j, seccondPos_i, seccondPos_j;
System.out.print("\nFirst position of the obstacle i : "); case 4:
firstPos_i = scanner.nextInt(); universe.resetUniverse();
System.out.print("First position of the obstacle j : ");
firstPos_j = scanner.nextInt();
System.out.print("Seccond position of the obstacle i : ");
seccondPos_i = scanner.nextInt();
System.out.print("Seccond position of the obstacle j : ");
seccondPos_j = scanner.nextInt();
for (int i = firstPos_i + 1; i < seccondPos_i + 2; i++) { break;
for (int j = firstPos_j + 1; j < seccondPos_j + 2; j++) {
universe.addObstacle(i, j);
}
}
break; case 5:
universe.resetUniverseObstacles();
case 4: break;
universe.resetUniverse();
break;
case 5: case 6:
universe.resetUniverseObstacles(); System.out.print("\nHow do you want to name your universe : ");
String name = "";
break; while (name.isEmpty()) {
name = scanner.nextLine();
}
universe.save(name);
case 6: break;
System.out.print("\nHow do you want to name your universe : ");
String name = "";
while (name.isEmpty()) { case 7:
name = scanner.nextLine();
}
universe.save(name); Set<String> files = Stream.of(new File("./saves").listFiles()).filter(file -> !file.isDirectory()).map(File::getName).collect(Collectors.toSet());
break; System.out.println("\nAvailable files : \n");
case 7: for (String element : files) {
System.out.println(element.replace(".txt", ""));
}
Set<String> files = Stream.of(new File("./saves").listFiles()).filter(file -> !file.isDirectory()).map(File::getName).collect(Collectors.toSet()); System.out.print("\nWhat universe do you want load ? : ");
String name2 = "";
System.out.println("\nAvailable files : \n"); while (name2.isEmpty()) {
name2 = scanner.nextLine();
}
for (String element : files) { try {
System.out.println(element.replace(".txt", "")); BufferedReader reader = new BufferedReader(new FileReader("./saves/" + name2 + ".txt"));
} universe_height = Integer.valueOf(reader.readLine());
universe_width = Integer.valueOf(reader.readLine());
start_dir = Integer.valueOf(reader.readLine());
start_i = Integer.valueOf(reader.readLine());
start_j = Integer.valueOf(reader.readLine());
System.out.print("\nWhat universe do you want load ? : ");
String name2 = "";
while (name2.isEmpty()) { universe.changeUniverseDim(universe_width + 2, universe_height + 2);
name2 = scanner.nextLine();
}
try { firstState_i = start_i;
BufferedReader reader = new BufferedReader(new FileReader("./saves/" + name2 + ".txt")); firstState_j = start_j;
universe_height = Integer.valueOf(reader.readLine());
universe_width = Integer.valueOf(reader.readLine());
start_dir = Integer.valueOf(reader.readLine());
start_i = Integer.valueOf(reader.readLine());
start_j = Integer.valueOf(reader.readLine());
if (start_dir == 10) firstState_i = start_i - 1;
else if (start_dir == 11) firstState_i = start_i + 1;
else if (start_dir == 12) firstState_j = start_j + 1;
else if (start_dir == 13) firstState_j = start_j - 1;
universe.changeUniverseDim(universe_width, universe_height); currentState = new Situation(firstState_i, firstState_j, start_dir, 0);
firstState_i = start_i; universe.changeUniverseStart(start_i, start_j, start_dir);
firstState_j = start_j;
if (start_dir == 10) firstState_i = start_i - 1; while (true) {
else if (start_dir == 11) firstState_i = start_i + 1; try {
else if (start_dir == 12) firstState_j = start_j + 1; int pos1 = Integer.valueOf(reader.readLine());
else if (start_dir == 13) firstState_j = start_j - 1; int pos2 = Integer.valueOf(reader.readLine());
currentState = new Situation(firstState_i, firstState_j, start_dir, 0); universe.addObstacle(pos1, pos2);
}
catch (Exception e) {
break;
}
}
}
catch (Exception e) {}
universe.changeUniverseStart(start_i, start_j, start_dir); break;
while (true) {
try {
int pos1 = Integer.valueOf(reader.readLine());
int pos2 = Integer.valueOf(reader.readLine());
universe.addObstacle(pos1, pos2); case 8:
} boolean display_progress = false, display_regress = false;
catch (Exception e) {
break;
}
}
}
catch (Exception e) {}
break; System.out.println("\n1 - display progress and regress");
System.out.println("2 - display progress");
System.out.println("3 - display regress");
System.out.println("4 - display nothing");
System.out.print("\nChoice : ");
choice = scanner.nextInt();
switch (choice) {
case 1:
display_progress = true;
display_regress = true;
break;
case 8: case 2:
boolean display_progress = false, display_regress = false; display_progress = true;
break;
System.out.println("\n1 - display progress and regress"); case 3:
System.out.println("2 - display progress"); display_regress = true;
System.out.println("3 - display regress"); break;
System.out.println("4 - display nothing");
System.out.print("\nChoice : ");
choice = scanner.nextInt();
switch (choice) { case 4:
case 1: break;
display_progress = true;
display_regress = true;
break;
case 2: default:
display_progress = true; break;
break; }
case 3: System.out.print("\033[?25l");
display_regress = true; System.out.print("\033[H\033[2J");
break; System.out.flush();
case 4: universe.resetUniverse();
break;
default: Universe.print(universe.getGrid(), universe_width + 2, universe_height + 2, 2, 4);
break;
}
System.out.print("\033[?25l"); int start_time = (int) Instant.now().getEpochSecond();
System.out.print("\033[H\033[2J");
System.out.flush();
universe.resetUniverse(); int [][] bestGrid = universe.copyGrid();
int best_filled_boxes = 0;
int best_nb_mirrors = 0;
universe.print(2, 4); do {
if (universe.canEvolve(currentState)) {
stack.push(currentState.copy(universe.possibleChoices(currentState)));
currentState = universe.evolve(currentState);
int start_time = (int) Instant.now().getEpochSecond(); if (display_progress == true) Universe.print(universe.getGrid(), universe_width + 2, universe_height + 2, universe_height + 6, 4);
while (!universe.isSolved()) { if ((universe.getFilledBoxes() > best_filled_boxes) || (universe.getFilledBoxes() == best_filled_boxes && universe.getNbMirrors() < best_nb_mirrors)) {
if (universe.canEvolve(currentState)) { bestGrid = universe.copyGrid();
stack.push(currentState.copy(universe.possibleChoices(currentState))); best_filled_boxes = universe.getFilledBoxes();
currentState = universe.evolve(currentState); best_nb_mirrors = universe.getNbMirrors();
if (display_progress == true) universe.print(universe_height + 6, 4); Universe.print(bestGrid, universe_width + 2, universe_height + 2, 2, 2 * universe_width + 10);
} System.out.println("Miroirs: " + best_nb_mirrors + " Cases: " + best_filled_boxes);
else if (stack.size() > 0) { }
currentState = stack.pop(); }
universe.reset(currentState); else if (stack.size() > 0) {
currentState = stack.pop();
universe.reset(currentState);
if (display_regress == true) universe.print(universe_height + 6, 4); if (display_regress == true) Universe.print(universe.getGrid(), universe_width + 2, universe_height + 2, universe_height + 6, 4);
} else { } else {
break; break;
} }
if ((int) Instant.now().getEpochSecond() - start_time > 60 && optimize_duration == true) { if ((int) Instant.now().getEpochSecond() - start_time > 60 && optimize_duration == true) {
display_progress = false; display_progress = false;
} }
if ((int) Instant.now().getEpochSecond() - start_time > 2 * 60 && optimize_duration == true) { if ((int) Instant.now().getEpochSecond() - start_time > 2 * 60 && optimize_duration == true) {
display_regress = false; display_regress = false;
} }
} } while (stack.size() != 0);
System.out.println("\n\n"); System.out.println("\n\n");
universe.print(universe_height + 6, 4); Universe.print(bestGrid, universe_width + 2, universe_height + 2, universe_height + 6, 4);
System.out.println("\nSolved in " + ((int) Instant.now().getEpochSecond() - start_time) + " secconds");
System.out.print("\033[?25h");
System.out.print("\nEnter anything to continue....");
scanner.nextInt();
System.out.println("\nSolved in " + ((int) Instant.now().getEpochSecond() - start_time) + " secconds"); break;
default:
break;
System.out.print("\033[?25h"); }
System.out.print("\nEnter anything to continue...."); } while (choice != 0);
scanner.nextInt(); }
else {
break; Universe universe = new Universe(universe_width + 2, universe_height + 2, start_i + 1, start_j + 1, start_dir);
UserInterface userInterface = new UserInterface(universe);
default: userInterface.start();
break; }
}
}
} while (choice != 0);
}
else {
System.out.println("there is no GUI yet.");
}
}
} }

View file

@ -1,373 +0,0 @@
// Antoine CRETUAL, Lukian LEIZOUR, 14/02/2024
import java.io.File;
import java.io.FileWriter;
public class Universe {
// Atributes
private int[][] grid;
private int width, height;
private int boxes_to_fill;
// Constructors
public Universe(int width, int height, int i_start, int j_start, int dir_start) {
this.grid = new int[height][width];
this.height = height;
this.width = width;
this.boxes_to_fill = (width - 2) * (height - 2) - 1;
int i, j;
for (i = 1; i < this.height - 1; i++) {
for (j = 1; j < this.width - 1; j++) {
this.grid[i][j] = 0;
}
}
for (i = 0; i < this.height; i++) {
this.grid[i][0] = -1;
this.grid[i][width - 1] = -1;
}
for (j = 0; j < this.width; j++) {
this.grid[0][j] = -1;
this.grid[height - 1][j] = -1;
}
this.grid[i_start][j_start] = dir_start;
}
// Methods
public void print(int pos_i, int pos_j) {
int i, j;
for (i = 0; i < this.height; i++) {
for (j = 0; j < this.width; j++) {
System.out.print("\033[" + (i + pos_i) + ";" + (j*2 + pos_j) + "H");
switch (this.grid[i][j]) {
case -1:
System.out.printf(" X");
break;
case 0:
System.out.printf(" ");
break;
case 1:
System.out.printf(" |");
break;
case 2:
System.out.printf(" -");
break;
case 3:
System.out.printf(" +");
break;
case 4:
System.out.printf(" /");
break;
case 5:
System.out.printf(" \\");
break;
case 10:
System.out.printf(" ^");
break;
case 11:
System.out.printf(" v");
break;
case 12:
System.out.printf(" >");
break;
case 13:
System.out.printf(" <");
break;
default:
System.out.printf("%2d", this.grid[i][j]);
}
}
System.out.print("\n");
}
}
public void resetUniverse() {
for (int i = 1; i < this.height - 1; i++) {
for (int j = 1; j < this.width - 1; j++) {
if (this.grid[i][j] != 10 && this.grid[i][j] != 11 && this.grid[i][j] != 12 && this.grid[i][j] != 13 && this.grid[i][j] != 0 && this.grid[i][j] != -1) {
this.grid[i][j] = 0;
}
}
}
}
public void resetUniverseObstacles() {
for (int i = 1; i < this.height - 1; i++) {
for (int j = 1; j < this.width - 1; j++) {
if (this.grid[i][j] != 10 && this.grid[i][j] != 11 && this.grid[i][j] != 12 && this.grid[i][j] != 13 && this.grid[i][j] != 0) {
this.grid[i][j] = 0;
}
}
}
this.boxes_to_fill = ((this.height - 2) * (this.width - 2)) - 1;
}
public void changeUniverseDim(int width, int height) {
int [][] newgrid = new int[width][height];
for (int i = 1; i < height - 1; i++) {
for (int j = 1; j < width - 1; j++) {
newgrid[i][j] = 0;
}
}
for (int i = 1; i < height - 1 && i < this.height - 1; i++) {
for (int j = 1; j < width - 1 && j < this.width - 1; j++) {
newgrid[i][j] = this.grid[i][j];
}
}
for (int i = 0; i < height; i++) {
newgrid[i][0] = -1;
newgrid[i][width - 1] = -1;
}
for (int j = 0; j < width; j++) {
newgrid[height - 1][j] = -1;
newgrid[0][j] = -1;
}
this.grid = newgrid;
this.width = width;
this.height = height;
this.boxes_to_fill = 0;
for (int i = 1; i < height - 1; i++) {
for (int j = 1; j < width - 1; j++) {
if (this.grid[i][j] == 0) {
this.boxes_to_fill ++;
}
}
}
}
public void changeUniverseStart(int pos_i, int pos_j, int dir) {
for (int i = 0; i < this.height; i++) {
for (int j = 0; j < this.width; j++) {
if (this.grid[i][j] == 10 || this.grid[i][j] == 11 || this.grid[i][j] == 12|| this.grid[i][j] == 13) {
this.grid[i][j] = 0;
}
}
}
this.grid[pos_i][pos_j] = dir;
}
public void addObstacle(int pos_i, int pos_j) {
if (this.grid[pos_i][pos_j] == 0) {
this.grid[pos_i][pos_j] = -1;
this.boxes_to_fill--;
}
else {}
}
public int possibleChoices(Situation s) {
int i = s.pos_i;
int j = s.pos_j;
int d = s.direction;
int c = s.nb_choix;
switch (c) {
case 0: {
switch (d) {
case 10: // north
if (this.grid[i - 1][j] == 0 || this.grid[i - 1][j] == 2) return 1; // front
else if (this.grid[i][j - 1] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i][j + 1] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 11: // south
if (this.grid[i + 1][j] == 0 || this.grid[i + 1][j] == 2) return 1; // front
else if (this.grid[i][j + 1] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i][j - 1] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 12: // east
if (this.grid[i][j + 1] == 0 || this.grid[i][j + 1] == 1) return 1; // front
else if (this.grid[i - 1][j] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i + 1][j] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 13: //west
if (this.grid[i][j - 1] == 0 || this.grid[i][j - 1] == 1) return 1; // front
else if (this.grid[i + 1][j] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i - 1][j] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
default: {}
}
}
case 1: {
switch (d) {
case 10: // north
if (this.grid[i][j - 1] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i][j + 1] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 11: // south
if (this.grid[i][j + 1] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i][j - 1] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 12: // east
if (this.grid[i - 1][j] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i + 1][j] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 13: //west
if (this.grid[i + 1][j] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i - 1][j] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
default: {}
}
}
case 2: {
switch (d) {
case 10: // north
if (this.grid[i][j + 1] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 11: // south
if (this.grid[i][j - 1] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 12: // east
if (this.grid[i + 1][j] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 13: //west
if (this.grid[i - 1][j] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
default: {}
}
}
case 3:
return -1;
default: return -1;
}
}
public boolean canEvolve(Situation s) {
return possibleChoices(s) != -1;
}
public Situation evolve(Situation s) {
int i = s.pos_i;
int j = s.pos_j;
int d = s.direction;
int c = possibleChoices(s);
// new status of the box
if (c == 1 && (d == 10 || d == 11)) {
if (this.grid[i][j] == 0) {
this.grid[i][j] = 1;
} else {
this.grid[i][j] = 3;
this.boxes_to_fill++;
}
}
if (c == 1 && (d == 12 || d == 13)) {
if (this.grid[i][j] == 0) {
this.grid[i][j] = 2;
} else {
this.grid[i][j] = 3;
this.boxes_to_fill++;
}
}
if ((c == 3 && d == 10) || (c == 3 && d == 11) || (c == 2 && d == 12) || (c == 2 && d == 13)) this.grid[i][j] = 4;
if ((c == 2 && d == 10) || (c == 2 && d == 11) || (c == 3 && d == 12) || (c == 3 && d == 13)) this.grid[i][j] = 5;
// changing the position of the situation
if (c == 1 && d == 10 || c == 2 && d == 12 || c == 3 && d == 13) {
i --;
d = 10;
}
else if (c == 1 && d == 11 || c == 2 && d == 13 || c == 3 && d == 12) {
i ++;
d = 11;
}
else if (c == 1 && d == 12 || c == 2 && d == 11 || c == 3 && d == 10) {
j ++;
d = 12;
}
else if (c == 1 && d == 13 || c == 2 && d == 10 || c == 3 && d == 11) {
j --;
d = 13;
}
this.boxes_to_fill--;
return new Situation(i, j, d, 0);
}
public void reset(Situation s) {
int i = s.pos_i;
int j = s.pos_j;
int d = s.direction;
if (this.grid[i][j] == 3) {
if (d == 10 || d == 11) {
this.grid[i][j] = 2;
} else {
this.grid[i][j] = 1;
}
} else {
this.grid[s.pos_i][s.pos_j] = 0;
this.boxes_to_fill++;
}
}
public boolean isSolved() {
return this.boxes_to_fill == 0;
}
public void save(String fileName) {
try {
File file = new File("./saves/" + fileName + ".txt");
file.createNewFile();
FileWriter writer = new FileWriter("./saves/" + fileName + ".txt");
writer.write(this.height + "\n" + this.width + "\n");
for (int i = 1; i < this.height - 1; i++) {
for (int j = 1; j < this.width - 1; j++) {
if (this.grid[i][j] == 10 || this.grid[i][j] == 11 || this.grid[i][j] == 12 || this.grid[i][j] == 13) writer.write(this.grid[i][j] + "\n" + i + "\n" + j + "\n");
}
}
for (int i = 1; i < this.height - 1; i++) {
for (int j = 1; j < this.width - 1; j++) {
if (this.grid[i][j] == -1) writer.write(i + "\n" + j + "\n");
}
}
writer.close();
}
catch (Exception e) {}
}
}

BIN
images/blade.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
images/crossLaser.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

BIN
images/horizontalLaser.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

BIN
images/miror1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 B

BIN
images/miror2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

BIN
images/miror3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 B

BIN
images/miror4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 B

BIN
images/new.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 B

BIN
images/open.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 B

BIN
images/save.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

BIN
images/startBot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

BIN
images/startLeft.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

BIN
images/startRight.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B

BIN
images/startUp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

BIN
images/verticalLaser.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

BIN
images/wall.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B

View file

@ -1,7 +1,17 @@
build: build:
javac --source 1.8 --target 1.8 universe/*.java
javac --source 1.8 --target 1.8 userInterface/*.java
javac --source 1.8 --target 1.8 AppLaser.java javac --source 1.8 --target 1.8 AppLaser.java
jar cfe AppLaser.jar AppLaser *.class jar cfe AppLaser.jar AppLaser *.class
run: run:
javac --source 1.8 --target 1.8 universe/*.java
javac --source 1.8 --target 1.8 userInterface/*.java
javac --source 1.8 --target 1.8 AppLaser.java javac --source 1.8 --target 1.8 AppLaser.java
java AppLaser -cli --optimize-duration java AppLaser -cli --optimize-duration
run_gui:
javac --source 1.8 --target 1.8 universe/*.java
javac --source 1.8 --target 1.8 userInterface/*.java
javac --source 1.8 --target 1.8 AppLaser.java
java AppLaser

View file

@ -1,5 +1,5 @@
5 3
5 3
11 11
1 1
1 1

187
saves/maze1.txt Normal file
View file

@ -0,0 +1,187 @@
10
20
11
1
1
1
2
1
6
1
10
1
14
1
18
1
20
2
2
2
4
2
6
2
8
2
10
2
12
2
14
2
16
2
18
2
20
3
2
3
4
3
6
3
8
3
10
3
12
3
14
3
16
3
18
3
20
4
2
4
4
4
6
4
8
4
10
4
12
4
14
4
16
4
18
4
20
5
2
5
4
5
6
5
8
5
10
5
12
5
14
5
16
5
18
5
20
6
2
6
4
6
6
6
8
6
10
6
12
6
14
6
16
6
18
6
20
7
2
7
4
7
6
7
8
7
10
7
12
7
14
7
16
7
18
7
20
8
2
8
4
8
6
8
8
8
10
8
12
8
14
8
16
8
18
8
20
9
2
9
4
9
6
9
8
9
10
9
12
9
14
9
16
9
18
9
20
10
4
10
8
10
12
10
16
10
20

155
saves/maze2.txt Normal file
View file

@ -0,0 +1,155 @@
10
20
11
1
1
1
2
1
6
1
10
1
14
1
18
1
20
2
2
2
4
2
6
2
7
2
8
2
10
2
12
2
13
2
14
2
15
2
16
2
18
2
20
3
4
3
18
4
2
4
4
4
5
4
6
4
8
4
9
4
10
4
12
4
14
4
16
4
18
4
19
4
20
5
12
5
14
6
2
6
4
6
6
6
7
6
8
6
10
6
11
6
12
6
14
6
15
6
16
6
18
6
19
6
20
7
1
7
2
8
2
8
4
8
6
8
8
8
10
8
11
8
12
8
13
8
14
8
16
8
17
8
18
8
20
9
4
9
12
9
16
9
18
10
3
10
4
10
8
10
12
10
16
10
20

83
saves/prof.txt Normal file
View file

@ -0,0 +1,83 @@
13
20
10
9
1
2
6
2
9
2
10
2
13
2
14
2
15
2
16
2
17
3
3
3
4
3
5
3
6
3
9
3
10
4
19
5
19
6
3
6
4
6
5
6
8
6
9
6
11
6
14
6
15
6
16
7
3
7
8
7
14
8
3
8
8
8
14
9
3
9
8
9
9
9
12
9
13
9
14
10
3
11
3

View file

@ -1,5 +1,5 @@
12 10
12 10
10 10
6 6
1 1

147
saves/roux.txt Normal file
View file

@ -0,0 +1,147 @@
20
13
10
20
3
1
1
2
1
2
3
2
12
3
1
3
3
3
12
4
3
4
12
5
3
5
12
6
3
6
4
6
5
6
6
6
7
6
8
6
9
6
10
6
12
7
12
8
12
9
7
9
8
9
9
9
12
10
5
10
9
10
11
10
12
11
2
11
3
11
9
12
2
13
2
14
2
14
12
15
2
15
5
15
6
15
7
15
8
15
9
15
10
15
11
15
12
16
2
16
4
16
5
16
6
16
7
16
8
16
9
16
10
16
11
16
12
17
2
18
2
18
5
18
9
18
10
18
11
18
12
19
5
19
8
19
9
19
10
19
11
19
12
20
1
20
5

View file

@ -1,5 +1,7 @@
// Antoine CRETUAL, Lukian LEIZOUR, 21/02/2024 // Antoine CRETUAL, Lukian LEIZOUR, 21/02/2024
package universe;
public class Situation { public class Situation {
// Atributes // Atributes

View file

@ -1,5 +1,7 @@
// Antoine CRETUAL, Lukian LEIZOUR, 21/02/2024 // Antoine CRETUAL, Lukian LEIZOUR, 21/02/2024
package universe;
import java.util.Vector; import java.util.Vector;
public class Stack <T> { public class Stack <T> {
@ -13,6 +15,10 @@ public class Stack <T> {
array = new Vector<T>(); array = new Vector<T>();
} }
public Stack(Vector<T> array) {
array = array;
}
// Methods // Methods
public void push(T x) { public void push(T x) {
@ -28,4 +34,8 @@ public class Stack <T> {
public int size() { public int size() {
return this.array.size(); return this.array.size();
} }
public Stack copy() {
return new Stack(new Vector<T>(this.array));
}
} }

431
universe/Universe.java Normal file
View file

@ -0,0 +1,431 @@
// Antoine CRETUAL, Lukian LEIZOUR, 14/02/2024
package universe;
import java.io.File;
import java.io.FileWriter;
public class Universe {
// Atributes
private int[][] grid;
private int width, height;
private int start_i, start_j;
private int filled_boxes;
private int nb_mirors;
private String name;
// Constructors
public Universe(int width, int height, int i_start, int j_start, int dir_start) {
this.grid = new int[height][width];
this.height = height;
this.width = width;
this.start_i = i_start;
this.start_j = j_start;
this.filled_boxes = 0;
this.nb_mirors = 0;
int i, j;
for (i = 1; i < this.height - 1; i++) {
for (j = 1; j < this.width - 1; j++) {
this.grid[i][j] = 0;
}
}
for (i = 0; i < this.height; i++) {
this.grid[i][0] = -1;
this.grid[i][width - 1] = -1;
}
for (j = 0; j < this.width; j++) {
this.grid[0][j] = -1;
this.grid[height - 1][j] = -1;
}
this.grid[i_start][j_start] = dir_start;
}
// Methods
public static void print(int [][] tab, int width, int height, int pos_i, int pos_j) {
int i, j;
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
System.out.print("\033[" + (i + pos_i) + ";" + (j*2 + pos_j) + "H");
switch (tab[i][j]) {
case -1:
System.out.printf(" X");
break;
case 0:
System.out.printf(" ");
break;
case 1:
System.out.printf(" |");
break;
case 2:
System.out.printf(" -");
break;
case 3:
System.out.printf(" +");
break;
case 4:
System.out.printf(" /");
break;
case 5:
System.out.printf(" /");
break;
case 6:
System.out.printf(" \\");
break;
case 7:
System.out.printf(" \\");
break;
case 10:
System.out.printf(" ^");
break;
case 11:
System.out.printf(" v");
break;
case 12:
System.out.printf(" >");
break;
case 13:
System.out.printf(" <");
break;
default:
System.out.printf("%2d", tab[i][j]);
}
}
System.out.print("\n");
}
}
public void resetUniverse() {
for (int i = 1; i < this.height - 1; i++) {
for (int j = 1; j < this.width - 1; j++) {
if (this.grid[i][j] != 10 && this.grid[i][j] != 11 && this.grid[i][j] != 12 && this.grid[i][j] != 13 && this.grid[i][j] != 0 && this.grid[i][j] != -1) {
this.grid[i][j] = 0;
}
}
}
}
public void resetUniverseObstacles() {
for (int i = 1; i < this.height - 1; i++) {
for (int j = 1; j < this.width - 1; j++) {
if (this.grid[i][j] != 10 && this.grid[i][j] != 11 && this.grid[i][j] != 12 && this.grid[i][j] != 13 && this.grid[i][j] != 0) {
this.grid[i][j] = 0;
}
}
}
}
public void changeUniverseDim(int width, int height) {
int [][] newgrid = new int[height][width];
for (int i = 1; i < height - 1; i++) {
for (int j = 1; j < width - 1; j++) {
newgrid[i][j] = 0;
}
}
for (int i = 1; i < height - 1 && i < this.height - 1; i++) {
for (int j = 1; j < width - 1 && j < this.width - 1; j++) {
newgrid[i][j] = this.grid[i][j];
}
}
for (int i = 0; i < height; i++) {
newgrid[i][0] = -1;
newgrid[i][width - 1] = -1;
}
for (int j = 0; j < width; j++) {
newgrid[height - 1][j] = -1;
newgrid[0][j] = -1;
}
this.grid = newgrid;
this.width = width;
this.height = height;
}
public void changeUniverseStart(int pos_i, int pos_j, int dir) {
this.grid[this.start_i][start_j] = 0;
this.grid[pos_i][pos_j] = dir;
this.start_i = pos_i;
this.start_j = pos_j;
}
public void addObstacle(int pos_i, int pos_j) {
if (this.grid[pos_i][pos_j] == 0) {
this.grid[pos_i][pos_j] = -1;
}
else {}
}
public void removeObstacle(int pos_i, int pos_j) {
if (this.grid[pos_i][pos_j] == -1) {
this.grid[pos_i][pos_j] = 0;
}
else {}
}
public int possibleChoices(Situation s) {
int i = s.pos_i;
int j = s.pos_j;
int d = s.direction;
int c = s.nb_choix;
switch (c) {
case 0: {
switch (d) {
case 10: // north
if (this.grid[i - 1][j] == 0 || this.grid[i - 1][j] == 2) return 1; // front
else if (this.grid[i][j - 1] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i][j + 1] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 11: // south
if (this.grid[i + 1][j] == 0 || this.grid[i + 1][j] == 2) return 1; // front
else if (this.grid[i][j + 1] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i][j - 1] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 12: // east
if (this.grid[i][j + 1] == 0 || this.grid[i][j + 1] == 1) return 1; // front
else if (this.grid[i - 1][j] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i + 1][j] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 13: //west
if (this.grid[i][j - 1] == 0 || this.grid[i][j - 1] == 1) return 1; // front
else if (this.grid[i + 1][j] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i - 1][j] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
default: {}
}
}
case 1: {
switch (d) {
case 10: // north
if (this.grid[i][j - 1] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i][j + 1] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 11: // south
if (this.grid[i][j + 1] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i][j - 1] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 12: // east
if (this.grid[i - 1][j] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i + 1][j] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 13: //west
if (this.grid[i + 1][j] == 0 && this.grid[i][j] == 0) return 2; // left
else if (this.grid[i - 1][j] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
default: {}
}
}
case 2: {
switch (d) {
case 10: // north
if (this.grid[i][j + 1] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 11: // south
if (this.grid[i][j - 1] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 12: // east
if (this.grid[i + 1][j] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
case 13: //west
if (this.grid[i - 1][j] == 0 && this.grid[i][j] == 0) return 3; // right
else return -1; // back
default: {}
}
}
case 3:
return -1;
default: return -1;
}
}
public boolean canEvolve(Situation s) {
return possibleChoices(s) != -1;
}
public Situation evolve(Situation s) {
int i = s.pos_i;
int j = s.pos_j;
int d = s.direction;
int c = possibleChoices(s);
// new status of the box
if (c == 1 && (d == 10 || d == 11)) {
if (this.grid[i][j] == 0) {
this.grid[i][j] = 1;
this.filled_boxes ++;
} else {
this.grid[i][j] = 3;
}
}
if (c == 1 && (d == 12 || d == 13)) {
if (this.grid[i][j] == 0) {
this.grid[i][j] = 2;
this.filled_boxes ++;
} else {
this.grid[i][j] = 3;
}
}
if ((c == 3 && d == 10) || (c == 2 && d == 13)) {
this.grid[i][j] = 4;
this.filled_boxes ++;
this.nb_mirors ++;
}
if ((c == 2 && d == 12) || (c == 3 && d == 11)) {
this.grid[i][j] = 5;
this.filled_boxes ++;
this.nb_mirors ++;
}
if ((c == 2 && d == 10) || (c == 3 && d == 12)) {
this.grid[i][j] = 6;
this.filled_boxes ++;
this.nb_mirors ++;
}
if ((c == 2 && d == 11) || (c == 3 && d == 13)) {
this.grid[i][j] = 7;
this.filled_boxes ++;
this.nb_mirors ++;
}
// changing the position of the situation
if (c == 1 && d == 10 || c == 2 && d == 12 || c == 3 && d == 13) {
i --;
d = 10;
}
else if (c == 1 && d == 11 || c == 2 && d == 13 || c == 3 && d == 12) {
i ++;
d = 11;
}
else if (c == 1 && d == 12 || c == 2 && d == 11 || c == 3 && d == 10) {
j ++;
d = 12;
}
else if (c == 1 && d == 13 || c == 2 && d == 10 || c == 3 && d == 11) {
j --;
d = 13;
}
return new Situation(i, j, d, 0);
}
public void reset(Situation s) {
int i = s.pos_i;
int j = s.pos_j;
int d = s.direction;
if (this.grid[i][j] == 3) {
if (d == 10 || d == 11) {
this.grid[i][j] = 2;
} else {
this.grid[i][j] = 1;
}
} else {
if (this.grid[i][j] == 4 || this.grid[i][j] == 5 || this.grid[i][j] == 6 || this.grid[i][j] == 7) {this.nb_mirors--;}
this.filled_boxes--;
this.grid[i][j] = 0;
}
}
public void save(String fileName) {
try {
File file = new File("./saves/" + fileName + ".txt");
file.createNewFile();
FileWriter writer = new FileWriter("./saves/" + fileName + ".txt");
writer.write((this.height - 2) + "\n" + (this.width - 2) + "\n");
for (int i = 1; i < this.height - 1; i++) {
for (int j = 1; j < this.width - 1; j++) {
if (this.grid[i][j] == 10 || this.grid[i][j] == 11 || this.grid[i][j] == 12 || this.grid[i][j] == 13) writer.write(this.grid[i][j] + "\n" + i + "\n" + j + "\n");
}
}
for (int i = 1; i < this.height - 1; i++) {
for (int j = 1; j < this.width - 1; j++) {
if (this.grid[i][j] == -1) writer.write(i + "\n" + j + "\n");
}
}
writer.close();
}
catch (Exception e) {}
}
public int getFilledBoxes() {
return this.filled_boxes;
}
public int getNbMirrors() {
return this.nb_mirors;
}
public int[][] getGrid() {
return this.grid;
}
public int[][] copyGrid() {
int [][] newGrid = new int[this.height][this.width];
for (int i = 0; i < this.height; i++) {
for (int j = 0; j < this.width; j++) {
newGrid[i][j] = this.grid[i][j];
}
}
return newGrid;
}
public int getWidth() {
return this.width;
}
public int getHeight() {
return this.height;
}
public int[] getStartCoords() {
int [] tab = new int[2];
tab[0] = this.start_i;
tab[1] = this.start_j;
return tab;
}
}

291
userInterface/Grid.java Normal file
View file

@ -0,0 +1,291 @@
package userInterface;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridLayout;
import java.awt.Insets;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import java.net.URL;
import universe.Universe;
import universe.Stack;
import universe.Situation;
import java.time.Instant;
public class Grid extends JPanel {
private int width;
private int height;
private JButton[][] mat;
private int selected;
private Universe universe;
private int button_width, button_height;
private int refreshRate;
private boolean solving;
private int display;
public Grid(int width, int height, Universe universe, int refreshRate, int display) {
super(new GridLayout(height, width));
this.width = width;
this.height = height;
this.selected = 0;
this.universe = universe;
this.button_width = 600 / this.height;
this.button_height = button_width;
this.refreshRate = refreshRate;
this.solving = false;
this.display = display;
this.mat = new JButton[height][width];
for (int i = 0; i < this.height; i++) {
for (int j = 0; j < this.width; j++) {
this.mat[i][j] = new JButton();
this.mat[i][j].setPreferredSize(new Dimension(this.button_width, this.button_height));
final int coord_i = i;
final int coord_j = j;
this.mat[i][j].addActionListener(e -> {
if (solving) {
return;
}
this.universe.resetUniverse();
switch (this.universe.getGrid()[coord_i + 1][coord_j + 1]) {
case 0:
if (this.selected == 1) {
this.universe.changeUniverseStart(coord_i + 1, coord_j + 1, 10);
break;
}
this.universe.addObstacle(coord_i + 1, coord_j + 1);
break;
case -1:
this.universe.removeObstacle(coord_i + 1, coord_j + 1);
break;
case 10:
if (this.selected == 1) {
this.universe.changeUniverseStart(coord_i + 1, coord_j + 1, 11);
break;
}
break;
case 11:
if (this.selected == 1) {
this.universe.changeUniverseStart(coord_i + 1, coord_j + 1, 12);
break;
}
break;
case 12:
if (this.selected == 1) {
this.universe.changeUniverseStart(coord_i + 1, coord_j + 1, 13);
break;
}
break;
case 13:
if (this.selected == 1) {
this.universe.changeUniverseStart(coord_i + 1, coord_j + 1, 10);
break;
}
break;
}
this.printUniverseGrid(this.universe.getGrid());
});
super.add(this.mat[i][j]);
}
}
this.printUniverseGrid(this.universe.getGrid());
}
public void setSelected(int selected) {
this.selected = selected;
}
public void setRefreshRate(int refreshRate) {
this.refreshRate = refreshRate;
}
public void setSolving(boolean solving) {
this.solving = solving;
}
public void setDisplay(int display) {
this.display = display;
}
public void printUniverseGrid(int [][] universeGrid) {
for (int i = 0; i < this.height; i++) {
for (int j = 0; j < this.width; j ++) {
Image photo;
switch (universeGrid[i + 1][j + 1]) {
case -1:
this.changeButtonState(i, j, "../images/wall.png");
break;
case 0:
this.changeButtonState(i, j, null);
break;
case 1:
this.changeButtonState(i, j, "../images/verticalLaser.png");
break;
case 2:
this.changeButtonState(i, j, "../images/horizontalLaser.png");
break;
case 3:
this.changeButtonState(i, j, "../images/crossLaser.png");
break;
case 4:
this.changeButtonState(i, j, "../images/miror1.png");
break;
case 5:
this.changeButtonState(i, j, "../images/miror2.png");
break;
case 6:
this.changeButtonState(i, j, "../images/miror3.png");
break;
case 7:
this.changeButtonState(i, j, "../images/miror4.png");
break;
case 10:
this.changeButtonState(i, j, "../images/startUp.png");
break;
case 11:
this.changeButtonState(i, j, "../images/startBot.png");
break;
case 12:
this.changeButtonState(i, j, "../images/startRight.png");
break;
case 13:
this.changeButtonState(i, j, "../images/startLeft.png");
break;
}
}
}
}
public void changeButtonState(int coord_i, int coord_j, String url) {
if (url == null) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
mat[coord_i][coord_j].setBackground(Color.WHITE);
mat[coord_i][coord_j].setIcon(null);
}
});
t.start();
} else {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
Image image = new ImageIcon(getClass().getResource(url)).getImage().getScaledInstance(button_width, button_height, Image.SCALE_SMOOTH);
mat[coord_i][coord_j].setIcon(new ImageIcon(image));
}
});
t.start();
}
}
public void reset() {
this.universe.resetUniverse();
this.printUniverseGrid(this.universe.getGrid());
}
public void alert(String message) {
JOptionPane.showMessageDialog(this, message);
}
public void solve() {
this.universe.resetUniverse();
final Universe universe = this.universe;
this.solving = true;
Thread computeThread = new Thread(new Runnable() {
int [][] bestGrid;
@Override
public void run() {
int [] startCoords = universe.getStartCoords();
int firstState_i = startCoords[0];
int firstState_j = startCoords[1];
int start_dir = universe.getGrid()[startCoords[0]][startCoords[1]];
if (start_dir == 10) firstState_i = firstState_i - 1;
else if (start_dir == 11) firstState_i = firstState_i + 1;
else if (start_dir == 12) firstState_j = firstState_j + 1;
else if (start_dir == 13) firstState_j = firstState_j - 1;
Stack <Situation> stack = new Stack <Situation>();
Situation currentState = new Situation(firstState_i, firstState_j, start_dir, 0);
this.bestGrid = universe.copyGrid();
int best_filled_boxes = 0;
int best_nb_mirrors = 0;
long start = Instant.now().toEpochMilli();
long lastRefresh = start;
do {
if (universe.canEvolve(currentState)) {
stack.push(currentState.copy(universe.possibleChoices(currentState)));
currentState = universe.evolve(currentState);
if (display == 1 && Instant.now().toEpochMilli() - lastRefresh > refreshRate) {
lastRefresh = Instant.now().toEpochMilli();
printUniverseGrid(universe.getGrid());
}
if ((universe.getFilledBoxes() > best_filled_boxes) || (universe.getFilledBoxes() == best_filled_boxes && universe.getNbMirrors() < best_nb_mirrors)) {
this.bestGrid = universe.copyGrid();
best_filled_boxes = universe.getFilledBoxes();
best_nb_mirrors = universe.getNbMirrors();
if (display == 2 && Instant.now().toEpochMilli() - lastRefresh > refreshRate) {
lastRefresh = Instant.now().toEpochMilli();
printUniverseGrid(this.bestGrid);
}
}
}
else if (stack.size() > 0) {
currentState = stack.pop();
universe.reset(currentState);
} else {
break;
}
if (display == 0 && Instant.now().toEpochMilli() - lastRefresh > refreshRate) {
lastRefresh = Instant.now().toEpochMilli();
printUniverseGrid(universe.getGrid());
}
} while (stack.size() != 0 && solving == true);
printUniverseGrid(bestGrid);
solving = false;
String message = "Solved in " + ((Instant.now().toEpochMilli() - start)/1000) + "s and " + ((Instant.now().toEpochMilli() - start)%1000) + "ms \nMirrors : " + best_nb_mirrors + "\nLaser length : " + best_filled_boxes;
alert(message);
}
});
computeThread.start();
}
}

View file

@ -0,0 +1,14 @@
package userInterface;
import universe.*;
public class UserInterface extends Thread {
private Window window;
public UserInterface(Universe universe) {
window = new Window(universe);
}
public void run() {
}
}

275
userInterface/Window.java Normal file
View file

@ -0,0 +1,275 @@
package userInterface;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridLayout;
import java.awt.Insets;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.File;
import java.util.Set;
import java.util.stream.Stream;
import java.util.stream.Collectors;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import java.net.URL;
import universe.Universe;
public class Window extends JFrame {
private JPanel panel;
private JMenuBar menuBar;
private Grid grid;
private Universe universe;
public Window(Universe universe) {
super("Laser Finder");
this.universe = universe;
panel = new JPanel();
panel.setPreferredSize(new Dimension(1000,800));
panel.setBackground(Color.decode("#EBEBD3"));
menuBar = new JMenuBar();
JMenu fichierMenu = new JMenu("File");
JMenu aideMenu = new JMenu("Help");
JMenu toolsMenu = new JMenu("Tools");
JMenu solveMenu = new JMenu("Solve");
JMenu displayMenu = new JMenu("Display");
JMenu refreshRate = new JMenu("Refresh Rate");
URL newUrl = getClass().getResource("../images/new.png");
URL openUrl = getClass().getResource("../images/open.png");
URL saveUrl = getClass().getResource("../images/save.png");
ImageIcon nouveauIcon = new ImageIcon(newUrl.getPath());
ImageIcon openIcon = new ImageIcon(openUrl.getPath());
ImageIcon saveIcon = new ImageIcon(saveUrl.getPath());
JMenuItem nouveauItem = new JMenuItem("New", nouveauIcon);
JMenuItem ouvrirItem = new JMenuItem("Open", openIcon);
JMenuItem enregistrerItem = new JMenuItem("Save", saveIcon);
JMenuItem apropos = new JMenuItem("About");
JMenuItem regles = new JMenuItem("Rules");
JRadioButtonMenuItem radioWall = new JRadioButtonMenuItem("Wall");
JRadioButtonMenuItem radioStart = new JRadioButtonMenuItem("Start");
radioWall.setSelected(true);
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(radioWall);
buttonGroup.add(radioStart);
JMenuItem changeSize = new JMenuItem("Change Size");
JMenuItem reset = new JMenuItem("Reset");
JMenuItem solve = new JMenuItem("Start");
JMenuItem stop = new JMenuItem("Stop");
JRadioButtonMenuItem radio10ms = new JRadioButtonMenuItem("10ms");
JRadioButtonMenuItem radio200ms = new JRadioButtonMenuItem("200ms");
JRadioButtonMenuItem radio500ms = new JRadioButtonMenuItem("500ms");
JRadioButtonMenuItem radio1000ms = new JRadioButtonMenuItem("1000ms");
radio10ms.setSelected(true);
ButtonGroup refreshRates = new ButtonGroup();
refreshRates.add(radio10ms);
refreshRates.add(radio200ms);
refreshRates.add(radio500ms);
refreshRates.add(radio1000ms);
JMenuItem displayAll = new JMenuItem("Display progress and regress");
JMenuItem displayProgress = new JMenuItem("Display only progress");
JMenuItem displayBest = new JMenuItem("Display best grid");
fichierMenu.add(nouveauItem);
fichierMenu.add(ouvrirItem);
fichierMenu.add(enregistrerItem);
aideMenu.add(apropos);
aideMenu.add(regles);
toolsMenu.add(radioWall);
toolsMenu.add(radioStart);
toolsMenu.addSeparator();
toolsMenu.add(changeSize);
toolsMenu.addSeparator();
toolsMenu.add(reset);
solveMenu.add(solve);
solveMenu.add(stop);
refreshRate.add(radio10ms);
refreshRate.add(radio200ms);
refreshRate.add(radio500ms);
refreshRate.add(radio1000ms);
displayMenu.add(refreshRate);
displayMenu.addSeparator();
displayMenu.add(displayAll);
displayMenu.add(displayProgress);
displayMenu.add(displayBest);
menuBar.add(fichierMenu);
menuBar.add(aideMenu);
menuBar.add(toolsMenu);
menuBar.add(solveMenu);
menuBar.add(displayMenu);
nouveauItem.addActionListener(e -> {
this.universe.changeUniverseStart(1, 1, 11);
this.universe.changeUniverseDim(5, 5);
this.universe.resetUniverseObstacles();
this.panel.remove(this.grid);
this.grid = new Grid(3, 3, this.universe, 10, 0);
this.panel.add(this.grid);
super.pack();
super.repaint();
});
enregistrerItem.addActionListener(e -> {
String name = JOptionPane.showInputDialog("Choose the universe name");
this.universe.save(name);
});
ouvrirItem.addActionListener(e -> {
String message = "Choose the universe among those : ";
Set<String> files = Stream.of(new File("./saves").listFiles()).filter(file -> !file.isDirectory()).map(File::getName).collect(Collectors.toSet());
for (String element : files) {
message += "\n- " + element.replace(".txt", "");
}
String name = JOptionPane.showInputDialog(message);
try {
BufferedReader reader = new BufferedReader(new FileReader("./saves/" + name + ".txt"));
int universe_height = Integer.valueOf(reader.readLine());
int universe_width = Integer.valueOf(reader.readLine());
int start_dir = Integer.valueOf(reader.readLine());
int start_i = Integer.valueOf(reader.readLine());
int start_j = Integer.valueOf(reader.readLine());
this.universe.changeUniverseDim(universe_width + 2, universe_height + 2);
this.universe.changeUniverseStart(start_i, start_j, start_dir);
this.universe.resetUniverseObstacles();
while (true) {
try {
int pos1 = Integer.valueOf(reader.readLine());
int pos2 = Integer.valueOf(reader.readLine());
this.universe.addObstacle(pos1, pos2);
}
catch (Exception error) {
break;
}
}
this.panel.remove(this.grid);
this.grid = new Grid(universe_width, universe_height, this.universe, 10, 0);
this.panel.add(this.grid);
super.pack();
super.repaint();
}
catch (Exception error) {}
});
regles.addActionListener(e -> {
JOptionPane.showMessageDialog(this, "Définissez la taille du plateau ainsi que l'orientation du laser, enfin ajoutez des obstacles et laissez le programme trouver le bon chemin !");
});
changeSize.addActionListener(e -> {
int width = Integer.valueOf(JOptionPane.showInputDialog("Choose the width"));
int height = Integer.valueOf(JOptionPane.showInputDialog("Choose the height"));
this.universe.changeUniverseDim(width + 2, height + 2);
this.panel.remove(this.grid);
this.grid = new Grid(width, height, this.universe, 10, 0);
this.panel.add(this.grid);
super.pack();
super.repaint();
});
radioWall.addActionListener(e -> {
this.grid.setSelected(0);
});
radioStart.addActionListener(e -> {
this.grid.setSelected(1);
});
solve.addActionListener(e -> {
this.grid.solve();
});
stop.addActionListener(e -> {
this.grid.setSolving(false);
});
reset.addActionListener(e -> {
this.grid.reset();
});
radio10ms.addActionListener(e -> {
this.grid.setRefreshRate(10);
});
radio200ms.addActionListener(e -> {
this.grid.setRefreshRate(200);
});
radio500ms.addActionListener(e -> {
this.grid.setRefreshRate(500);
});
radio1000ms.addActionListener(e -> {
this.grid.setRefreshRate(1000);
});
displayAll.addActionListener(e -> {
this.grid.setDisplay(0);
});
displayProgress.addActionListener(e -> {
this.grid.setDisplay(1);
});
displayBest.addActionListener(e -> {
this.grid.setDisplay(2);
});
this.grid = new Grid(this.universe.getHeight() - 2, this.universe.getWidth() - 2, this.universe, 10, 0);
this.panel.add(grid, BorderLayout.CENTER);
super.setJMenuBar(menuBar);
super.setContentPane(this.panel);
super.setLocationRelativeTo(null);
super.setLocation(1000, 400);
super.pack();
super.setVisible(true);
super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}