Feat: Ajout confirmation restart et sauvegarde/chargement état

- Ajout dialog_restart_confirm.xml et dialog_background.xml pour la confirmation.
- Mise à jour strings.xml avec les textes de la boîte de dialogue.
- Modification de MainActivity:
  - Implémentation de showRestartConfirmationDialog.
  - Ajout logique SharedPreferences pour saveGame() dans onPause() et loadGame() dans onCreate().
- Modification de Game:
  - Ajout constructeur Game(board, score, highScore).
  - Ajout setter setHighScore(int).
  - Implémentation de serialize() et static deserialize() pour l'état du jeu.
  - updateHighScore() appelle maintenant saveHighScore() (stub).
This commit is contained in:
Augustin ROUX 2025-04-04 11:39:22 +02:00
parent a5cf3509d8
commit a190263cf5
6 changed files with 279 additions and 217 deletions

View File

@ -1,23 +1,29 @@
package legion.muyue.best2048; package legion.muyue.best2048;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; // Import explicite import java.util.List;
import java.util.Random; import java.util.Random;
import android.util.Log; import android.util.Log;
public class Game { public class Game {
private int[][] gameBoard; private int[][] gameBoard;
private Random random; private Random random;
private int score = 0; private int score = 0;
private int highScore = 0; // Ajout variable high score private int highScore = 0;
public Game() { public Game() {
gameBoard = new int[4][4]; gameBoard = new int[4][4];
random = new Random(); random = new Random();
loadHighScore(); // Charger au démarrage loadHighScore();
}
// Nouveau constructeur pour désérialisation
public Game(int[][] board, int score, int highScore) {
gameBoard = board;
this.score = score;
this.highScore = highScore;
random = new Random(); // Toujours initialiser
} }
public int getGameBoard(int x, int y) { public int getGameBoard(int x, int y) {
@ -32,20 +38,23 @@ public class Game {
return highScore; return highScore;
} }
// Charger le meilleur score (stub) // Ajout Setter highScore
private void loadHighScore() { public void setHighScore(int highScore) {
// highScore = sharedPreferences.getInt("high_score", 0); this.highScore = highScore;
} }
// Sauvegarder le meilleur score (stub) public void loadHighScore() {
private void saveHighScore() { // highScore = sharedPreferences.getInt("high_score", 0); // Stub
}
public void saveHighScore() {
/* SharedPreferences.Editor editor = sharedPreferences.edit(); /* SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("high_score", highScore); editor.putInt("high_score", highScore);
editor.apply(); // ou editor.commit()*/ editor.apply(); */ // Stub
} }
public void addNewNumbers() { public void addNewNumbers() {
List<int[]> emptySpaces = new ArrayList<>(); // Utilisation de List List<int[]> emptySpaces = new ArrayList<>();
for (int x = 0; x < 4; x++) { for (int x = 0; x < 4; x++) {
for (int y = 0; y < 4; y++) { for (int y = 0; y < 4; y++) {
@ -63,7 +72,6 @@ public class Game {
int newNumber; int newNumber;
int randomNumber = random.nextInt(100); int randomNumber = random.nextInt(100);
// Switch comme dans le snippet (même si if/else if était correct aussi)
if (randomNumber < 85) { if (randomNumber < 85) {
newNumber = 2; newNumber = 2;
} else if (randomNumber < 95) { } else if (randomNumber < 95) {
@ -76,43 +84,19 @@ public class Game {
} }
} }
// Les méthodes pushX appellent updateHighScore maintenant
public void pushUp() { public void pushUp() {
Log.d("Game", "Pushing Up"); Log.d("Game", "Pushing Up");
boolean[] alreadyCombined = new boolean[4]; boolean[] alreadyCombined = new boolean[4];
for (int y = 0; y < 4; y++) { for (int y = 0; y < 4; y++) {
alreadyCombined = new boolean[4]; alreadyCombined = new boolean[4];
for (int x = 1; x < 4; x++) { for (int x = 1; x < 4; x++) {
if (gameBoard[x][y] != 0) { if (gameBoard[x][y] != 0) {
int value = gameBoard[x][y]; int value = gameBoard[x][y]; int currentX = x;
int currentX = x; while (currentX > 0 && gameBoard[currentX - 1][y] == 0) { currentX--; }
if (currentX == 0) { gameBoard[0][y] = value; if (currentX != x) gameBoard[x][y] = 0; }
while (currentX > 0 && gameBoard[currentX - 1][y] == 0) { else if (gameBoard[currentX - 1][y] != value) { gameBoard[currentX][y] = value; if (currentX != x) gameBoard[x][y] = 0; }
currentX--; else if (!alreadyCombined[currentX - 1]) { gameBoard[currentX - 1][y] *= 2; score += gameBoard[currentX - 1][y]; gameBoard[x][y] = 0; alreadyCombined[currentX - 1] = true; updateHighScore(); }
} else { gameBoard[currentX][y] = value; if (currentX != x) gameBoard[x][y] = 0; }
if (currentX == 0) {
gameBoard[0][y] = value;
if (currentX != x)
gameBoard[x][y] = 0;
} else if (gameBoard[currentX - 1][y] != value) {
gameBoard[currentX][y] = value;
if (currentX != x)
gameBoard[x][y] = 0;
} else if (!alreadyCombined[currentX - 1]) {
gameBoard[currentX - 1][y] *= 2;
score += gameBoard[currentX - 1][y];
gameBoard[x][y] = 0;
alreadyCombined[currentX - 1] = true;
updateHighScore(); // Appel après fusion
} else {
gameBoard[currentX][y] = value;
if (currentX != x) {
gameBoard[x][y] = 0;
}
}
} }
} }
} }
@ -121,40 +105,16 @@ public class Game {
public void pushDown() { public void pushDown() {
Log.d("Game", "Pushing Down"); Log.d("Game", "Pushing Down");
boolean[] alreadyCombined = new boolean[4]; boolean[] alreadyCombined = new boolean[4];
for (int y = 0; y < 4; y++) { for (int y = 0; y < 4; y++) {
alreadyCombined = new boolean[4]; alreadyCombined = new boolean[4];
for (int x = 2; x >= 0; x--) { for (int x = 2; x >= 0; x--) {
if (gameBoard[x][y] != 0) { if (gameBoard[x][y] != 0) {
int value = gameBoard[x][y]; int value = gameBoard[x][y]; int currentX = x;
int currentX = x; while (currentX < 3 && gameBoard[currentX + 1][y] == 0) { currentX++; }
if (currentX == 3) { gameBoard[3][y] = value; if(currentX != x) gameBoard[x][y] = 0; }
while (currentX < 3 && gameBoard[currentX + 1][y] == 0) { else if (gameBoard[currentX + 1][y] != value) { gameBoard[currentX][y] = value; if(currentX != x) gameBoard[x][y] = 0; }
currentX++; else if (!alreadyCombined[currentX + 1]) { gameBoard[currentX + 1][y] *= 2; score += gameBoard[currentX + 1][y]; gameBoard[x][y] = 0; alreadyCombined[currentX + 1] = true; updateHighScore(); }
} else { gameBoard[currentX][y] = value; if (currentX != x) gameBoard[x][y] = 0; }
if (currentX == 3) {
gameBoard[3][y] = value;
if(currentX != x)
gameBoard[x][y] = 0;
} else if (gameBoard[currentX + 1][y] != value) {
gameBoard[currentX][y] = value;
if(currentX != x)
gameBoard[x][y] = 0;
} else if (!alreadyCombined[currentX + 1]) {
gameBoard[currentX + 1][y] *= 2;
score += gameBoard[currentX + 1][y];
gameBoard[x][y] = 0;
alreadyCombined[currentX + 1] = true;
updateHighScore(); // Appel après fusion
}
else {
gameBoard[currentX][y] = value;
if (currentX != x) {
gameBoard[x][y] = 0;
}
}
} }
} }
} }
@ -163,37 +123,16 @@ public class Game {
public void pushLeft() { public void pushLeft() {
Log.d("Game", "Pushing Left"); Log.d("Game", "Pushing Left");
boolean[] alreadyCombined = new boolean[4]; boolean[] alreadyCombined = new boolean[4];
for (int x = 0; x < 4; x++) { for (int x = 0; x < 4; x++) {
alreadyCombined = new boolean[4]; alreadyCombined = new boolean[4];
for (int y = 1; y < 4; y++) { for (int y = 1; y < 4; y++) {
if (gameBoard[x][y] != 0) { if (gameBoard[x][y] != 0) {
int value = gameBoard[x][y]; int value = gameBoard[x][y]; int currentY = y;
int currentY = y; while (currentY > 0 && gameBoard[x][currentY - 1] == 0) { currentY--; }
if (currentY == 0) { gameBoard[x][0] = value; if(currentY != y) gameBoard[x][y] = 0; }
while (currentY > 0 && gameBoard[x][currentY - 1] == 0) { else if (gameBoard[x][currentY - 1] != value) { gameBoard[x][currentY] = value; if(currentY != y) gameBoard[x][y] = 0; }
currentY--; else if (!alreadyCombined[currentY - 1]) { gameBoard[x][currentY - 1] *= 2; score += gameBoard[x][currentY - 1]; gameBoard[x][y] = 0; alreadyCombined[currentY - 1] = true; updateHighScore(); }
} else { gameBoard[x][currentY] = value; if(currentY != y) gameBoard[x][y] = 0; }
if (currentY == 0) {
gameBoard[x][0] = value;
if(currentY != y)
gameBoard[x][y] = 0;
} else if (gameBoard[x][currentY - 1] != value) {
gameBoard[x][currentY] = value;
if(currentY != y)
gameBoard[x][y] = 0;
} else if (!alreadyCombined[currentY - 1]) {
gameBoard[x][currentY - 1] *= 2;
score += gameBoard[x][currentY - 1];
gameBoard[x][y] = 0;
alreadyCombined[currentY - 1] = true;
updateHighScore(); // Appel après fusion
} else {
gameBoard[x][currentY] = value;
if(currentY != y)
gameBoard[x][y] = 0;
}
} }
} }
} }
@ -202,52 +141,58 @@ public class Game {
public void pushRight() { public void pushRight() {
Log.d("Game", "Pushing Right"); Log.d("Game", "Pushing Right");
boolean[] alreadyCombined = new boolean[4]; boolean[] alreadyCombined = new boolean[4];
for (int x = 0; x < 4; x++) { for (int x = 0; x < 4; x++) {
alreadyCombined = new boolean[4]; alreadyCombined = new boolean[4];
for (int y = 2; y >= 0; y--) { for (int y = 2; y >= 0; y--) {
if (gameBoard[x][y] != 0) { if (gameBoard[x][y] != 0) {
int value = gameBoard[x][y]; int value = gameBoard[x][y]; int currentY = y;
int currentY = y; while (currentY < 3 && gameBoard[x][currentY + 1] == 0) { currentY++; }
if (currentY == 3) { gameBoard[x][3] = value; if (currentY != y) gameBoard[x][y] = 0; }
while (currentY < 3 && gameBoard[x][currentY + 1] == 0) { else if (gameBoard[x][currentY + 1] != value) { gameBoard[x][currentY] = value; if(currentY != y) gameBoard[x][y] = 0; }
currentY++; else if (!alreadyCombined[currentY + 1]) { gameBoard[x][currentY + 1] *= 2; score += gameBoard[x][currentY + 1]; gameBoard[x][y] = 0; alreadyCombined[currentY + 1] = true; updateHighScore(); }
} else { gameBoard[x][currentY] = value; if (currentY != y) gameBoard[x][y] = 0; }
if (currentY == 3) {
gameBoard[x][3] = value;
if (currentY != y)
gameBoard[x][y] = 0;
} else if (gameBoard[x][currentY + 1] != value) {
gameBoard[x][currentY] = value;
if(currentY != y)
gameBoard[x][y] = 0;
} else if (!alreadyCombined[currentY + 1]) {
gameBoard[x][currentY + 1] *= 2;
score += gameBoard[x][currentY + 1];
gameBoard[x][y] = 0;
alreadyCombined[currentY + 1] = true;
updateHighScore(); // Appel après fusion
}
else{
gameBoard[x][currentY] = value;
if (currentY != y)
gameBoard[x][y] = 0;
}
} }
} }
} }
} }
// Nouvelle méthode pour mettre à jour le high score
private void updateHighScore() { private void updateHighScore() {
if (score > highScore) { if (score > highScore) {
highScore = score; highScore = score;
saveHighScore(); // Sauvegarder (même si le stub est vide) saveHighScore(); // Appel stub
} }
} }
// La méthode printArray reste définie comme dans l'extrait précédent // Nouvelle méthode Sérialisation
public String serialize() {
StringBuilder sb = new StringBuilder();
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 4; y++) {
sb.append(gameBoard[x][y]).append(",");
}
}
sb.append(score).append(",");
sb.append(highScore); // Ajout highScore
return sb.toString();
}
// Nouvelle méthode Désérialisation
public static Game deserialize(String serializedData) {
String[] data = serializedData.split(",");
int[][] board = new int[4][4];
int index = 0;
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 4; y++) {
board[x][y] = Integer.parseInt(data[index++]);
}
}
int score = Integer.parseInt(data[index++]);
int highScore = Integer.parseInt(data[index++]); // Lecture highScore
return new Game(board, score, highScore); // Appel nouveau constructeur
}
// printArray reste défini
public void printArray() { public void printArray() {
for (int[] row : gameBoard) { for (int[] row : gameBoard) {
String rowString = String.format("%6d%6d%6d%6d%n", row[0], row[1], row[2], row[3]); String rowString = String.format("%6d%6d%6d%6d%n", row[0], row[1], row[2], row[3]);

View File

@ -1,19 +1,20 @@
package legion.muyue.best2048; package legion.muyue.best2048;
import android.app.AlertDialog; // Ajout
import android.content.SharedPreferences; // Ajout
import android.os.Bundle; import android.os.Bundle;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.Gravity; import android.view.Gravity;
import android.view.animation.AnimationUtils; // Ajout pour Animation import android.view.LayoutInflater; // Ajout
import android.view.View; // Ajout
import android.view.animation.AnimationUtils;
import android.widget.TextView; import android.widget.TextView;
import androidx.activity.EdgeToEdge; import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.gridlayout.widget.GridLayout; import androidx.gridlayout.widget.GridLayout;
import android.widget.Button; // Ajout pour Button import android.widget.Button;
import androidx.core.view.WindowCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.core.view.WindowInsetsControllerCompat;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
@ -22,10 +23,16 @@ public class MainActivity extends AppCompatActivity {
private TextView scoreTextView; private TextView scoreTextView;
private TextView highScoreTextView; private TextView highScoreTextView;
private Game game; private Game game;
private SharedPreferences sharedPreferences; // Ajout
// Constantes SharedPreferences
private static final String PREFS_NAME = "MyPrefs";
private static final String GAME_STATE_KEY = "gameState";
private static final String HIGH_SCORE_KEY = "highScore";
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
EdgeToEdge.enable(this); EdgeToEdge.enable(this);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
@ -33,19 +40,19 @@ public class MainActivity extends AppCompatActivity {
gameBoardLayout = findViewById(R.id.gameBoard); gameBoardLayout = findViewById(R.id.gameBoard);
scoreTextView = findViewById(R.id.scoreLabel); scoreTextView = findViewById(R.id.scoreLabel);
highScoreTextView = findViewById(R.id.highScoreLabel); highScoreTextView = findViewById(R.id.highScoreLabel);
Button restartButton = findViewById(R.id.restartButton); // Initialisation Button restartButton = findViewById(R.id.restartButton);
Button statsButton = findViewById(R.id.statsButton); // Initialisation Button statsButton = findViewById(R.id.statsButton);
Button menuButton = findViewById(R.id.menuButton); // Initialisation Button menuButton = findViewById(R.id.menuButton);
Button multiplayerButton = findViewById(R.id.multiplayerButton); // Initialisation Button multiplayerButton = findViewById(R.id.multiplayerButton);
game = new Game(); // Initialisation SharedPreferences
sharedPreferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
initGameBoardLayout(); initGameBoardLayout();
// Initialisation du jeu et de l'UI via restartGame // Chargement du jeu (ou création si pas de sauvegarde)
restartGame(); loadGame();
// Ajout des listeners de swipe
setupSwipeListener(); setupSwipeListener();
//Listeners des boutons //Listeners des boutons
@ -53,9 +60,10 @@ public class MainActivity extends AppCompatActivity {
v.startAnimation(AnimationUtils.loadAnimation(this, R.anim.button_press)); v.startAnimation(AnimationUtils.loadAnimation(this, R.anim.button_press));
showMultiplayerScreen(); showMultiplayerScreen();
}); });
restartButton.setOnClickListener(v -> restartGame()); // Lambda pour restart // restartGame appelle maintenant la dialog
statsButton.setOnClickListener(v -> showStats()); // Lambda pour stats restartButton.setOnClickListener(v -> restartGame());
menuButton.setOnClickListener(v -> showMenu()); // Lambda pour menu statsButton.setOnClickListener(v -> showStats());
menuButton.setOnClickListener(v -> showMenu());
} }
private void initGameBoardLayout() { private void initGameBoardLayout() {
@ -65,14 +73,13 @@ public class MainActivity extends AppCompatActivity {
} }
private void updateUI() { private void updateUI() {
gameBoardLayout.removeAllViews(); // Efface les tuiles précédentes gameBoardLayout.removeAllViews();
for (int x = 0; x < 4; x++) { for (int x = 0; x < 4; x++) {
for (int y = 0; y < 4; y++) { for (int y = 0; y < 4; y++) {
TextView tileTextView = new TextView(this); TextView tileTextView = new TextView(this);
int value = game.getGameBoard(x, y); int value = game.getGameBoard(x, y);
// Utilisation d'une méthode pour définir l'arrière-plan et le texte
setTileAppearance(tileTextView, value); setTileAppearance(tileTextView, value);
GridLayout.LayoutParams params = new GridLayout.LayoutParams(); GridLayout.LayoutParams params = new GridLayout.LayoutParams();
@ -80,7 +87,6 @@ public class MainActivity extends AppCompatActivity {
params.height = 0; params.height = 0;
params.rowSpec = GridLayout.spec(x, 1f); params.rowSpec = GridLayout.spec(x, 1f);
params.columnSpec = GridLayout.spec(y, 1f); params.columnSpec = GridLayout.spec(y, 1f);
// Utilisation des dimensions pour les marges
params.setMargins( params.setMargins(
(int) getResources().getDimension(R.dimen.tile_margin), (int) getResources().getDimension(R.dimen.tile_margin),
(int) getResources().getDimension(R.dimen.tile_margin), (int) getResources().getDimension(R.dimen.tile_margin),
@ -92,23 +98,18 @@ public class MainActivity extends AppCompatActivity {
gameBoardLayout.addView(tileTextView); gameBoardLayout.addView(tileTextView);
} }
} }
// Met à jour les TextViews du score et du high score en utilisant getString scoreTextView.setText(getString(R.string.score_placeholder, game.getScore()));
scoreTextView.setText(getString(R.string.score, game.getScore())); highScoreTextView.setText(getString(R.string.high_score_placeholder, game.getHighScore()));
highScoreTextView.setText(getString(R.string.high_score, game.getHighScore()));
} }
// Méthode refactorisée pour l'apparence des tuiles
private void setTileAppearance(TextView tile, int value) { private void setTileAppearance(TextView tile, int value) {
// int drawableId; // N'est plus utilisé directement
int textColorId; int textColorId;
int textSizeId; int textSizeId;
// Utilisation d'un switch pour déterminer la couleur de fond, texte et taille.
switch (value) { switch (value) {
case 2: case 2:
tile.setBackgroundResource(R.drawable.tile_background); // Utilise le drawable générique tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_2_color)); // Applique la teinte tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_2_color));
textColorId = R.color.text_tile_low; textColorId = R.color.text_tile_low;
textSizeId = R.dimen.text_size_tile_small; textSizeId = R.dimen.text_size_tile_small;
break; break;
@ -121,32 +122,32 @@ public class MainActivity extends AppCompatActivity {
case 8: case 8:
tile.setBackgroundResource(R.drawable.tile_background); tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_8_color)); tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_8_color));
textColorId = R.color.text_tile_low; // Couleur texte change à partir de 8 dans le code final, mais pas dans ce snippet textColorId = R.color.text_tile_low; // Devrait être high
textSizeId = R.dimen.text_size_tile_small; textSizeId = R.dimen.text_size_tile_small;
break; break;
case 16: case 16:
tile.setBackgroundResource(R.drawable.tile_background); tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_16_color)); tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_16_color));
textColorId = R.color.text_tile_low; // Devrait être text_tile_high selon la logique standard 2048 textColorId = R.color.text_tile_low; // Devrait être high
textSizeId = R.dimen.text_size_tile_small; textSizeId = R.dimen.text_size_tile_small;
break; break;
case 32: case 32:
tile.setBackgroundResource(R.drawable.tile_background); tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_32_color)); tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_32_color));
textColorId = R.color.text_tile_low; // Devrait être text_tile_high textColorId = R.color.text_tile_low; // Devrait être high
textSizeId = R.dimen.text_size_tile_small; textSizeId = R.dimen.text_size_tile_small;
break; break;
case 64: case 64:
tile.setBackgroundResource(R.drawable.tile_background); tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_64_color)); tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_64_color));
textColorId = R.color.text_tile_low; // Devrait être text_tile_high textColorId = R.color.text_tile_low; // Devrait être high
textSizeId = R.dimen.text_size_tile_small; textSizeId = R.dimen.text_size_tile_small;
break; break;
case 128: case 128:
tile.setBackgroundResource(R.drawable.tile_background); tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_128_color)); tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_128_color));
textColorId = R.color.text_tile_high; // Correct ici textColorId = R.color.text_tile_high;
textSizeId = R.dimen.text_size_tile_medium; // Taille change textSizeId = R.dimen.text_size_tile_medium;
break; break;
case 256: case 256:
tile.setBackgroundResource(R.drawable.tile_background); tile.setBackgroundResource(R.drawable.tile_background);
@ -164,7 +165,7 @@ public class MainActivity extends AppCompatActivity {
tile.setBackgroundResource(R.drawable.tile_background); tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_1024_color)); tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_1024_color));
textColorId = R.color.text_tile_high; textColorId = R.color.text_tile_high;
textSizeId = R.dimen.text_size_tile_large; // Taille change textSizeId = R.dimen.text_size_tile_large;
break; break;
case 2048: case 2048:
tile.setBackgroundResource(R.drawable.tile_background); tile.setBackgroundResource(R.drawable.tile_background);
@ -172,12 +173,11 @@ public class MainActivity extends AppCompatActivity {
textColorId = R.color.text_tile_high; textColorId = R.color.text_tile_high;
textSizeId = R.dimen.text_size_tile_large; textSizeId = R.dimen.text_size_tile_large;
break; break;
default: // Tuile vide ou > 2048 default:
tile.setBackgroundResource(R.drawable.tile_background); tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_empty_color)); tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_empty_color));
textColorId = android.R.color.transparent; // Pas de texte textColorId = android.R.color.transparent;
textSizeId = R.dimen.text_size_tile_small; // Taille par défaut textSizeId = R.dimen.text_size_tile_small;
// Gérer les tuiles > 2048 si nécessaire (non montré dans ce snippet)
if (value > 2048) { if (value > 2048) {
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_super_color)); tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_super_color));
textColorId = R.color.text_tile_high; textColorId = R.color.text_tile_high;
@ -189,69 +189,69 @@ public class MainActivity extends AppCompatActivity {
if (value > 0) { if (value > 0) {
tile.setText(String.valueOf(value)); tile.setText(String.valueOf(value));
tile.setTextColor(ContextCompat.getColor(this, textColorId)); tile.setTextColor(ContextCompat.getColor(this, textColorId));
// Utilise la dimension pour la taille du texte
tile.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(textSizeId)); tile.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(textSizeId));
} else { } else {
tile.setText(""); // Efface le texte pour les tuiles vides tile.setText("");
} }
tile.setGravity(Gravity.CENTER); tile.setGravity(Gravity.CENTER);
} }
private void setupSwipeListener() { private void setupSwipeListener() {
// Utilise l'interface SwipeListener
gameBoardLayout.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this, new OnSwipeTouchListener.SwipeListener() { gameBoardLayout.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this, new OnSwipeTouchListener.SwipeListener() {
@Override @Override public void onSwipeTop() { handleSwipe(Direction.UP); }
public void onSwipeTop() { @Override public void onSwipeBottom() { handleSwipe(Direction.DOWN); }
handleSwipe(Direction.UP); @Override public void onSwipeLeft() { handleSwipe(Direction.LEFT); }
} @Override public void onSwipeRight() { handleSwipe(Direction.RIGHT); }
@Override
public void onSwipeBottom() {
handleSwipe(Direction.DOWN);
}
@Override
public void onSwipeLeft() {
handleSwipe(Direction.LEFT);
}
@Override
public void onSwipeRight() {
handleSwipe(Direction.RIGHT);
}
})); }));
} }
// Méthode pour gérer les swipes via l'enum
private void handleSwipe(Direction direction) { private void handleSwipe(Direction direction) {
switch (direction) { switch (direction) {
case UP: case UP: game.pushUp(); break;
game.pushUp(); case DOWN: game.pushDown(); break;
break; case LEFT: game.pushLeft(); break;
case DOWN: case RIGHT: game.pushRight(); break;
game.pushDown();
break;
case LEFT:
game.pushLeft();
break;
case RIGHT:
game.pushRight();
break;
} }
game.addNewNumbers(); game.addNewNumbers();
updateUI(); updateUI();
} }
// Méthode pour redémarrer le jeu // Modifié pour montrer la dialog
private void restartGame() { private void restartGame() {
game = new Game(); // Crée une nouvelle instance de Game showRestartConfirmationDialog();
game.addNewNumbers(); // Ajoute les tuiles initiales
game.addNewNumbers();
updateUI(); // Met à jour l'interface utilisateur
} }
// Stubs pour les autres boutons // Nouvelle méthode pour la dialog
private void showRestartConfirmationDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
LayoutInflater inflater = getLayoutInflater();
View dialogView = inflater.inflate(R.layout.dialog_restart_confirm, null);
builder.setView(dialogView);
// Références vues dialog
TextView dialogTitle = dialogView.findViewById(R.id.dialogTitle); // Non utilisé mais présent dans snippet
TextView dialogMessage = dialogView.findViewById(R.id.dialogMessage); // Non utilisé mais présent dans snippet
Button cancelButton = dialogView.findViewById(R.id.dialogCancelButton);
Button confirmButton = dialogView.findViewById(R.id.dialogConfirmButton);
final AlertDialog dialog = builder.create();
cancelButton.setOnClickListener(v -> {
dialog.dismiss();
});
confirmButton.setOnClickListener(v -> {
dialog.dismiss();
game = new Game(); // Création nouveau jeu
game.addNewNumbers(); // Ajout tuiles initiales
game.addNewNumbers();
updateUI(); // Mise à jour UI
});
dialog.show();
}
private void showStats() { private void showStats() {
//A faire //A faire
} }
@ -263,7 +263,44 @@ public class MainActivity extends AppCompatActivity {
//A faire //A faire
} }
// Enum pour les directions // Ajout onPause
@Override
protected void onPause() {
super.onPause();
saveGame(); // Sauvegarde en quittant
}
// Nouvelle méthode sauvegarde
private void saveGame() {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(GAME_STATE_KEY, game.serialize()); // Sauvegarde état sérialisé
editor.putInt(HIGH_SCORE_KEY, game.getHighScore()); // Sauvegarde high score
editor.apply(); // Appliquer
}
// Nouvelle méthode chargement
private void loadGame() {
String gameState = sharedPreferences.getString(GAME_STATE_KEY, null); // Récupère état
if (gameState != null) {
game = Game.deserialize(gameState); // Restaure si existe
// game.loadHighScore(); // Pas dans le snippet loadGame
} else {
game = new Game(); // Nouveau jeu sinon
game.addNewNumbers();
game.addNewNumbers();
}
game.loadHighScore(); // Présent dans le snippet loadGame
updateUI(); // MAJ UI
// Logique high score séparée comme dans snippet
int savedHighScore = sharedPreferences.getInt(HIGH_SCORE_KEY, 0);
if (savedHighScore > game.getHighScore()) {
game.setHighScore(savedHighScore);
// updateUI(); // Pas de second updateUI dans le snippet ici
}
}
private enum Direction { private enum Direction {
UP, DOWN, LEFT, RIGHT UP, DOWN, LEFT, RIGHT
} }

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/white"/>
<corners android:radius="12dp"/>
<stroke android:width="1dp"
android:color="@color/game_board_background"/>
</shape>

