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;
import java.util.ArrayList;
import java.util.List; // Import explicite
import java.util.List;
import java.util.Random;
import android.util.Log;
public class Game {
private int[][] gameBoard;
private Random random;
private int score = 0;
private int highScore = 0; // Ajout variable high score
private int highScore = 0;
public Game() {
gameBoard = new int[4][4];
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) {
@ -32,20 +38,23 @@ public class Game {
return highScore;
}
// Charger le meilleur score (stub)
private void loadHighScore() {
// highScore = sharedPreferences.getInt("high_score", 0);
// Ajout Setter highScore
public void setHighScore(int highScore) {
this.highScore = highScore;
}
// Sauvegarder le meilleur score (stub)
private void saveHighScore() {
public void loadHighScore() {
// highScore = sharedPreferences.getInt("high_score", 0); // Stub
}
public void saveHighScore() {
/* SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("high_score", highScore);
editor.apply(); // ou editor.commit()*/
editor.apply(); */ // Stub
}
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 y = 0; y < 4; y++) {
@ -63,7 +72,6 @@ public class Game {
int newNumber;
int randomNumber = random.nextInt(100);
// Switch comme dans le snippet (même si if/else if était correct aussi)
if (randomNumber < 85) {
newNumber = 2;
} else if (randomNumber < 95) {
@ -76,43 +84,19 @@ public class Game {
}
}
// Les méthodes pushX appellent updateHighScore maintenant
public void pushUp() {
Log.d("Game", "Pushing Up");
boolean[] alreadyCombined = new boolean[4];
for (int y = 0; y < 4; y++) {
alreadyCombined = new boolean[4];
for (int x = 1; x < 4; x++) {
if (gameBoard[x][y] != 0) {
int value = gameBoard[x][y];
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;
} 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;
}
}
int value = gameBoard[x][y]; 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; }
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(); }
else { gameBoard[currentX][y] = value; if (currentX != x) gameBoard[x][y] = 0; }
}
}
}
@ -121,40 +105,16 @@ public class Game {
public void pushDown() {
Log.d("Game", "Pushing Down");
boolean[] alreadyCombined = new boolean[4];
for (int y = 0; y < 4; y++) {
alreadyCombined = new boolean[4];
for (int x = 2; x >= 0; x--) {
if (gameBoard[x][y] != 0) {
int value = gameBoard[x][y];
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;
} 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;
}
}
int value = gameBoard[x][y]; 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; }
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(); }
else { gameBoard[currentX][y] = value; if (currentX != x) gameBoard[x][y] = 0; }
}
}
}
@ -163,37 +123,16 @@ public class Game {
public void pushLeft() {
Log.d("Game", "Pushing Left");
boolean[] alreadyCombined = new boolean[4];
for (int x = 0; x < 4; x++) {
alreadyCombined = new boolean[4];
for (int y = 1; y < 4; y++) {
if (gameBoard[x][y] != 0) {
int value = gameBoard[x][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;
} 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;
}
int value = gameBoard[x][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; }
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(); }
else { gameBoard[x][currentY] = value; if(currentY != y) gameBoard[x][y] = 0; }
}
}
}
@ -202,52 +141,58 @@ public class Game {
public void pushRight() {
Log.d("Game", "Pushing Right");
boolean[] alreadyCombined = new boolean[4];
for (int x = 0; x < 4; x++) {
alreadyCombined = new boolean[4];
for (int y = 2; y >= 0; y--) {
if (gameBoard[x][y] != 0) {
int value = gameBoard[x][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;
} 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;
}
int value = gameBoard[x][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; }
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(); }
else { gameBoard[x][currentY] = value; if (currentY != y) gameBoard[x][y] = 0; }
}
}
}
}
// Nouvelle méthode pour mettre à jour le high score
private void updateHighScore() {
if (score > highScore) {
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() {
for (int[] row : gameBoard) {
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;
import android.app.AlertDialog; // Ajout
import android.content.SharedPreferences; // Ajout
import android.os.Bundle;
import android.util.TypedValue;
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 androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.gridlayout.widget.GridLayout;
import android.widget.Button; // Ajout pour Button
import androidx.core.view.WindowCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.core.view.WindowInsetsControllerCompat;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@ -22,10 +23,16 @@ public class MainActivity extends AppCompatActivity {
private TextView scoreTextView;
private TextView highScoreTextView;
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
protected void onCreate(Bundle savedInstanceState) {
EdgeToEdge.enable(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
@ -33,19 +40,19 @@ public class MainActivity extends AppCompatActivity {
gameBoardLayout = findViewById(R.id.gameBoard);
scoreTextView = findViewById(R.id.scoreLabel);
highScoreTextView = findViewById(R.id.highScoreLabel);
Button restartButton = findViewById(R.id.restartButton); // Initialisation
Button statsButton = findViewById(R.id.statsButton); // Initialisation
Button menuButton = findViewById(R.id.menuButton); // Initialisation
Button multiplayerButton = findViewById(R.id.multiplayerButton); // Initialisation
Button restartButton = findViewById(R.id.restartButton);
Button statsButton = findViewById(R.id.statsButton);
Button menuButton = findViewById(R.id.menuButton);
Button multiplayerButton = findViewById(R.id.multiplayerButton);
game = new Game();
// Initialisation SharedPreferences
sharedPreferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
initGameBoardLayout();
// Initialisation du jeu et de l'UI via restartGame
restartGame();
// Chargement du jeu (ou création si pas de sauvegarde)
loadGame();
// Ajout des listeners de swipe
setupSwipeListener();
//Listeners des boutons
@ -53,9 +60,10 @@ public class MainActivity extends AppCompatActivity {
v.startAnimation(AnimationUtils.loadAnimation(this, R.anim.button_press));
showMultiplayerScreen();
});
restartButton.setOnClickListener(v -> restartGame()); // Lambda pour restart
statsButton.setOnClickListener(v -> showStats()); // Lambda pour stats
menuButton.setOnClickListener(v -> showMenu()); // Lambda pour menu
// restartGame appelle maintenant la dialog
restartButton.setOnClickListener(v -> restartGame());
statsButton.setOnClickListener(v -> showStats());
menuButton.setOnClickListener(v -> showMenu());
}
private void initGameBoardLayout() {
@ -65,14 +73,13 @@ public class MainActivity extends AppCompatActivity {
}
private void updateUI() {
gameBoardLayout.removeAllViews(); // Efface les tuiles précédentes
gameBoardLayout.removeAllViews();
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 4; y++) {
TextView tileTextView = new TextView(this);
int value = game.getGameBoard(x, y);
// Utilisation d'une méthode pour définir l'arrière-plan et le texte
setTileAppearance(tileTextView, value);
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
@ -80,7 +87,6 @@ public class MainActivity extends AppCompatActivity {
params.height = 0;
params.rowSpec = GridLayout.spec(x, 1f);
params.columnSpec = GridLayout.spec(y, 1f);
// Utilisation des dimensions pour les marges
params.setMargins(
(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);
}
}
// Met à jour les TextViews du score et du high score en utilisant getString
scoreTextView.setText(getString(R.string.score, game.getScore()));
highScoreTextView.setText(getString(R.string.high_score, game.getHighScore()));
scoreTextView.setText(getString(R.string.score_placeholder, game.getScore()));
highScoreTextView.setText(getString(R.string.high_score_placeholder, game.getHighScore()));
}
// Méthode refactorisée pour l'apparence des tuiles
private void setTileAppearance(TextView tile, int value) {
// int drawableId; // N'est plus utilisé directement
int textColorId;
int textSizeId;
// Utilisation d'un switch pour déterminer la couleur de fond, texte et taille.
switch (value) {
case 2:
tile.setBackgroundResource(R.drawable.tile_background); // Utilise le drawable générique
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_2_color)); // Applique la teinte
tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_2_color));
textColorId = R.color.text_tile_low;
textSizeId = R.dimen.text_size_tile_small;
break;
@ -121,32 +122,32 @@ public class MainActivity extends AppCompatActivity {
case 8:
tile.setBackgroundResource(R.drawable.tile_background);
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;
break;
case 16:
tile.setBackgroundResource(R.drawable.tile_background);
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;
break;
case 32:
tile.setBackgroundResource(R.drawable.tile_background);
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;
break;
case 64:
tile.setBackgroundResource(R.drawable.tile_background);
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;
break;
case 128:
tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_128_color));
textColorId = R.color.text_tile_high; // Correct ici
textSizeId = R.dimen.text_size_tile_medium; // Taille change
textColorId = R.color.text_tile_high;
textSizeId = R.dimen.text_size_tile_medium;
break;
case 256:
tile.setBackgroundResource(R.drawable.tile_background);
@ -164,7 +165,7 @@ public class MainActivity extends AppCompatActivity {
tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_1024_color));
textColorId = R.color.text_tile_high;
textSizeId = R.dimen.text_size_tile_large; // Taille change
textSizeId = R.dimen.text_size_tile_large;
break;
case 2048:
tile.setBackgroundResource(R.drawable.tile_background);
@ -172,12 +173,11 @@ public class MainActivity extends AppCompatActivity {
textColorId = R.color.text_tile_high;
textSizeId = R.dimen.text_size_tile_large;
break;
default: // Tuile vide ou > 2048
default:
tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_empty_color));
textColorId = android.R.color.transparent; // Pas de texte
textSizeId = R.dimen.text_size_tile_small; // Taille par défaut
// Gérer les tuiles > 2048 si nécessaire (non montré dans ce snippet)
textColorId = android.R.color.transparent;
textSizeId = R.dimen.text_size_tile_small;
if (value > 2048) {
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_super_color));
textColorId = R.color.text_tile_high;
@ -189,69 +189,69 @@ public class MainActivity extends AppCompatActivity {
if (value > 0) {
tile.setText(String.valueOf(value));
tile.setTextColor(ContextCompat.getColor(this, textColorId));
// Utilise la dimension pour la taille du texte
tile.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(textSizeId));
} else {
tile.setText(""); // Efface le texte pour les tuiles vides
tile.setText("");
}
tile.setGravity(Gravity.CENTER);
}
private void setupSwipeListener() {
// Utilise l'interface SwipeListener
gameBoardLayout.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this, new OnSwipeTouchListener.SwipeListener() {
@Override
public void onSwipeTop() {
handleSwipe(Direction.UP);
}
@Override
public void onSwipeBottom() {
handleSwipe(Direction.DOWN);
}
@Override
public void onSwipeLeft() {
handleSwipe(Direction.LEFT);
}
@Override
public void onSwipeRight() {
handleSwipe(Direction.RIGHT);
}
@Override public void onSwipeTop() { handleSwipe(Direction.UP); }
@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) {
switch (direction) {
case UP:
game.pushUp();
break;
case DOWN:
game.pushDown();
break;
case LEFT:
game.pushLeft();
break;
case RIGHT:
game.pushRight();
break;
case UP: game.pushUp(); break;
case DOWN: game.pushDown(); break;
case LEFT: game.pushLeft(); break;
case RIGHT: game.pushRight(); break;
}
game.addNewNumbers();
updateUI();
}
// Méthode pour redémarrer le jeu
// Modifié pour montrer la dialog
private void restartGame() {
game = new Game(); // Crée une nouvelle instance de Game
game.addNewNumbers(); // Ajoute les tuiles initiales
game.addNewNumbers();
updateUI(); // Met à jour l'interface utilisateur
showRestartConfirmationDialog();
}
// 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() {
//A faire
}
@ -263,7 +263,44 @@ public class MainActivity extends AppCompatActivity {
//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 {
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:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="28dp"
android:layout_marginTop="32dp"
android:baselineAligned="false"
android:orientation="horizontal"
android:padding="@dimen/padding_general"
@ -110,6 +110,7 @@
layout="@layout/bottom_buttons_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="32dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="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>
<string name="app_name">Best 2048</string>
<string name="name_2048">2048</string>
<string name="score">Score :\n0</string>
<string name="high_score">High Score :\n0</string>
<string name="score">Score :</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="multiplayer">Multiplayer</string>
<string name="stats">Stats</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>