diff --git a/Flow_Free/.idea/misc.xml b/Flow_Free/.idea/misc.xml index 0ad17cb..8978d23 100644 --- a/Flow_Free/.idea/misc.xml +++ b/Flow_Free/.idea/misc.xml @@ -1,4 +1,3 @@ - diff --git a/Flow_Free/.idea/other.xml b/Flow_Free/.idea/other.xml new file mode 100644 index 0000000..22069ff --- /dev/null +++ b/Flow_Free/.idea/other.xml @@ -0,0 +1,549 @@ + + + + + + \ No newline at end of file diff --git a/test_sae_contenue_juste_le_main/main/AndroidManifest.xml b/test_sae_contenue_juste_le_main/main/AndroidManifest.xml new file mode 100644 index 0000000..8ca4082 --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/AndroidManifest.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + diff --git a/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle10.xml b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle10.xml new file mode 100644 index 0000000..ba1f181 --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle10.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle11.xml b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle11.xml new file mode 100644 index 0000000..7c89026 --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle11.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle12.xml b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle12.xml new file mode 100644 index 0000000..6c756c0 --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle12.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle13.xml b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle13.xml new file mode 100644 index 0000000..fcf53b9 --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle13.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle14.xml b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle14.xml new file mode 100644 index 0000000..1c3778c --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle14.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle5.xml b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle5.xml new file mode 100644 index 0000000..6a7d1f1 --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle5.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle6.xml b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle6.xml new file mode 100644 index 0000000..424dcb9 --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle6.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle7.xml b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle7.xml new file mode 100644 index 0000000..23f4bed --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle7.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle8.xml b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle8.xml new file mode 100644 index 0000000..8f5f65e --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle8.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle9.xml b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle9.xml new file mode 100644 index 0000000..61366a5 --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/assets/puzzles/puzzle9.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/FlowFreeView.java b/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/FlowFreeView.java new file mode 100644 index 0000000..84765c9 --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/FlowFreeView.java @@ -0,0 +1,160 @@ +package com.example.flow_free; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class FlowFreeView extends View { + private final Puzzle puzzle; + private final Paint paint = new Paint(); + private final int[][] board; + private final Map> paths = new HashMap<>(); + + private int selectedColor = 0; + private int cellSize; + + public FlowFreeView(Context context, Puzzle puzzle) { + super(context); + this.puzzle = puzzle; + this.board = new int[puzzle.getSize()][puzzle.getSize()]; + + // Initialisation du board avec les points du puzzle + for (int[] pair : puzzle.getPairs()) { + int col1 = pair[0]; + int row1 = pair[1]; + int col2 = pair[2]; + int row2 = pair[3]; + + // Crée une couleur id unique pour chaque paire (1, 2, 3, ...) + int colorId = col1 * puzzle.getSize() + row1 + 1; + board[row1][col1] = colorId; + board[row2][col2] = colorId; + } + } + @Override//test pour calculer cellsize + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + if (puzzle != null) { + cellSize = Math.min(w, h) / puzzle.getSize(); + Log.d("DEBUG_FLOW", "cellSize calculé : " + cellSize); + } + }//fin test cellsize + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + Log.d("DEBUG_FLOW", "onDraw() a été appelé !");//debug + // --- DEBUG : Affiche le contenu du board dans la console --- + StringBuilder boardLog = new StringBuilder("Contenu du board :\n"); + for (int row = 0; row < puzzle.getSize(); row++) { + for (int col = 0; col < puzzle.getSize(); col++) { + boardLog.append(String.format("%3d ", board[row][col])); + } + boardLog.append("\n"); + } + Log.d("DEBUG_FLOW", boardLog.toString()); + + + paint.setStrokeWidth(4); + paint.setStyle(Paint.Style.STROKE); + paint.setColor(Color.BLACK); + + // Affiche la grille + for (int i = 0; i <= puzzle.getSize(); i++) { + canvas.drawLine(i * cellSize, 0, i * cellSize, puzzle.getSize() * cellSize, paint); + canvas.drawLine(0, i * cellSize, puzzle.getSize() * cellSize, i * cellSize, paint); + } + + // Affiche les points de couleur + paint.setStyle(Paint.Style.FILL); + + for (int row = 0; row < puzzle.getSize(); row++) { + for (int col = 0; col < puzzle.getSize(); col++) { + int colorId = board[row][col]; + if (colorId != 0) { + paint.setColor(getColorForId(colorId)); + float cx = col * cellSize + cellSize / 2f; + float cy = row * cellSize + cellSize / 2f; + canvas.drawCircle(cx, cy, cellSize / 4f, paint); + } + } + } + + // Affiche les chemins tracés + paint.setStrokeWidth(cellSize / 4f); + paint.setStyle(Paint.Style.STROKE); + for (Map.Entry> entry : paths.entrySet()) { + paint.setColor(getColorForId(entry.getKey())); + List path = entry.getValue(); + for (int i = 0; i < path.size() - 1; i++) { + int[] p1 = path.get(i); + int[] p2 = path.get(i + 1); + canvas.drawLine( + p1[1] * cellSize + cellSize / 2f, p1[0] * cellSize + cellSize / 2f, + p2[1] * cellSize + cellSize / 2f, p2[0] * cellSize + cellSize / 2f, + paint + ); + } + } + } + + + @Override + public boolean onTouchEvent(MotionEvent event) { + int col = (int) (event.getX() / cellSize); + int row = (int) (event.getY() / cellSize); + + if (col < 0 || row < 0 || col >= puzzle.getSize() || row >= puzzle.getSize()) + return false; + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + int colorAtCell = board[row][col]; + if (colorAtCell != 0) { + selectedColor = colorAtCell; + if (!paths.containsKey(selectedColor)) { + paths.put(selectedColor, new ArrayList<>()); + } + // Si on relâche et reprend depuis la dernière case + List path = paths.get(selectedColor); + if (path.isEmpty() || (path.get(path.size() - 1)[0] != row || path.get(path.size() - 1)[1] != col)) { + path.add(new int[]{row, col}); + } + } + break; + + case MotionEvent.ACTION_MOVE: + if (selectedColor != 0) { + List path = paths.get(selectedColor); + int[] last = path.get(path.size() - 1); + if (last[0] != row || last[1] != col) { + path.add(new int[]{row, col}); + } + } + break; + + case MotionEvent.ACTION_UP: + selectedColor = 0; // Permet de reprendre à la prochaine touche + break; + } + invalidate(); + return true; + } + + + private int getColorForId(int id) { + // Associe une couleur différente à chaque id unique + int[] colors = {Color.RED, Color.BLUE, Color.GREEN, Color.MAGENTA, Color.YELLOW, Color.CYAN, Color.DKGRAY, Color.rgb(139, 69, 19)}; // Marron inclus + return colors[(id - 1) % colors.length]; + } +} diff --git a/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/GameActivity.java b/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/GameActivity.java new file mode 100644 index 0000000..ab2404a --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/GameActivity.java @@ -0,0 +1,39 @@ +package com.example.flow_free; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.ViewGroup; + +public class GameActivity extends Activity { + private FlowFreeView flowFreeView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Log.d("DEBUG_FLOW", "GameActivity lancé"); // debug + String puzzleFile = getIntent().getStringExtra("PUZZLE_FILE"); + Puzzle puzzle = PuzzleLoader.loadPuzzle(this, puzzleFile); + if (puzzle == null) {//debut debug + Log.d("DEBUG_FLOW", "Échec du chargement du puzzle : " + puzzleFile); + finish(); // quitte l’activité + return; + } else { + Log.d("DEBUG_FLOW", "Puzzle chargé avec succès : " + puzzle.getName() + ", taille = " + puzzle.getSize()); + FlowFreeView flowFreeView = new FlowFreeView(this, puzzle); + Log.d("DEBUG_FLOW", "FlowFreeView créé, on va l'afficher maintenant."); + setContentView(flowFreeView); + }//fin debug + + + if (puzzle == null) { + finish(); + return; + } + + FlowFreeView flowFreeView = new FlowFreeView(this, puzzle); + setContentView(flowFreeView); + } + +} diff --git a/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/MainActivity.java b/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/MainActivity.java new file mode 100644 index 0000000..fadef6b --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/MainActivity.java @@ -0,0 +1,66 @@ +// MainActivity.java +package com.example.flow_free; + +import android.app.Activity; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ListView; +import android.widget.Toast; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class MainActivity extends Activity { + + private ListView puzzleListView; + private Button settingsButton; + private List puzzleList; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + // Préférences + SharedPreferences preferences = getSharedPreferences("FlowFreePrefs", MODE_PRIVATE); + + // Initialisation des vues + puzzleListView = findViewById(R.id.puzzle_list_view); + settingsButton = findViewById(R.id.settings_button); + + // Chargement des puzzles depuis assets/puzzles + try { + puzzleList = new ArrayList<>(Arrays.asList(getAssets().list("puzzles"))); + } catch (IOException e) { + puzzleList = new ArrayList<>(); + } + + ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, puzzleList); + puzzleListView.setAdapter(adapter); + + // Click sur un puzzle + puzzleListView.setOnItemClickListener((parent, view, position, id) -> { + String selectedPuzzle = puzzleList.get(position); + if (!selectedPuzzle.endsWith(".xml")) { + Toast.makeText(this, "Puzzle invalide", Toast.LENGTH_SHORT).show(); + return; + } + Intent intent = new Intent(MainActivity.this, GameActivity.class); + intent.putExtra("PUZZLE_FILE", selectedPuzzle); + startActivity(intent); + }); + + // Bouton paramètres + settingsButton.setOnClickListener(v -> { + Intent intent = new Intent(MainActivity.this, SettingsActivity.class); + startActivity(intent); + }); + } +} diff --git a/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/Puzzle.java b/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/Puzzle.java new file mode 100644 index 0000000..e0918bb --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/Puzzle.java @@ -0,0 +1,28 @@ +// Puzzle.java +package com.example.flow_free; + +import java.util.List; + +public class Puzzle { + private int size; + private String name; + private List pairs; + + public Puzzle(int size, String name, List pairs) { + this.size = size; + this.name = name; + this.pairs = pairs; + } + + public int getSize() { + return size; + } + + public String getName() { + return name; + } + + public List getPairs() { + return pairs; + } +} \ No newline at end of file diff --git a/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/PuzzleLoader.java b/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/PuzzleLoader.java new file mode 100644 index 0000000..d1b646b --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/PuzzleLoader.java @@ -0,0 +1,11 @@ +package com.example.flow_free; + +import android.content.Context; + +public class PuzzleLoader { + + public static Puzzle loadPuzzle(Context context, String filename) { + // Charge le puzzle via le parser et retourne l'objet Puzzle + return PuzzleParser.parsePuzzle(context, filename); + } +} diff --git a/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/PuzzleParser.java b/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/PuzzleParser.java new file mode 100644 index 0000000..d9f651e --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/PuzzleParser.java @@ -0,0 +1,62 @@ +package com.example.flow_free; + +import android.content.Context; +import android.content.res.AssetManager; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlPullParserFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +public class PuzzleParser { + + public static Puzzle parsePuzzle(Context context, String filename) { + AssetManager assetManager = context.getAssets(); + + try { + InputStream inputStream = assetManager.open("puzzles/" + filename); + XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser(); + parser.setInput(inputStream, "UTF-8"); + + int size = -1; + String name = filename.replace(".xml", ""); + List pairs = new ArrayList<>(); + int[] currentPair = new int[4]; + int pointIndex = 0; + + int eventType = parser.getEventType(); + while (eventType != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.START_TAG) { + String tagName = parser.getName(); + if (tagName.equals("puzzle")) { + size = Integer.parseInt(parser.getAttributeValue(null, "size")); + if (parser.getAttributeValue(null, "nom") != null) { + name = parser.getAttributeValue(null, "nom"); + } + } else if (tagName.equals("point")) { + int col = Integer.parseInt(parser.getAttributeValue(null, "colonne")); + int row = Integer.parseInt(parser.getAttributeValue(null, "ligne")); + currentPair[pointIndex * 2] = col; + currentPair[pointIndex * 2 + 1] = row; + pointIndex++; + if (pointIndex == 2) { + pairs.add(new int[]{currentPair[0], currentPair[1], currentPair[2], currentPair[3]}); + currentPair = new int[4]; + pointIndex = 0; + } + } + } + eventType = parser.next(); + } + + return new Puzzle(size, name, pairs); + } catch (IOException | XmlPullParserException | NumberFormatException e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/SettingsActivity.java b/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/SettingsActivity.java new file mode 100644 index 0000000..e656230 --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/java/com/example/flow_free/SettingsActivity.java @@ -0,0 +1,12 @@ +package com.example.flow_free; + +import android.os.Bundle; +import android.preference.PreferenceActivity; + +public class SettingsActivity extends PreferenceActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.preferences); + } +} diff --git a/test_sae_contenue_juste_le_main/main/res/drawable-v24/ic_launcher_foreground.xml b/test_sae_contenue_juste_le_main/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/test_sae_contenue_juste_le_main/main/res/drawable/ic_launcher_background.xml b/test_sae_contenue_juste_le_main/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test_sae_contenue_juste_le_main/main/res/layout/activity_game.xml b/test_sae_contenue_juste_le_main/main/res/layout/activity_game.xml new file mode 100644 index 0000000..d84374e --- /dev/null +++ b/test_sae_contenue_juste_le_main/main/res/layout/activity_game.xml @@ -0,0 +1,18 @@ + + + + + +