rebase ff
Merge conflicts
This commit is contained in:
parent
21e2bdb163
commit
0e01163567
7
.idea/.gitignore
generated
vendored
7
.idea/.gitignore
generated
vendored
@ -1,8 +1 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
|
124
.idea/uiDesigner.xml
generated
124
.idea/uiDesigner.xml
generated
@ -1,124 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
12
.vscode/launch.json
vendored
Normal file
12
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Labyrinthe",
|
||||
"request": "launch",
|
||||
"mainClass": "Main",
|
||||
"projectName": "SAE21_2022_c8f95a52"
|
||||
}
|
||||
]
|
||||
}
|
10
Makefile
10
Makefile
@ -1,3 +1,11 @@
|
||||
# If the first argument is "run"...
|
||||
ifeq (run,$(firstword $(MAKECMDGOALS)))
|
||||
# use the rest as arguments for "run"
|
||||
RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
|
||||
# ...and turn them into do-nothing targets
|
||||
$(eval $(RUN_ARGS):;@:)
|
||||
endif
|
||||
|
||||
### VARIABLES ###
|
||||
|
||||
JC = javac
|
||||
@ -21,7 +29,7 @@ $(OUTDIR)/Main.class : $(OFILES)
|
||||
### REGLES OPTIONNELLES ###
|
||||
|
||||
run : $(OUTDIR)/Main.class
|
||||
${JVM} ${JVMFLAGS} -cp $(OUTDIR) Main
|
||||
${JVM} ${JVMFLAGS} -cp $(OUTDIR) Main $(RUN_ARGS)
|
||||
|
||||
clean :
|
||||
-rm -rf $(OUTDIR)
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<component name="NewModuleRootManager">
|
||||
<output url="file://$MODULE_DIR$/out" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
|
@ -10,8 +10,4 @@ public interface Algo {
|
||||
*/
|
||||
void nextMove();
|
||||
|
||||
/**
|
||||
* Resets the algorithm
|
||||
*/
|
||||
void reset();
|
||||
}
|
||||
|
17
src/AlgoType.java
Normal file
17
src/AlgoType.java
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Enum for the different types of algorithms
|
||||
* @version 1.0
|
||||
* @author Amir Daouadi
|
||||
* @author Lyanis Souidi
|
||||
*/
|
||||
public enum AlgoType {
|
||||
/**
|
||||
* The random algorithm
|
||||
*/
|
||||
RANDOM,
|
||||
|
||||
/**
|
||||
* The deterministic algorithm
|
||||
*/
|
||||
DETERMINISTIC,
|
||||
}
|
98
src/AutoSimulation.java
Normal file
98
src/AutoSimulation.java
Normal file
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* This class is used to store the data of the auto simulations
|
||||
* @version 1.0
|
||||
* @author Amir Daouadi
|
||||
* @author Lyanis Souidi
|
||||
*/
|
||||
public class AutoSimulation {
|
||||
/**
|
||||
* The grid to use for the simulations
|
||||
*/
|
||||
private final Grid grid;
|
||||
|
||||
/**
|
||||
* The algorithm type to use for the simulations
|
||||
*/
|
||||
private final AlgoType algoType;
|
||||
|
||||
/**
|
||||
* The simulations
|
||||
*/
|
||||
private final Simulation[] simulations = new Simulation[100];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param grid The grid to use for the simulations
|
||||
* @param algoType The algorithm type to use for the simulations
|
||||
*/
|
||||
public AutoSimulation(Grid grid, AlgoType algoType) {
|
||||
this.grid = grid;
|
||||
this.algoType = algoType;
|
||||
|
||||
for (int i = 0; i < this.simulations.length; i++) {
|
||||
simulations[i] = new Simulation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the grid used for the simulations
|
||||
* @return The grid
|
||||
*/
|
||||
public Grid getGrid() {
|
||||
return this.grid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the algorithm type used for the simulations
|
||||
* @return The algorithm type
|
||||
*/
|
||||
public AlgoType getAlgoType() {
|
||||
return this.algoType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the simulations
|
||||
* @return The simulations
|
||||
*/
|
||||
public Simulation[] getSimulations() {
|
||||
return this.simulations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the average number of moves of the simulations
|
||||
* @return The average number of moves
|
||||
*/
|
||||
public float getAverageMoves() {
|
||||
int endedSimulations = 0;
|
||||
float averageMoves = 0;
|
||||
|
||||
for (Simulation simulation : simulations) {
|
||||
if (simulation.isEnded()) {
|
||||
endedSimulations++;
|
||||
averageMoves += simulation.getMoves();
|
||||
}
|
||||
}
|
||||
|
||||
if (endedSimulations == 0) return 0;
|
||||
|
||||
averageMoves = averageMoves / endedSimulations;
|
||||
|
||||
return averageMoves;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of ended simulations
|
||||
* @return The number of ended simulations
|
||||
*/
|
||||
public int getNumberOfEndedSimulations() {
|
||||
int endedSimulations = 0;
|
||||
|
||||
for (Simulation simulation : simulations) {
|
||||
if (simulation.isEnded()) {
|
||||
endedSimulations++;
|
||||
}
|
||||
}
|
||||
|
||||
return endedSimulations;
|
||||
}
|
||||
}
|
51
src/AutoSimulationController.java
Normal file
51
src/AutoSimulationController.java
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Controller for the automatic simulation
|
||||
* @version 1.0
|
||||
* @author Amir Daouadi
|
||||
* @author Lyanis Souidi
|
||||
*/
|
||||
public class AutoSimulationController {
|
||||
/**
|
||||
* The automatic simulation view
|
||||
*/
|
||||
private final AutoSimulationView view;
|
||||
|
||||
/**
|
||||
* The automatic simulation model
|
||||
*/
|
||||
private final AutoSimulation model;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param view The automatic simulation view
|
||||
* @param model The automatic simulation model
|
||||
*/
|
||||
public AutoSimulationController(AutoSimulationView view, AutoSimulation model) {
|
||||
this.view = view;
|
||||
this.model = model;
|
||||
|
||||
new Thread(this::run).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the simulations
|
||||
*/
|
||||
public void run() {
|
||||
for (Simulation simulation : this.model.getSimulations()) {
|
||||
if (!simulation.isEnded()) {
|
||||
Algo algo;
|
||||
if (this.model.getAlgoType() == AlgoType.RANDOM) {
|
||||
algo = new RandomAlgo(this.model.getGrid(), simulation);
|
||||
} else {
|
||||
algo = new DeterministicAlgo(this.model.getGrid(), simulation);
|
||||
}
|
||||
while (!simulation.isEnded()) {
|
||||
algo.nextMove();
|
||||
this.view.repaint();
|
||||
}
|
||||
|
||||
this.model.getGrid().reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -2,64 +2,51 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* The view for the auto simulation
|
||||
* The view for the automatic simulation
|
||||
* Display directly the success rate and the average number of moves of the simulations
|
||||
* @version 1.0
|
||||
* @version 1.1
|
||||
* @author Amir Daouadi
|
||||
* @author Lyanis Souidi
|
||||
*/
|
||||
public class AutoSimulationView extends JPanel {
|
||||
/**
|
||||
* The simulations to display
|
||||
*/
|
||||
private Simulation[] simulations;
|
||||
/**
|
||||
* The success rate of the simulations
|
||||
*/
|
||||
private float success = 0;
|
||||
|
||||
/**
|
||||
* The average number of moves of the simulations
|
||||
*/
|
||||
private float moves = 0;
|
||||
public final AutoSimulation model;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param simulations The simulations to display
|
||||
* @param model The automatic simulation model
|
||||
*/
|
||||
public AutoSimulationView(Simulation[] simulations) {
|
||||
public AutoSimulationView(AutoSimulation model) {
|
||||
super();
|
||||
this.simulations = simulations;
|
||||
this.model = model;
|
||||
this.setOpaque(false);
|
||||
this.setPreferredSize(new Dimension(700, 500));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the success rate and the average number of moves
|
||||
*/
|
||||
private void calculate() {
|
||||
for (Simulation simulation : simulations) {
|
||||
this.success += simulation.isSuccess() ? 1 : 0;
|
||||
this.moves += simulation.getMoves();
|
||||
}
|
||||
|
||||
this.success = (this.success / simulations.length) * 100;
|
||||
|
||||
this.moves = this.moves / simulations.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
calculate();
|
||||
g.setColor(Color.BLACK);
|
||||
|
||||
if (this.model.getSimulations()[0].getMoves() == 0) return;
|
||||
|
||||
g.setFont(new Font("Arial", Font.PLAIN, 20));
|
||||
FontMetrics metrics = g.getFontMetrics(g.getFont());
|
||||
|
||||
String successStr = "Taux de réussite : " + this.success + "%";
|
||||
g.drawString(successStr, (getWidth() - metrics.stringWidth(successStr)) / 2, ((getHeight() - metrics.getHeight()) / 2 + metrics.getAscent()) - 50);
|
||||
int y = 0;
|
||||
|
||||
String movesStr = "Nombre de mouvements moyen : " + this.moves;
|
||||
g.drawString(movesStr, (getWidth() - metrics.stringWidth(movesStr)) / 2, ((getHeight() - metrics.getHeight()) / 2 + metrics.getAscent()) + 50);
|
||||
int endedSimulations = this.model.getNumberOfEndedSimulations();
|
||||
int totalSimulations = this.model.getSimulations().length;
|
||||
int index = endedSimulations >= totalSimulations ? totalSimulations - 1 : endedSimulations;
|
||||
Simulation lastSimulation = this.model.getSimulations()[index];
|
||||
|
||||
if (!lastSimulation.isEnded()) {
|
||||
y = 50;
|
||||
g.setColor(Color.RED);
|
||||
String simulationStr = "Simulation " + endedSimulations + "/" + totalSimulations + " : " + lastSimulation.getMoves() + " mouvements";
|
||||
g.drawString(simulationStr, (getWidth() - metrics.stringWidth(simulationStr)) / 2, ((getHeight() - metrics.getHeight()) / 2 + metrics.getAscent()) - 50);
|
||||
}
|
||||
|
||||
g.setColor(Color.BLACK);
|
||||
String movesStr = "Nombre de mouvements moyen : " + this.model.getAverageMoves();
|
||||
g.drawString(movesStr, (getWidth() - metrics.stringWidth(movesStr)) / 2, ((getHeight() - metrics.getHeight()) / 2 + metrics.getAscent()) + y);
|
||||
}
|
||||
}
|
||||
|
74
src/DeterministicAlgo.java
Normal file
74
src/DeterministicAlgo.java
Normal file
@ -0,0 +1,74 @@
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* Deterministic algorithm
|
||||
* @version 0.1
|
||||
* @author Amir Daouadi
|
||||
* @author Lyanis Souidi
|
||||
*/
|
||||
public class DeterministicAlgo implements Algo {
|
||||
/**
|
||||
* The grid model
|
||||
*/
|
||||
private final Grid grid;
|
||||
|
||||
/**
|
||||
* The simulation model
|
||||
*/
|
||||
private final Simulation simulation;
|
||||
|
||||
/**
|
||||
* The Thésée model
|
||||
*/
|
||||
private final Thesee thesee;
|
||||
|
||||
/**
|
||||
* The Thésée controller
|
||||
*/
|
||||
private final TheseeController theseeController;
|
||||
|
||||
/**
|
||||
* The directions stack used to go back
|
||||
*/
|
||||
private final Stack<Direction> directions = new Stack<>();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param grid The grid model
|
||||
* @param simulation The simulation model
|
||||
*/
|
||||
public DeterministicAlgo(Grid grid, Simulation simulation) {
|
||||
this.grid = grid;
|
||||
this.simulation = simulation;
|
||||
this.thesee = this.grid.getThesee();
|
||||
this.theseeController = new TheseeController(this.thesee);
|
||||
this.thesee.getSquare().setVisited(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the next move of the algorithm
|
||||
*/
|
||||
@Override
|
||||
public void nextMove() {
|
||||
if (this.simulation.isEnded()) return;
|
||||
Direction[] availableDirection = this.theseeController.getAvailableDirections();
|
||||
|
||||
Direction nextUnvisitedDirection = null;
|
||||
for (Direction direction : availableDirection) {
|
||||
try {
|
||||
if (!this.thesee.getSquare(direction).isVisited()) {
|
||||
nextUnvisitedDirection = direction;
|
||||
break;
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
if (nextUnvisitedDirection != null) {
|
||||
if (this.theseeController.move(nextUnvisitedDirection, this.simulation)) this.directions.push(nextUnvisitedDirection);
|
||||
} else this.theseeController.move(this.directions.pop().opposite(), this.simulation);
|
||||
|
||||
if (!this.simulation.isEnded() && this.grid.isEnded()) {
|
||||
this.simulation.setEnded();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
64
src/Direction.java
Normal file
64
src/Direction.java
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Enum for the direction of Thésée's movement.
|
||||
* @version 1.0
|
||||
* @author Amir Daouadi
|
||||
* @author Lyanis Souidi
|
||||
*/
|
||||
public enum Direction {
|
||||
/**
|
||||
* Up direction
|
||||
*/
|
||||
UP,
|
||||
|
||||
/**
|
||||
* Down direction
|
||||
*/
|
||||
DOWN,
|
||||
|
||||
/**
|
||||
* Left direction
|
||||
*/
|
||||
LEFT,
|
||||
|
||||
/**
|
||||
* Right direction
|
||||
*/
|
||||
RIGHT;
|
||||
|
||||
/**
|
||||
* Get the index to add to the row of the current square to get the row of the next square.
|
||||
* @return The index to add to the row
|
||||
*/
|
||||
public int row() {
|
||||
return switch (this) {
|
||||
case UP -> -1;
|
||||
case DOWN -> 1;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index to add to the column of the current square to get the column of the next square.
|
||||
* @return The index to add to the column
|
||||
*/
|
||||
public int column() {
|
||||
return switch (this) {
|
||||
case LEFT -> -1;
|
||||
case RIGHT -> 1;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the opposite direction
|
||||
* @return The opposite direction
|
||||
*/
|
||||
public Direction opposite() {
|
||||
return switch (this) {
|
||||
case UP -> DOWN;
|
||||
case DOWN -> UP;
|
||||
case LEFT -> RIGHT;
|
||||
case RIGHT -> LEFT;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
public class Editor {
|
||||
private Grid gridModel;
|
||||
private final Grid gridModel;
|
||||
|
||||
public Editor(Grid gridModel) {
|
||||
this.gridModel = gridModel;
|
||||
|
@ -1,76 +1,141 @@
|
||||
import javax.swing.*;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.File;
|
||||
import java.util.Random;
|
||||
|
||||
public class EditorController extends GridController {
|
||||
private Editor model;
|
||||
private EditorView view;
|
||||
private final Editor model;
|
||||
private final EditorView view;
|
||||
private enum Mode { DISABLED, WALL, THESEE, EXIT }
|
||||
private Mode editMode = Mode.DISABLED;
|
||||
private Button editTheseeButton = new Button("Placer Joueur");
|
||||
private Button editExitButton = new Button("Placer Sortie");
|
||||
private Button editWallButton = new Button("Enlever/Ajouter Murs");
|
||||
private boolean edited = false;
|
||||
private final Button editTheseeButton = new Button("Modifier Thésée");
|
||||
private final Button editExitButton = new Button("Modifier Sortie");
|
||||
private final Button editWallButton = new Button("Modifier Murs");
|
||||
private final Button exportButton = new Button("Exporter");
|
||||
private final Button startButton = new Button("Démarrer");
|
||||
|
||||
public EditorController(Editor model, EditorView view) {
|
||||
super(model.getGrid(), view);
|
||||
this.model = model;
|
||||
this.view = view;
|
||||
|
||||
this.view.window.setPageTitle(this.model.getGrid().getFile().getName());
|
||||
|
||||
this.view.addMouseListener(new MouseAdapter() {
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
public void mousePressed(MouseEvent e) {
|
||||
edit(view.click(e));
|
||||
}
|
||||
});
|
||||
|
||||
JPanel buttons = new JPanel();
|
||||
|
||||
editWallButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (editMode == Mode.DISABLED) {
|
||||
editWallButton.setText("Mode Dessin");
|
||||
setEditMode(Mode.WALL);
|
||||
} else {
|
||||
editWallButton.setText("Enlever/Ajouter Murs");
|
||||
setEditMode(Mode.DISABLED);
|
||||
}
|
||||
}
|
||||
});
|
||||
buttons.add(editWallButton);
|
||||
|
||||
editTheseeButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (editMode == Mode.DISABLED) {
|
||||
editTheseeButton.setText("Mode Dessin");
|
||||
setEditMode(Mode.THESEE);
|
||||
} else {
|
||||
editTheseeButton.setText("Placer Joueur");
|
||||
setEditMode(Mode.DISABLED);
|
||||
}
|
||||
}
|
||||
});
|
||||
buttons.add(editTheseeButton);
|
||||
|
||||
editExitButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (editMode == Mode.DISABLED) {
|
||||
editExitButton.setText("Mode Dessin");
|
||||
setEditMode(Mode.EXIT);
|
||||
} else {
|
||||
editExitButton.setText("Placer Sortie");
|
||||
setEditMode(Mode.DISABLED);
|
||||
Button randomizeButton = new Button("Aléatoire");
|
||||
randomizeButton.addActionListener(e -> {
|
||||
random();
|
||||
if (!edited) {
|
||||
edited = true;
|
||||
view.window.setPageTitle("*" + view.window.getPageTitle());
|
||||
}
|
||||
view.repaint();
|
||||
});
|
||||
buttons.add(randomizeButton);
|
||||
|
||||
this.editWallButton.addActionListener(e -> setEditMode(Mode.WALL));
|
||||
buttons.add(editWallButton);
|
||||
|
||||
this.editTheseeButton.addActionListener(e -> setEditMode(Mode.THESEE));
|
||||
buttons.add(this.editTheseeButton);
|
||||
|
||||
this.editExitButton.addActionListener(e -> setEditMode(Mode.EXIT));
|
||||
buttons.add(this.editExitButton);
|
||||
|
||||
this.exportButton.addActionListener(e -> {
|
||||
JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setDialogTitle("Sélectionnez le fichier dans lequel vous souhaitez enregistrer votre grille");
|
||||
fileChooser.setSelectedFile(model.getGrid().getFile());
|
||||
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
fileChooser.setMultiSelectionEnabled(false);
|
||||
fileChooser.setAcceptAllFileFilterUsed(false);
|
||||
fileChooser.setFileFilter(new FileNameExtensionFilter("Fichier labyrinthe (*.lab)", "lab"));
|
||||
int choix = fileChooser.showSaveDialog(view);
|
||||
if (choix == JFileChooser.APPROVE_OPTION) {
|
||||
File file = fileChooser.getSelectedFile();
|
||||
if (!file.toString().toLowerCase().endsWith(".lab")) {
|
||||
file = new File(file + ".lab");
|
||||
}
|
||||
view.window.setPageTitle(file.getName());
|
||||
model.getGrid().setFile(file);
|
||||
try {
|
||||
FileManager.exportGrid(model.getGrid());
|
||||
} catch (Exception ex) {
|
||||
JOptionPane.showMessageDialog(view, ex.getMessage(), "Erreur", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
});
|
||||
buttons.add(editExitButton);
|
||||
|
||||
buttons.add(this.exportButton);
|
||||
|
||||
this.startButton.addActionListener(e -> {
|
||||
if (!this.model.getGrid().validate()) {
|
||||
JOptionPane.showMessageDialog(view, "La grille n'est pas valide.\nAssurez-vous que la grille contienne Thésée ainsi qu'une sortie, et que Thésée peut aller jusqu'à la sortie.", "Erreur", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
String[] algoOptions = {"Aléatoire", "Déterministe"};
|
||||
String[] viewOptions = {"Automatique", "Manuel"};
|
||||
int algoChoice = JOptionPane.showOptionDialog(view, "Choisissez l'algorithme à utiliser :", "Choix de l'algorithme", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, algoOptions, algoOptions[0]);
|
||||
|
||||
if (algoChoice == -1) {
|
||||
JOptionPane.showMessageDialog(view, "Aucun choix n'a été fait.", "Attention", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
int viewChoice = JOptionPane.showOptionDialog(view, "Choisissez l'affichage à utiliser :", "Choix de l'affichage", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, viewOptions, viewOptions[0]);
|
||||
|
||||
if (viewChoice == -1) {
|
||||
JOptionPane.showMessageDialog(view, "Aucun choix n'a été fait.", "Attention", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
AlgoType algoType = algoChoice == 0 ? AlgoType.RANDOM : AlgoType.DETERMINISTIC;
|
||||
|
||||
if (viewChoice == 0) {
|
||||
AutoSimulation autoSimulation = new AutoSimulation(model.getGrid(), algoType);
|
||||
AutoSimulationView autoSimulationView = new AutoSimulationView(autoSimulation);
|
||||
new AutoSimulationController(autoSimulationView, autoSimulation);
|
||||
view.window.setContentPane(autoSimulationView);
|
||||
} else {
|
||||
ManualSimulation manualSimulation = new ManualSimulation(model.getGrid(), algoType);
|
||||
ManualSimulationView manualSimulationView = new ManualSimulationView(view.window, manualSimulation);
|
||||
new ManualSimulationController(manualSimulationView, manualSimulation);
|
||||
view.window.setContentPane(manualSimulationView);
|
||||
}
|
||||
view.window.validate();
|
||||
});
|
||||
|
||||
buttons.add(this.startButton);
|
||||
|
||||
boolean validGrid = this.model.getGrid().validate();
|
||||
this.exportButton.setEnabled(validGrid);
|
||||
this.startButton.setEnabled(validGrid);
|
||||
|
||||
this.view.add(buttons, BorderLayout.NORTH);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process the click on a square
|
||||
* @param square The square clicked
|
||||
*/
|
||||
private void edit(Square square) {
|
||||
if (square != null) {
|
||||
if (!this.edited) {
|
||||
this.edited = true;
|
||||
this.view.window.setPageTitle("*" + this.view.window.getPageTitle());
|
||||
}
|
||||
if (this.editMode == Mode.WALL) {
|
||||
if (square.isWall()) {
|
||||
square.setEmpty();
|
||||
@ -81,22 +146,24 @@ public class EditorController extends GridController {
|
||||
JOptionPane.showMessageDialog(this.view, ex.getMessage(), "Erreur", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
this.view.repaint();
|
||||
} else if (this.editMode == Mode.THESEE) {
|
||||
try {
|
||||
this.model.getGrid().getThesee().setSquare(square);
|
||||
this.model.getGrid().getThesee().setSquare(square, true);
|
||||
} catch (Exception ex) {
|
||||
JOptionPane.showMessageDialog(this.view, ex.getMessage(), "Erreur", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
this.view.repaint();
|
||||
} else if (this.editMode == Mode.EXIT) {
|
||||
try {
|
||||
square.setExit();
|
||||
} catch (Exception ex) {
|
||||
JOptionPane.showMessageDialog(this.view, ex.getMessage(), "Erreur", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
this.view.repaint();
|
||||
}
|
||||
|
||||
boolean validGrid = this.model.getGrid().validate();
|
||||
this.exportButton.setEnabled(validGrid);
|
||||
this.startButton.setEnabled(validGrid);
|
||||
this.view.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,15 +173,10 @@ public class EditorController extends GridController {
|
||||
*/
|
||||
private void setEditMode(Mode mode) {
|
||||
this.editMode = mode;
|
||||
if (mode != Mode.DISABLED) {
|
||||
this.editTheseeButton.setEnabled(mode == Mode.THESEE);
|
||||
this.editExitButton.setEnabled(mode == Mode.EXIT);
|
||||
this.editWallButton.setEnabled(mode == Mode.WALL);
|
||||
} else {
|
||||
this.editTheseeButton.setEnabled(true);
|
||||
this.editExitButton.setEnabled(true);
|
||||
this.editWallButton.setEnabled(true);
|
||||
}
|
||||
|
||||
this.editTheseeButton.setEnabled(mode != Mode.THESEE);
|
||||
this.editExitButton.setEnabled(mode != Mode.EXIT);
|
||||
this.editWallButton.setEnabled(mode != Mode.WALL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,16 +187,25 @@ public class EditorController extends GridController {
|
||||
Random rand = new Random();
|
||||
Grid gridModel = this.model.getGrid();
|
||||
|
||||
gridModel.empty();
|
||||
|
||||
gridModel.getSquare(rand.nextInt(gridModel.getSize()), rand.nextInt(gridModel.getSize())).setExit();
|
||||
gridModel.getThesee().setSquare(gridModel.getSquare(rand.nextInt(gridModel.getSize()), rand.nextInt(gridModel.getSize())));
|
||||
try {
|
||||
gridModel.getThesee().setSquare(gridModel.getSquare(rand.nextInt(gridModel.getSize()), rand.nextInt(gridModel.getSize())));
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
for (int i = 0; i < gridModel.getSize(); i++) {
|
||||
for (int j = 0; j < gridModel.getSize(); j++) {
|
||||
if (!gridModel.getSquare(i, j).isExit() && !gridModel.getSquare(i, j).isThesee() && rand.nextInt(3) == 0) gridModel.getSquare(i, j).setWall();
|
||||
}
|
||||
}
|
||||
|
||||
// If the grid is invalid, try again.
|
||||
if (!gridModel.validate()) random();
|
||||
this.exportButton.setEnabled(true);
|
||||
this.startButton.setEnabled(true);
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
System.err.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import java.io.*;
|
||||
/**
|
||||
* Class to manage file import/export
|
||||
* @version 1.1
|
||||
* @version 1.0
|
||||
* @author Amir Daouadi
|
||||
* @author Lyanis Souidi
|
||||
*/
|
||||
@ -18,7 +18,7 @@ public class FileManager {
|
||||
FileInputStream fs = new FileInputStream(file);
|
||||
DataInputStream ds = new DataInputStream(fs);
|
||||
try {
|
||||
grid = new Grid(ds.read());
|
||||
grid = new Grid(ds.read(), file);
|
||||
grid.getThesee().setSquare(grid.getSquare(ds.read(), ds.read()));
|
||||
grid.getSquare(ds.read(), ds.read()).setExit();
|
||||
|
||||
@ -47,10 +47,11 @@ public class FileManager {
|
||||
/**
|
||||
* Export a grid to a file
|
||||
* @param grid The grid to export
|
||||
* @param file The file to export to
|
||||
* @throws Exception If an error occurs during the export
|
||||
*/
|
||||
public static void exportGrid(Grid grid, File file) throws Exception {
|
||||
public static void exportGrid(Grid grid) throws Exception {
|
||||
if (!grid.validate()) throw new Exception("La grille n'est pas valide. Assurez-vous que la grille contient Thésée et la sortie ainsi que la sortie puisse être accessible depuis la position de Thésée.");
|
||||
File file = grid.getFile();
|
||||
try {
|
||||
FileOutputStream fs = new FileOutputStream(file);
|
||||
DataOutputStream ds = new DataOutputStream(fs);
|
||||
@ -64,16 +65,9 @@ public class FileManager {
|
||||
ds.writeByte(theseeSquare.getColumn());
|
||||
|
||||
// Écriture de la position de la sortie
|
||||
for (int i = 0; i < grid.getSize(); i++) {
|
||||
for (int j = 0; j < grid.getSize(); j++) {
|
||||
Square square = grid.getSquare(i, j);
|
||||
if (square.isExit()) {
|
||||
ds.writeByte(square.getRow());
|
||||
ds.writeByte(square.getColumn());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Square exitSquare = grid.getExit();
|
||||
ds.writeByte(exitSquare.getRow());
|
||||
ds.writeByte(exitSquare.getColumn());
|
||||
|
||||
// Écriture des murs
|
||||
int bit = 0;
|
||||
@ -95,6 +89,7 @@ public class FileManager {
|
||||
if (bit != 0) {
|
||||
ds.writeByte(value);
|
||||
}
|
||||
ds.close();
|
||||
} catch (Exception e) {
|
||||
throw new Exception("Une erreur est survenue lors de l'écriture du fichier.");
|
||||
}
|
||||
|
170
src/Grid.java
170
src/Grid.java
@ -1,8 +1,52 @@
|
||||
import java.io.File;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* This class is used to store the grid's data
|
||||
* @version 1.0
|
||||
* @author Amir Daouadi
|
||||
* @author Lyanis Souidi
|
||||
*/
|
||||
public class Grid {
|
||||
/**
|
||||
* The grid's squares
|
||||
*/
|
||||
private Square[][] squares;
|
||||
|
||||
/**
|
||||
* Thésée
|
||||
*/
|
||||
private Thesee thesee = new Thesee();
|
||||
|
||||
/**
|
||||
* The grid's name
|
||||
*/
|
||||
private File file;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param size The size of the grid (number of squares on a row/column)
|
||||
*/
|
||||
public Grid(int size) {
|
||||
createGrid(size, new File("Sans titre"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param size The size of the grid (number of squares on a row/column)
|
||||
* @param file The name of the grid
|
||||
*/
|
||||
public Grid(int size, File file) {
|
||||
createGrid(size, file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the grid
|
||||
* @param size The size of the grid (number of squares on a row/column)
|
||||
* @param file The name of the grid
|
||||
*/
|
||||
private void createGrid(int size, File file) {
|
||||
this.file = file;
|
||||
this.squares = new Square[size][size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
for (int j = 0; j < size; j++) {
|
||||
@ -11,6 +55,37 @@ public class Grid {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Empty the grid
|
||||
* Removes the exit, Thésée and walls
|
||||
* @see Square#setEmpty()
|
||||
*/
|
||||
public void empty() {
|
||||
this.thesee = new Thesee();
|
||||
for (Square[] row : this.squares) {
|
||||
for (Square square : row) {
|
||||
square.setEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the grid's name
|
||||
* @return The grid's name
|
||||
*/
|
||||
public File getFile() {
|
||||
return this.file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the grid's name
|
||||
* @param file The grid's name
|
||||
*/
|
||||
public void setFile(File file) {
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the grid's size (number of squares on a row/column)
|
||||
* @return The grid's size
|
||||
@ -34,7 +109,102 @@ public class Grid {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Thésée
|
||||
* @return Thésée
|
||||
*/
|
||||
public Thesee getThesee() {
|
||||
return this.thesee;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if all the accessible squares have been visited
|
||||
* @return true if all the accessible squares have been visited, false otherwise
|
||||
*/
|
||||
public boolean isEnded() {
|
||||
for (Square[] row : this.squares) {
|
||||
for (Square square : row) {
|
||||
if (square.isAccessible() && !square.isVisited()) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets Thésée's position and all the squares' visited and accessible status
|
||||
*/
|
||||
public void reset() {
|
||||
this.thesee.reset();
|
||||
for (Square[] row : this.squares) {
|
||||
for (Square square : row) {
|
||||
square.setVisited(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the exit square
|
||||
* @return The exit square
|
||||
*/
|
||||
public Square getExit() {
|
||||
for (Square[] row : this.squares) {
|
||||
for (Square square : row) {
|
||||
if (square.isExit()) return square;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the grid
|
||||
* @return true if the grid can be solved, false otherwise
|
||||
*/
|
||||
public boolean validate() {
|
||||
reset();
|
||||
Square theseeSquare = this.thesee.getSquare();
|
||||
if (theseeSquare == null) return false;
|
||||
|
||||
Square exitSquare = getExit();
|
||||
if (exitSquare == null) return false;
|
||||
|
||||
if (theseeSquare == exitSquare) return false;
|
||||
|
||||
discover(theseeSquare);
|
||||
|
||||
return exitSquare.isAccessible();
|
||||
}
|
||||
|
||||
/**
|
||||
* Discovers all the accessible squares from a given square
|
||||
* @param square The square to start from
|
||||
*/
|
||||
private void discover(Square square) {
|
||||
Stack<Square> discoveredSquares = new Stack<>();
|
||||
discoveredSquares.push(square);
|
||||
while (!discoveredSquares.isEmpty()) {
|
||||
Square discoveredSquare = discoveredSquares.pop();
|
||||
|
||||
discoveredSquare.setAccessible(true);
|
||||
try {
|
||||
Square upSquare = getSquare(discoveredSquare.getRow() - 1, discoveredSquare.getColumn());
|
||||
if (!upSquare.isWall() && !upSquare.isAccessible()) discoveredSquares.push(upSquare);
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
try {
|
||||
Square downSquare = getSquare(discoveredSquare.getRow() + 1, discoveredSquare.getColumn());
|
||||
if (!downSquare.isWall() && !downSquare.isAccessible()) discoveredSquares.push(downSquare);
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
try {
|
||||
Square leftSquare = getSquare(discoveredSquare.getRow(), discoveredSquare.getColumn() - 1);
|
||||
if (!leftSquare.isWall() && !leftSquare.isAccessible()) discoveredSquares.push(leftSquare);
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
try {
|
||||
Square rightSquare = getSquare(discoveredSquare.getRow(), discoveredSquare.getColumn() + 1);
|
||||
if (!rightSquare.isWall() && !rightSquare.isAccessible()) discoveredSquares.push(rightSquare);
|
||||
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
}
|
||||
}
|
@ -2,15 +2,13 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class GridView extends JPanel {
|
||||
public Window window;
|
||||
public final Window window;
|
||||
protected Grid model;
|
||||
protected int gridSize;
|
||||
protected int gridStartX;
|
||||
protected int gridStartY;
|
||||
protected int squareSize;
|
||||
private Font font;
|
||||
private final String exit = "∩";
|
||||
private final String thesee = "Θ";
|
||||
|
||||
/**
|
||||
* Manages the display of the grid
|
||||
@ -44,7 +42,11 @@ public class GridView extends JPanel {
|
||||
for (int i = 0; i < this.model.getSize(); i++) {
|
||||
for (int j = 0; j < this.model.getSize(); j++) {
|
||||
try {
|
||||
if (this.model.getSquare(i, j).isWall()) g.setColor(new Color(122, 68, 25));
|
||||
Square square = this.model.getSquare(i, j);
|
||||
|
||||
if (square.isWall() && square.isVisited()) g.setColor(new Color(82, 79, 47));
|
||||
else if (square.isWall()) g.setColor(new Color(122, 68, 25));
|
||||
else if (square.isVisited()) g.setColor(new Color(41, 90, 69));
|
||||
else g.setColor(new Color(77, 170, 87));
|
||||
g.fillRect(this.gridStartX + (this.squareSize * j), this.gridStartY + (this.squareSize * i), this.squareSize, this.squareSize);
|
||||
|
||||
@ -52,13 +54,15 @@ public class GridView extends JPanel {
|
||||
FontMetrics metrics = g.getFontMetrics(this.font);
|
||||
g.setFont(this.font);
|
||||
// Draw exit
|
||||
if (this.model.getSquare(i, j).isExit()) {
|
||||
g.drawString(this.exit, (this.gridStartX + (this.squareSize * j)) + ((this.squareSize - metrics.stringWidth(this.exit)) / 2), (this.gridStartY + (this.squareSize * i)) + (((this.squareSize - metrics.getHeight()) / 2) + metrics.getAscent()));
|
||||
if (square.isExit()) {
|
||||
String exit = "∩";
|
||||
g.drawString(exit, (this.gridStartX + (this.squareSize * j)) + ((this.squareSize - metrics.stringWidth(exit)) / 2), (this.gridStartY + (this.squareSize * i)) + (((this.squareSize - metrics.getHeight()) / 2) + metrics.getAscent()));
|
||||
}
|
||||
|
||||
// Draw Thésée
|
||||
if (this.model.getThesee().getSquare() == this.model.getSquare(i, j)) {
|
||||
g.drawString(this.thesee, (this.gridStartX + (this.squareSize * j)) + ((this.squareSize - metrics.stringWidth(this.thesee)) / 2), (this.gridStartY + (this.squareSize * i)) + (((this.squareSize - metrics.getHeight()) / 2) + metrics.getAscent()));
|
||||
if (this.model.getThesee().getSquare() == square) {
|
||||
String thesee = "Θ";
|
||||
g.drawString(thesee, (this.gridStartX + (this.squareSize * j)) + ((this.squareSize - metrics.stringWidth(thesee)) / 2), (this.gridStartY + (this.squareSize * i)) + (((this.squareSize - metrics.getHeight()) / 2) + metrics.getAscent()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
|
@ -1,9 +1,10 @@
|
||||
import javax.swing.*;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
|
||||
public class HomeView extends JPanel {
|
||||
private Window window;
|
||||
public final Window window;
|
||||
|
||||
public HomeView(Window window) {
|
||||
this.window = window;
|
||||
@ -40,52 +41,50 @@ public class HomeView extends JPanel {
|
||||
}
|
||||
|
||||
private Button choisirGrille() {
|
||||
JPanel panel = new JPanel();
|
||||
Button choisirGrille = new Button("Générer une grille", new Dimension(250, 50));
|
||||
|
||||
choisirGrille.addActionListener(e -> {
|
||||
String strTaille = JOptionPane.showInputDialog(panel, "Entrez la taille de la grille :", "Taille de la grille", JOptionPane.PLAIN_MESSAGE);
|
||||
String strTaille = JOptionPane.showInputDialog(this, "Entrez la taille de la grille :", "Taille de la grille", JOptionPane.PLAIN_MESSAGE);
|
||||
if (strTaille != null && !strTaille.isEmpty()) {
|
||||
if (!Character.isDigit(strTaille.charAt(0))) {
|
||||
JOptionPane.showMessageDialog(panel, "Le premier caractère doit être un chiffre ou nombre.", "Erreur", JOptionPane.ERROR_MESSAGE);
|
||||
JOptionPane.showMessageDialog(this, "Le premier caractère doit être un chiffre ou nombre.", "Erreur", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int taille = Integer.parseInt(strTaille);
|
||||
if (taille > 3 && taille < 21) {
|
||||
if (taille >= 2 && taille <= 255) {
|
||||
if (!sizeWarning(this, taille)) return;
|
||||
|
||||
String[] options = {"Remplir aléatoirement", "Partir d'une grille vide"};
|
||||
int choix = JOptionPane.showOptionDialog(panel, "Choisissez comment remplir la grille :", "Remplissage de la grille", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
|
||||
int choix = JOptionPane.showOptionDialog(this, "Choisissez comment remplir la grille :", "Remplissage de la grille", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
|
||||
|
||||
EditorView editorView = new EditorView(window);
|
||||
EditorController editorController = new EditorController(new Editor(new Grid(taille)), editorView);
|
||||
switch (choix) {
|
||||
case 0:
|
||||
case 0 -> {
|
||||
// afficher la grille aléatoirement
|
||||
editorController.random();
|
||||
window.setContentPane(editorView);
|
||||
window.validate();
|
||||
break;
|
||||
case 1:
|
||||
}
|
||||
case 1 -> {
|
||||
window.setContentPane(editorView);
|
||||
window.validate();
|
||||
break;
|
||||
default:
|
||||
}
|
||||
default ->
|
||||
// gérer le cas où aucun choix n'a été fait
|
||||
JOptionPane.showMessageDialog(panel, "Aucun choix n'a été fait.", "Attention", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
JOptionPane.showMessageDialog(this, "Aucun choix n'a été fait.", "Attention", JOptionPane.WARNING_MESSAGE);
|
||||
}
|
||||
|
||||
} else {
|
||||
String errorMessage = "La taille doit être au moins de 4.";
|
||||
if (taille >= 21) {
|
||||
errorMessage = "La taille ne doit pas dépasser 20.";
|
||||
String errorMessage = "La taille doit être supérieur ou égale à 2.";
|
||||
if (taille > 255) {
|
||||
errorMessage = "La taille doit être inférieur ou égale à 255.";
|
||||
}
|
||||
JOptionPane.showMessageDialog(panel, errorMessage, "Erreur", JOptionPane.ERROR_MESSAGE);
|
||||
JOptionPane.showMessageDialog(this, errorMessage, "Erreur", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
} catch (NumberFormatException ex) {
|
||||
JOptionPane.showMessageDialog(panel, "Tapez " + strTaille.charAt(0) + " pour une grille " + strTaille.charAt(0) +"x"+ strTaille.charAt(0) +".", "Erreur", JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
|
||||
JOptionPane.showMessageDialog(this, "Tapez " + strTaille.charAt(0) + " pour une grille " + strTaille.charAt(0) +"x"+ strTaille.charAt(0) +".", "Erreur", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -94,22 +93,27 @@ public class HomeView extends JPanel {
|
||||
}
|
||||
|
||||
private Button importerGrille() {
|
||||
JPanel panel = new JPanel();
|
||||
Button importerGrille = new Button("Importer une grille", new Dimension(250, 50));
|
||||
|
||||
importerGrille.addActionListener(e -> {
|
||||
JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setDialogTitle("Selectionnez le fichier ou se trouve votre grille");
|
||||
int choix = fileChooser.showOpenDialog(panel);
|
||||
fileChooser.setDialogTitle("Sélectionnez le fichier où se trouve votre grille");
|
||||
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
fileChooser.setMultiSelectionEnabled(false);
|
||||
fileChooser.setAcceptAllFileFilterUsed(false);
|
||||
fileChooser.setFileFilter(new FileNameExtensionFilter("Fichier labyrinthe (*.lab)", "lab"));
|
||||
int choix = fileChooser.showOpenDialog(this);
|
||||
if (choix == JFileChooser.APPROVE_OPTION) {
|
||||
File fichier = fileChooser.getSelectedFile();
|
||||
try {
|
||||
Grid grid = FileManager.importGrid(fichier);
|
||||
if (!sizeWarning(this, grid.getSize())) return;
|
||||
EditorView editorView = new EditorView(window);
|
||||
new EditorController(new Editor(FileManager.importGrid(fichier)), editorView);
|
||||
new EditorController(new Editor(grid), editorView);
|
||||
window.setContentPane(editorView);
|
||||
window.validate();
|
||||
} catch (Exception ex) {
|
||||
JOptionPane.showMessageDialog(panel, ex.getMessage(), "Erreur", JOptionPane.ERROR_MESSAGE);
|
||||
JOptionPane.showMessageDialog(this, ex.getMessage(), "Erreur", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -117,6 +121,18 @@ public class HomeView extends JPanel {
|
||||
return importerGrille;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a warning message if the grid size is too big
|
||||
* @param size the size of the grid
|
||||
* @return true if the user wants to continue, false otherwise
|
||||
*/
|
||||
public static boolean sizeWarning(JComponent parentComponent, int size) {
|
||||
if (size <= 25) return true;
|
||||
String[] options = {"Abandonner", "Continuer avec cette grille"};
|
||||
int choice = JOptionPane.showOptionDialog(parentComponent, "Vous essayez d'ouvrir une grille de taille " + size + "x" + size + ".\nEn continuant avec cette grille, vous pourrez rencontrer des difficultées lors de l'edition et la durée des simulations de résolutions pourra être impactée.\nVoulez-vous continuer quand même ?", "Attention", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]);
|
||||
return choice != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
|
@ -1,8 +1,30 @@
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
Window window = new Window();
|
||||
HomeView home = new HomeView(window);
|
||||
window.setContentPane(home);
|
||||
|
||||
// If the first argument is a .lab file, try to open it
|
||||
if (args.length > 0 && args[0].toLowerCase().endsWith(".lab")) {
|
||||
Grid grid = null;
|
||||
try {
|
||||
File file = new File(args[0]);
|
||||
grid = FileManager.importGrid(new File(file.getAbsolutePath()));
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
if (grid != null && HomeView.sizeWarning(new JPanel(), grid.getSize())) {
|
||||
window.setPageTitle(args[0]);
|
||||
EditorView editorView = new EditorView(window);
|
||||
new EditorController(new Editor(grid), editorView);
|
||||
window.setContentPane(editorView);
|
||||
window.setVisible(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Else, open the home page
|
||||
HomeView homeView = new HomeView(window);
|
||||
window.setContentPane(homeView);
|
||||
window.setVisible(true);
|
||||
}
|
||||
}
|
57
src/ManualSimulation.java
Normal file
57
src/ManualSimulation.java
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* This class is used to store the data of a manual simulation
|
||||
* @version 1.0
|
||||
* @author Amir Daouadi
|
||||
* @author Lyanis Souidi
|
||||
*/
|
||||
public class ManualSimulation {
|
||||
/**
|
||||
* The grid to use for the simulations
|
||||
*/
|
||||
private final Grid grid;
|
||||
|
||||
/**
|
||||
* The algorithm type to use for the simulations
|
||||
*/
|
||||
private final AlgoType algoType;
|
||||
|
||||
/**
|
||||
* The simulation
|
||||
*/
|
||||
private final Simulation simulation = new Simulation();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param grid The grid to use for the simulation
|
||||
* @param algoType The algorithm type to use for the simulation
|
||||
*/
|
||||
public ManualSimulation(Grid grid, AlgoType algoType) {
|
||||
this.grid = grid;
|
||||
this.algoType = algoType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the grid used for the simulation
|
||||
* @return The grid
|
||||
*/
|
||||
public Grid getGrid() {
|
||||
return this.grid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the algorithm type used for the simulation
|
||||
* @return The algorithm type
|
||||
*/
|
||||
public AlgoType getAlgoType() {
|
||||
return this.algoType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the simulation
|
||||
* @return The simulation
|
||||
*/
|
||||
public Simulation getSimulation() {
|
||||
return this.simulation;
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.*;
|
||||
|
||||
/**
|
||||
* Controller for the manual simulation view.
|
||||
@ -13,58 +12,68 @@ public class ManualSimulationController {
|
||||
/**
|
||||
* The simulation model
|
||||
*/
|
||||
private Simulation model;
|
||||
private final ManualSimulation model;
|
||||
|
||||
/**
|
||||
* The manual simulation view
|
||||
*/
|
||||
private ManualSimulationView view;
|
||||
/**
|
||||
* The grid model
|
||||
*/
|
||||
private Grid grid;
|
||||
private final ManualSimulationView view;
|
||||
|
||||
/**
|
||||
* The algorithm used for the simulation
|
||||
*/
|
||||
private Algo algo;
|
||||
/**
|
||||
* The restart button
|
||||
*/
|
||||
private Button restartButton = new Button("Recommencer");
|
||||
|
||||
/**
|
||||
* The next button
|
||||
*/
|
||||
private Button nextButton = new Button("Coup suivant");
|
||||
private final Button nextButton = new Button("Coup suivant");
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param model The simulation model
|
||||
* @param model The manual simulation model
|
||||
* @param view The manual simulation view
|
||||
* @param algo The algorithm used for the simulation
|
||||
*/
|
||||
public ManualSimulationController(Simulation model, ManualSimulationView view, Algo algo) {
|
||||
public ManualSimulationController(ManualSimulationView view, ManualSimulation model) {
|
||||
this.model = model;
|
||||
this.view = view;
|
||||
this.algo = algo;
|
||||
|
||||
JPanel buttons = new JPanel();
|
||||
|
||||
restartButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
algo.reset();
|
||||
}
|
||||
});
|
||||
buttons.add(restartButton);
|
||||
|
||||
nextButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
algo.nextMove();
|
||||
if (model.isSuccess()) {
|
||||
nextButton.setEnabled(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
nextButton.addActionListener(e -> move());
|
||||
buttons.add(nextButton);
|
||||
|
||||
this.view.add(buttons, BorderLayout.NORTH);
|
||||
|
||||
this.view.addKeyListener(new KeyAdapter() {
|
||||
public void keyPressed(KeyEvent e) {
|
||||
move();
|
||||
}
|
||||
});
|
||||
this.view.setFocusable(true);
|
||||
this.view.requestFocusInWindow();
|
||||
|
||||
run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the simulation
|
||||
*/
|
||||
public void run() {
|
||||
if (this.model.getAlgoType() == AlgoType.RANDOM) {
|
||||
this.algo = new RandomAlgo(this.model.getGrid(), this.model.getSimulation());
|
||||
} else {
|
||||
this.algo = new DeterministicAlgo(this.model.getGrid(), this.model.getSimulation());
|
||||
}
|
||||
}
|
||||
|
||||
private void move() {
|
||||
if (model.getSimulation().isEnded()) return;
|
||||
this.algo.nextMove();
|
||||
this.view.repaint();
|
||||
if (model.getSimulation().isEnded()) {
|
||||
nextButton.setEnabled(false);
|
||||
JOptionPane.showMessageDialog(view, "Partie terminée en " + model.getSimulation().getMoves() + " coups !", "Fin de partie", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,15 +10,17 @@ public class ManualSimulationView extends GridView {
|
||||
/**
|
||||
* The simulation model
|
||||
*/
|
||||
private Simulation model;
|
||||
private final ManualSimulation model;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param window The window
|
||||
* @param model The simulation model
|
||||
*/
|
||||
public ManualSimulationView(Window window, Simulation model) {
|
||||
public ManualSimulationView(Window window, ManualSimulation model) {
|
||||
super(window);
|
||||
this.model = model;
|
||||
super.setGrid(this.model.getGrid());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -27,9 +29,8 @@ public class ManualSimulationView extends GridView {
|
||||
|
||||
g.setColor(Color.BLACK);
|
||||
g.setFont(new Font("Arial", Font.PLAIN, 20));
|
||||
FontMetrics metrics = g.getFontMetrics(g.getFont());
|
||||
|
||||
String movesStr = "Coups : " + this.model.getMoves();
|
||||
g.drawString(movesStr, 5, 5);
|
||||
String movesStr = "Coups : " + this.model.getSimulation().getMoves();
|
||||
g.drawString(movesStr, 10, 20);
|
||||
}
|
||||
}
|
||||
|
59
src/RandomAlgo.java
Normal file
59
src/RandomAlgo.java
Normal file
@ -0,0 +1,59 @@
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Random algorithm
|
||||
* @version 0.1
|
||||
* @author Amir Daouadi
|
||||
* @author Lyanis Souidi
|
||||
*/
|
||||
public class RandomAlgo implements Algo {
|
||||
/**
|
||||
* The grid model
|
||||
*/
|
||||
private final Grid grid;
|
||||
|
||||
/**
|
||||
* The simulation model
|
||||
*/
|
||||
private final Simulation simulation;
|
||||
|
||||
/**
|
||||
* The Thésée controller
|
||||
*/
|
||||
private final TheseeController theseeController;
|
||||
|
||||
/**
|
||||
* Random number generator
|
||||
*/
|
||||
private final Random random = new Random();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param grid The grid model
|
||||
* @param simulation The simulation model
|
||||
*/
|
||||
public RandomAlgo(Grid grid, Simulation simulation) {
|
||||
this.grid = grid;
|
||||
this.simulation = simulation;
|
||||
this.theseeController = new TheseeController(this.grid.getThesee());
|
||||
this.grid.getThesee().getSquare().setVisited(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the next move of the algorithm
|
||||
*/
|
||||
public void nextMove() {
|
||||
if (this.simulation.isEnded()) return;
|
||||
Direction[] availableDirection = this.theseeController.getAvailableDirections();
|
||||
|
||||
Direction randomDirection = availableDirection[this.random.nextInt(availableDirection.length)];
|
||||
|
||||
this.theseeController.move(randomDirection, this.simulation);
|
||||
|
||||
this.theseeController.getAvailableDirections();
|
||||
if (!this.simulation.isEnded() && this.grid.isEnded()) {
|
||||
this.simulation.setEnded();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
import java.util.Random;
|
||||
|
||||
public class RandomDirection {
|
||||
public static final int UP = 0;
|
||||
public static final int DOWN = 1;
|
||||
public static final int LEFT = 2;
|
||||
public static final int RIGHT = 3;
|
||||
|
||||
public static int getRandomDirection() {
|
||||
Random rand = new Random();
|
||||
int direction = rand.nextInt(4);
|
||||
|
||||
return direction;
|
||||
}
|
||||
}
|
@ -11,9 +11,9 @@ public class Simulation {
|
||||
private int moves = 0;
|
||||
|
||||
/**
|
||||
* If the simulation has been successful or not
|
||||
* If the simulation has ended or not
|
||||
*/
|
||||
private boolean success = false;
|
||||
private boolean end = false;
|
||||
|
||||
/**
|
||||
* Get the number of moves of the simulation
|
||||
@ -24,11 +24,18 @@ public class Simulation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if the simulation has been successful or not
|
||||
* @return If the simulation has been successful or not
|
||||
* Check if the simulation has ended or not
|
||||
* @return If the simulation has ended or not
|
||||
*/
|
||||
public boolean isSuccess() {
|
||||
return this.success;
|
||||
public boolean isEnded() {
|
||||
return this.end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the simulation as ended
|
||||
*/
|
||||
public void setEnded() {
|
||||
this.end = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,11 +45,4 @@ public class Simulation {
|
||||
this.moves++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the simulation has been successful or not
|
||||
* @param success If the simulation has been successful or not
|
||||
*/
|
||||
public void setSuccess(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
public class Square {
|
||||
public final int row;
|
||||
public final int column;
|
||||
public int type = 0;
|
||||
private Grid gridModel;
|
||||
private final int row;
|
||||
private final int column;
|
||||
private int type = 0;
|
||||
private boolean isVisited = false;
|
||||
private boolean isAccessible = false;
|
||||
private final Grid gridModel;
|
||||
|
||||
public Square(Grid gridModel, int row, int column) {
|
||||
this.gridModel = gridModel;
|
||||
@ -26,14 +28,6 @@ public class Square {
|
||||
return this.type == 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current square is empty (not a wall and not an exit)
|
||||
* @return true if the current square is empty, false otherwise
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return this.type == 0;
|
||||
}
|
||||
|
||||
public boolean isThesee() {
|
||||
return this.gridModel.getThesee().getSquare() == this;
|
||||
}
|
||||
@ -52,16 +46,11 @@ public class Square {
|
||||
*/
|
||||
public void setExit() throws Exception {
|
||||
if (this.gridModel.getThesee().getSquare() == this) throw new Exception("Vous ne pouvez pas placer la sortie sur la même case que Thésée. Déplacez d'abord Thésée puis réessayez.");
|
||||
for (int i = 0; i < this.gridModel.getSize(); i++) {
|
||||
for (int j = 0; j < this.gridModel.getSize(); j++) {
|
||||
try {
|
||||
if (this.gridModel.getSquare(i, j).isExit()) {
|
||||
this.gridModel.getSquare(i, j).setEmpty();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
Square oldExit = this.gridModel.getExit();
|
||||
|
||||
if (oldExit != null) {
|
||||
oldExit.setEmpty();
|
||||
}
|
||||
|
||||
this.type = 2;
|
||||
@ -85,4 +74,20 @@ public class Square {
|
||||
public Grid getGrid() {
|
||||
return this.gridModel;
|
||||
}
|
||||
|
||||
public boolean isVisited() {
|
||||
return this.isVisited;
|
||||
}
|
||||
|
||||
public void setVisited(boolean isVisited) {
|
||||
this.isVisited = isVisited;
|
||||
}
|
||||
|
||||
public boolean isAccessible() {
|
||||
return this.isAccessible;
|
||||
}
|
||||
|
||||
public void setAccessible(boolean isAccessible) {
|
||||
this.isAccessible = isAccessible;
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,57 @@
|
||||
/**
|
||||
* Represents Thésée in the labyrinth.
|
||||
*/
|
||||
public class Thesee {
|
||||
private Square square;
|
||||
private Square intialSquare;
|
||||
|
||||
/**
|
||||
* Moves Thésée to the given square.
|
||||
* @param square The square to move Thesee to
|
||||
* @throws Exception If the given square is a wall
|
||||
*/
|
||||
public void setSquare(Square square) throws Exception {
|
||||
if (square.isExit()) throw new Exception("Vous ne pouvez pas placer Thesee sur la même case que la sortie. Déplacez d'abord la sortie puis réessayez.");
|
||||
square.setEmpty();
|
||||
this.square = square;
|
||||
if (this.intialSquare == null) this.intialSquare = this.square;
|
||||
setSquare(square, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves Thésée to the given square.
|
||||
* @param square The square to move Thesee to
|
||||
* @param initialPosition Whether the square is the initial position
|
||||
* @throws Exception If the given square is a wall
|
||||
*/
|
||||
public void setSquare(Square square, boolean initialPosition) throws Exception {
|
||||
if (square.isExit()) throw new Exception("Vous ne pouvez pas placer Thésée sur la même case que la sortie. Déplacez d'abord la sortie puis réessayez.");
|
||||
square.setEmpty();
|
||||
this.square = square;
|
||||
if (initialPosition) {
|
||||
this.intialSquare = this.square;
|
||||
} else {
|
||||
if (this.intialSquare == null) this.intialSquare = this.square;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the square where Thésée is.
|
||||
* @return The square where Thésée is
|
||||
*/
|
||||
public Square getSquare() {
|
||||
return this.square;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a square next to Thésée.
|
||||
* @param direction The direction to get the square from
|
||||
* @return The requested square
|
||||
* @throws Exception If the position is out of grid's bounds
|
||||
*/
|
||||
public Square getSquare(Direction direction) throws Exception {
|
||||
return this.square.getGrid().getSquare(this.square.getRow() + direction.row(), this.square.getColumn() + direction.column());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets Thésée's position to the initial square/
|
||||
*/
|
||||
public void reset() {
|
||||
this.square = this.intialSquare;
|
||||
}
|
||||
|
@ -1,9 +1,5 @@
|
||||
import javax.swing.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
|
||||
public class TheseeController implements KeyListener {
|
||||
private Thesee model;
|
||||
public class TheseeController {
|
||||
private final Thesee model;
|
||||
private GridView gridView;
|
||||
|
||||
public TheseeController(Thesee model, GridView gridView) {
|
||||
@ -11,78 +7,71 @@ public class TheseeController implements KeyListener {
|
||||
this.gridView = gridView;
|
||||
}
|
||||
|
||||
public boolean moveUp() {
|
||||
public TheseeController(Thesee model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move Thésée in the given direction
|
||||
* @param direction The direction to move Thésée to
|
||||
* @param simulation The simulation model
|
||||
* @return true if the move was successful, false otherwise.
|
||||
*/
|
||||
public boolean move(Direction direction, Simulation simulation) {
|
||||
simulation.addMove();
|
||||
try {
|
||||
Square currentSquare = this.model.getSquare();
|
||||
Square newSquare = currentSquare.getGrid().getSquare(currentSquare.getRow(), currentSquare.getColumn() - 1);
|
||||
if (newSquare.isWall()) return false;
|
||||
this.model.setSquare(newSquare);
|
||||
this.gridView.repaint();
|
||||
Square newSquare = this.model.getSquare(direction);
|
||||
newSquare.setVisited(true);
|
||||
// If the new square is a wall, add a move to simulate the rollback of the move
|
||||
if (newSquare.isWall()) {
|
||||
simulation.addMove();
|
||||
if (this.gridView != null) this.gridView.repaint();
|
||||
return false;
|
||||
}
|
||||
if (newSquare.isExit()) simulation.setEnded();
|
||||
else this.model.setSquare(newSquare);
|
||||
if (this.gridView != null) this.gridView.repaint();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean moveDown() {
|
||||
/**
|
||||
* Get the available directions for the next move.
|
||||
* It helps prevent Thésée from going out of the grid.
|
||||
* @return The available directions
|
||||
*/
|
||||
public Direction[] getAvailableDirections() {
|
||||
Direction[] availableDirections = new Direction[4];
|
||||
int availableDirectionsCount = 0;
|
||||
|
||||
try {
|
||||
Square currentSquare = this.model.getSquare();
|
||||
Square newSquare = currentSquare.getGrid().getSquare(currentSquare.getRow(), currentSquare.getColumn() + 1);
|
||||
if (newSquare.isWall()) return false;
|
||||
this.model.setSquare(newSquare);
|
||||
this.gridView.repaint();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this.model.getSquare(Direction.UP);
|
||||
availableDirections[availableDirectionsCount] = Direction.UP;
|
||||
availableDirectionsCount++;
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
public boolean moveLeft() {
|
||||
try {
|
||||
Square currentSquare = this.model.getSquare();
|
||||
Square newSquare = currentSquare.getGrid().getSquare(currentSquare.getRow() - 1, currentSquare.getColumn());
|
||||
if (newSquare.isWall()) return false;
|
||||
this.model.setSquare(newSquare);
|
||||
this.gridView.repaint();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this.model.getSquare(Direction.DOWN);
|
||||
availableDirections[availableDirectionsCount] = Direction.DOWN;
|
||||
availableDirectionsCount++;
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
public boolean moveRight() {
|
||||
try {
|
||||
Square currentSquare = this.model.getSquare();
|
||||
Square newSquare = currentSquare.getGrid().getSquare(currentSquare.getRow() + 1, currentSquare.getColumn());
|
||||
if (newSquare.isWall()) return false;
|
||||
this.model.setSquare(newSquare);
|
||||
this.gridView.repaint();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this.model.getSquare(Direction.LEFT);
|
||||
availableDirections[availableDirectionsCount] = Direction.LEFT;
|
||||
availableDirectionsCount++;
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
int keyCode = e.getKeyCode();
|
||||
boolean moved;
|
||||
if (keyCode == KeyEvent.VK_UP) {
|
||||
moved = moveUp();
|
||||
} else if (keyCode == KeyEvent.VK_DOWN) {
|
||||
moved = moveDown();
|
||||
} else if (keyCode == KeyEvent.VK_LEFT) {
|
||||
moved = moveLeft();
|
||||
} else if (keyCode == KeyEvent.VK_RIGHT) {
|
||||
moved = moveRight();
|
||||
}
|
||||
}
|
||||
try {
|
||||
this.model.getSquare(Direction.RIGHT);
|
||||
availableDirections[availableDirectionsCount] = Direction.RIGHT;
|
||||
availableDirectionsCount++;
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
Direction[] availableDirectionsTrimmed = new Direction[availableDirectionsCount];
|
||||
System.arraycopy(availableDirections, 0, availableDirectionsTrimmed, 0, availableDirectionsCount);
|
||||
return availableDirectionsTrimmed;
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,24 @@ import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
|
||||
public class Window extends JFrame {
|
||||
private static final String programTitle = "Labyrinthe";
|
||||
private String pageTitle = "";
|
||||
public Window() {
|
||||
super("Labyrinthe");
|
||||
super(programTitle);
|
||||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
Dimension d = new Dimension(screenSize.width-150, screenSize.height-150);
|
||||
this.setSize(d);
|
||||
this.setLocationRelativeTo(null);
|
||||
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
this.setMinimumSize(new Dimension(750, 750));
|
||||
this.setMinimumSize(new Dimension(800, 850));
|
||||
}
|
||||
|
||||
public String getPageTitle() {
|
||||
return this.pageTitle;
|
||||
}
|
||||
|
||||
public void setPageTitle(String title) {
|
||||
this.pageTitle = title;
|
||||
this.setTitle(this.pageTitle + " - " + Window.programTitle);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user