View File

@ -12,7 +12,7 @@
android:id="@+id/northPanel" android:id="@+id/northPanel"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="28dp" android:layout_marginTop="32dp"
android:baselineAligned="false" android:baselineAligned="false"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="@dimen/padding_general" android:padding="@dimen/padding_general"
@ -110,6 +110,7 @@
layout="@layout/bottom_buttons_layout" layout="@layout/bottom_buttons_layout"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="32dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintStart_toStartOf="parent" />

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:background="@drawable/dialog_background">
<TextView
android:id="@+id/dialogTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/restart_confirm_title"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="@color/text_tile_low"
android:gravity="center"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/dialogMessage"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/restart_confirm_message"
android:textSize="16sp"
android:textColor="@color/text_tile_low"
android:gravity="center"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/dialogTitle"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@+id/dialogMessage"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<Button
android:id="@+id/dialogCancelButton"
style="@style/ButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:text="@string/cancel" />
<Button
android:id="@+id/dialogConfirmButton"
style="@style/ButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:text="@string/confirm" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,10 +1,16 @@
<resources> <resources>
<string name="app_name">Best 2048</string> <string name="app_name">Best 2048</string>
<string name="name_2048">2048</string> <string name="name_2048">2048</string>
<string name="score">Score :\n0</string> <string name="score">Score :</string>
<string name="high_score">High Score :\n0</string> <string name="score_placeholder">Score :\n%d</string>
<string name="high_score_placeholder">High Score :\n%d</string>
<string name="high_score">High Score :</string>
<string name="restart">Restart</string> <string name="restart">Restart</string>
<string name="multiplayer">Multiplayer</string>
<string name="stats">Stats</string> <string name="stats">Stats</string>
<string name="menu">Menu</string> <string name="menu">Menu</string>
<string name="multiplayer">Multiplayer</string>
<string name="restart_confirm_title">Restart ?</string>
<string name="restart_confirm_message">Are you sure you want to restart the game ?</string>
<string name="cancel">Cancel</string>
<string name="confirm">Confirm</string>
</resources> </resources>