Refactor: UI - Styles, Dimens, Animations, Code Java

- XML:
  - Utilisation de <include> pour les boutons du bas (bottom_buttons_layout.xml).
  - Extraction des dimensions dans dimens.xml.
  - Définition de styles (ScoreLabelStyle, ButtonStyle, LargeButtonStyle) dans styles.xml.
  - Ajout de nombreuses couleurs dans colors.xml.
  - Ajout placeholders pour tile_background.xml et button_multiplayer_background.xml.
- Java:
  - MainActivity: Utilisation de switch et teinte pour l'apparence des tuiles (setTileAppearance),
    utilisation de getString pour les scores, ajout listeners et animations simples aux boutons,
    implémentation de restartGame(), ajout stubs autres boutons, ajout enum Direction.
  - Game: Ajout champ/méthodes highScore (stubs load/save), appel updateHighScore après fusion,
    utilisation de List<int[]> pour emptySpaces.
  - OnSwipeTouchListener: Utilisation d'une interface SwipeListener pour découplage.
- Ajout des fichiers d'animation button_press.xml et button_release.xml.
This commit is contained in:
Augustin ROUX 2025-04-03 19:25:08 +02:00
parent 84ca7f9fc3
commit 344db1e4ae
27 changed files with 435 additions and 352 deletions

View File

@ -1,6 +1,7 @@
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.Random; import java.util.Random;
import android.util.Log; import android.util.Log;
@ -10,10 +11,13 @@ 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
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
} }
public int getGameBoard(int x, int y) { public int getGameBoard(int x, int y) {
@ -25,20 +29,23 @@ public class Game {
} }
public int getHighScore() { public int getHighScore() {
return 0; // TODO: Implémentez la logique du meilleur score plus tard return highScore;
} }
// La méthode printArray est toujours présente dans l'extrait de Game.java pour l'étape 8 // Charger le meilleur score (stub)
public void printArray() { private void loadHighScore() {
for (int[] row : gameBoard) { // highScore = sharedPreferences.getInt("high_score", 0);
String rowString = String.format("%6d%6d%6d%6d%n", row[0], row[1], row[2], row[3]); }
Log.d("Game", rowString);
} // Sauvegarder le meilleur score (stub)
Log.d("Game", "\n"); private void saveHighScore() {
/* SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("high_score", highScore);
editor.apply(); // ou editor.commit()*/
} }
public void addNewNumbers() { public void addNewNumbers() {
ArrayList<int[]> emptySpaces = new ArrayList<>(); List<int[]> emptySpaces = new ArrayList<>(); // Utilisation de List
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++) {
@ -55,6 +62,8 @@ public class Game {
int y = coordinates[1]; int y = coordinates[1];
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) {
@ -62,10 +71,12 @@ public class Game {
} else { } else {
newNumber = 8; newNumber = 8;
} }
gameBoard[x][y] = newNumber; gameBoard[x][y] = newNumber;
} }
} }
// Les méthodes pushX appellent updateHighScore maintenant
public void pushUp() { public void pushUp() {
Log.d("Game", "Pushing Up"); Log.d("Game", "Pushing Up");
@ -95,6 +106,7 @@ public class Game {
score += gameBoard[currentX - 1][y]; score += gameBoard[currentX - 1][y];
gameBoard[x][y] = 0; gameBoard[x][y] = 0;
alreadyCombined[currentX - 1] = true; alreadyCombined[currentX - 1] = true;
updateHighScore(); // Appel après fusion
} else { } else {
gameBoard[currentX][y] = value; gameBoard[currentX][y] = value;
if (currentX != x) { if (currentX != x) {
@ -123,18 +135,21 @@ public class Game {
if (currentX == 3) { if (currentX == 3) {
gameBoard[3][y] = value; gameBoard[3][y] = value;
if (currentX != x) if(currentX != x)
gameBoard[x][y] = 0; gameBoard[x][y] = 0;
} else if (gameBoard[currentX + 1][y] != value) { } else if (gameBoard[currentX + 1][y] != value) {
gameBoard[currentX][y] = value; gameBoard[currentX][y] = value;
if (currentX != x) if(currentX != x)
gameBoard[x][y] = 0; gameBoard[x][y] = 0;
} else if (!alreadyCombined[currentX + 1]) { } else if (!alreadyCombined[currentX + 1]) {
gameBoard[currentX + 1][y] *= 2; gameBoard[currentX + 1][y] *= 2;
score += gameBoard[currentX + 1][y]; score += gameBoard[currentX + 1][y];
gameBoard[x][y] = 0; gameBoard[x][y] = 0;
alreadyCombined[currentX + 1] = true; alreadyCombined[currentX + 1] = true;
} else { updateHighScore(); // Appel après fusion
}
else {
gameBoard[currentX][y] = value; gameBoard[currentX][y] = value;
if (currentX != x) { if (currentX != x) {
gameBoard[x][y] = 0; gameBoard[x][y] = 0;
@ -173,6 +188,7 @@ public class Game {
score += gameBoard[x][currentY - 1]; score += gameBoard[x][currentY - 1];
gameBoard[x][y] = 0; gameBoard[x][y] = 0;
alreadyCombined[currentY - 1] = true; alreadyCombined[currentY - 1] = true;
updateHighScore(); // Appel après fusion
} else { } else {
gameBoard[x][currentY] = value; gameBoard[x][currentY] = value;
if(currentY != y) if(currentY != y)
@ -211,7 +227,9 @@ public class Game {
score += gameBoard[x][currentY + 1]; score += gameBoard[x][currentY + 1];
gameBoard[x][y] = 0; gameBoard[x][y] = 0;
alreadyCombined[currentY + 1] = true; alreadyCombined[currentY + 1] = true;
} else { updateHighScore(); // Appel après fusion
}
else{
gameBoard[x][currentY] = value; gameBoard[x][currentY] = value;
if (currentY != y) if (currentY != y)
gameBoard[x][y] = 0; gameBoard[x][y] = 0;
@ -220,4 +238,21 @@ public class Game {
} }
} }
} }
// 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)
}
}
// La méthode printArray reste définie comme dans l'extrait précédent
public void printArray() {
for (int[] row : gameBoard) {
String rowString = String.format("%6d%6d%6d%6d%n", row[0], row[1], row[2], row[3]);
Log.d("Game", rowString);
}
Log.d("Game", "\n");
}
} }

View File

@ -3,10 +3,13 @@ package legion.muyue.best2048;
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.widget.TextView; import android.widget.TextView;
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
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
@ -23,19 +26,31 @@ 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 statsButton = findViewById(R.id.statsButton); // Initialisation
Button menuButton = findViewById(R.id.menuButton); // Initialisation
Button multiplayerButton = findViewById(R.id.multiplayerButton); // Initialisation
game = new Game(); game = new Game();
initGameBoardLayout(); initGameBoardLayout();
game.addNewNumbers(); // Initialisation du jeu et de l'UI via restartGame
game.addNewNumbers(); restartGame();
game.addNewNumbers();
updateUI();
// Ajout des listeners de swipe // Ajout des listeners de swipe
setupSwipeListener(); setupSwipeListener();
//Listeners des boutons
multiplayerButton.setOnClickListener(v -> {
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
} }
private void initGameBoardLayout() { private void initGameBoardLayout() {
gameBoardLayout.removeAllViews(); gameBoardLayout.removeAllViews();
gameBoardLayout.setColumnCount(4); gameBoardLayout.setColumnCount(4);
@ -50,105 +65,200 @@ public class MainActivity extends AppCompatActivity {
TextView tileTextView = new TextView(this); TextView tileTextView = new TextView(this);
int value = game.getGameBoard(x, y); int value = game.getGameBoard(x, y);
// Choisir le bon drawable en fonction de la valeur // Utilisation d'une méthode pour définir l'arrière-plan et le texte
int drawableId; setTileAppearance(tileTextView, value);
switch (value) {
case 2:
drawableId = R.drawable.tile2;
break;
case 4:
drawableId = R.drawable.tile4;
break;
case 8:
drawableId = R.drawable.tile8;
break;
case 16:
drawableId = R.drawable.tile16;
break;
case 32:
drawableId = R.drawable.tile32;
break;
case 64:
drawableId = R.drawable.tile64;
break;
case 128:
drawableId = R.drawable.tile128;
break;
case 256:
drawableId = R.drawable.tile256;
break;
case 512:
drawableId = R.drawable.tile512;
break;
case 1024:
drawableId = R.drawable.tile1024;
break;
case 2048:
drawableId = R.drawable.tile2048;
break;
default:
drawableId = R.drawable.tile_empty;
break;
}
tileTextView.setBackground(ContextCompat.getDrawable(this, drawableId));
// Afficher le texte uniquement si la valeur est > 0
if (value > 0) {
tileTextView.setText(String.valueOf(value));
// Adapte la taille du texte en fonction de la valeur.
tileTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, value < 128 ? 24 : (value < 1024 ? 20 : 16));
tileTextView.setTextColor(ContextCompat.getColor(this, R.color.text_tile_low));
}
tileTextView.setGravity(Gravity.CENTER);
GridLayout.LayoutParams params = new GridLayout.LayoutParams(); GridLayout.LayoutParams params = new GridLayout.LayoutParams();
params.width = 0; params.width = 0;
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);
params.setMargins(10, 10, 10, 10); // Marges codées en dur selon l'extrait // Utilisation des dimensions pour les marges
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)
);
tileTextView.setLayoutParams(params); tileTextView.setLayoutParams(params);
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, game.getScore()));
highScoreTextView.setText(getString(R.string.high_score, game.getHighScore()));
scoreTextView.setText("Score:\n" + game.getScore()); // Concaténation simple selon l'extrait
highScoreTextView.setText("High Score:\n" + game.getHighScore()); // Concaténation simple selon l'extrait
} }
// 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
textColorId = R.color.text_tile_low;
textSizeId = R.dimen.text_size_tile_small;
break;
case 4:
tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_4_color));
textColorId = R.color.text_tile_low;
textSizeId = R.dimen.text_size_tile_small;
break;
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
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
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
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
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
break;
case 256:
tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_256_color));
textColorId = R.color.text_tile_high;
textSizeId = R.dimen.text_size_tile_medium;
break;
case 512:
tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_512_color));
textColorId = R.color.text_tile_high;
textSizeId = R.dimen.text_size_tile_medium;
break;
case 1024:
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
break;
case 2048:
tile.setBackgroundResource(R.drawable.tile_background);
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_2048_color));
textColorId = R.color.text_tile_high;
textSizeId = R.dimen.text_size_tile_large;
break;
default: // Tuile vide ou > 2048
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)
if (value > 2048) {
tile.getBackground().setTint(ContextCompat.getColor(this, R.color.tile_super_color));
textColorId = R.color.text_tile_high;
textSizeId = R.dimen.text_size_tile_large;
}
break;
}
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.setGravity(Gravity.CENTER);
}
private void setupSwipeListener() { private void setupSwipeListener() {
gameBoardLayout.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this) { // Utilise l'interface SwipeListener
gameBoardLayout.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this, new OnSwipeTouchListener.SwipeListener() {
@Override @Override
public void onSwipeTop() { public void onSwipeTop() {
game.pushUp(); handleSwipe(Direction.UP);
game.addNewNumbers();
updateUI();
} }
@Override @Override
public void onSwipeBottom() { public void onSwipeBottom() {
game.pushDown(); handleSwipe(Direction.DOWN);
game.addNewNumbers();
updateUI();
} }
@Override @Override
public void onSwipeLeft() { public void onSwipeLeft() {
game.pushLeft(); handleSwipe(Direction.LEFT);
game.addNewNumbers();
updateUI();
} }
@Override @Override
public void onSwipeRight() { public void onSwipeRight() {
game.pushRight(); handleSwipe(Direction.RIGHT);
game.addNewNumbers();
updateUI();
} }
}); }));
} }
// 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;
}
game.addNewNumbers();
updateUI();
}
// Méthode pour redémarrer le jeu
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
}
// Stubs pour les autres boutons
private void showStats() {
//A faire
}
private void showMenu() {
//A faire
}
private void showMultiplayerScreen() {
//A faire
}
// Enum pour les directions
private enum Direction {
UP, DOWN, LEFT, RIGHT
}
} }

View File

@ -8,9 +8,20 @@ import android.view.View;
public class OnSwipeTouchListener implements View.OnTouchListener { public class OnSwipeTouchListener implements View.OnTouchListener {
private final GestureDetector gestureDetector; private final GestureDetector gestureDetector;
private final SwipeListener listener; // Ajout de l'interface listener
public OnSwipeTouchListener(Context ctx) { // Interface pour les événements de swipe
public interface SwipeListener {
void onSwipeTop();
void onSwipeBottom();
void onSwipeLeft();
void onSwipeRight();
}
// Constructeur modifié pour accepter le listener
public OnSwipeTouchListener(Context ctx, SwipeListener listener) {
gestureDetector = new GestureDetector(ctx, new GestureListener()); gestureDetector = new GestureDetector(ctx, new GestureListener());
this.listener = listener;
} }
@Override @Override
@ -37,17 +48,17 @@ public class OnSwipeTouchListener implements View.OnTouchListener {
if (Math.abs(diffX) > Math.abs(diffY)) { if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) { if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) { if (diffX > 0) {
onSwipeRight(); listener.onSwipeRight(); // Appel via listener
} else { } else {
onSwipeLeft(); listener.onSwipeLeft(); // Appel via listener
} }
result = true; result = true;
} }
} else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) { } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) { if (diffY > 0) {
onSwipeBottom(); listener.onSwipeBottom(); // Appel via listener
} else { } else {
onSwipeTop(); listener.onSwipeTop(); // Appel via listener
} }
result = true; result = true;
} }
@ -57,16 +68,5 @@ public class OnSwipeTouchListener implements View.OnTouchListener {
return result; return result;
} }
} }
// Les méthodes locales vides ne sont plus nécessaires car on utilise l'interface
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeTop() {
}
public void onSwipeBottom() {
}
} }

View File

@ -0,0 +1,15 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator">
<scale
android:fromXScale="1.0"
android:toXScale="0.95"
android:fromYScale="1.0"
android:toYScale="0.95"
android:pivotX="50%"
android:pivotY="50%"
android:duration="100" />
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.8"
android:duration="100" />
</set>

View File

@ -0,0 +1,15 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator">
<scale
android:fromXScale="0.95"
android:toXScale="1.0"
android:fromYScale="0.95"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="100" />
<alpha
android:fromAlpha="0.8"
android:toAlpha="1.0"
android:duration="100" />
</set>

View File

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

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FCE588" /> <corners android:radius="6dp" />
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" />
</shape>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#EDCF72" />
<corners android:radius="6dp" />
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" />
</shape>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#F59563" />
<corners android:radius="6dp" />
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" />
</shape>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#EEE4DA" />
<corners android:radius="6dp" />
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" />
</shape>

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FFEB84" /> <corners android:radius="6dp" />
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" />
</shape>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#EDCC61" />
<corners android:radius="6dp" />
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" />
</shape>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#F67C5F" />
<corners android:radius="6dp" />
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" />
</shape>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#EDE0C8" />
<corners android:radius="6dp" />
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" />
</shape>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#EDC850" />
<corners android:radius="6dp" />
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" />
</shape>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#F65E3B" />
<corners android:radius="6dp" />
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" />
</shape>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#F2B179" />
<corners android:radius="6dp" />
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" />
</shape>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#CDC1B4"/>
<corners android:radius="@dimen/corner_radius"/>
</shape>

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#C9BCAC" /> <corners android:radius="6dp" />
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" />
</shape>

View File

@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="#FCFAEE" android:background="@color/background_color"
tools:context=".MainActivity"> tools:context=".MainActivity">
<LinearLayout <LinearLayout
@ -12,7 +12,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="16dp" android:padding="@dimen/padding_general"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
@ -20,20 +20,20 @@
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="20dp" android:layout_marginEnd="@dimen/margin_between_elements"
android:layout_weight="1"> android:layout_weight="1">
<TextView <TextView
android:id="@+id/gameLabel" android:id="@+id/gameLabel"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:background="#EDCC5F" android:background="@color/game_label_background"
android:fontFamily="sans-serif-medium" android:fontFamily="sans-serif-medium"
android:gravity="center" android:gravity="center"
android:padding="16dp" android:padding="@dimen/padding_general"
android:text="@string/name_2048" android:text="@string/name_2048"
android:textColor="#FFFFFF" android:textColor="@color/white"
android:textSize="48sp" android:textSize="@dimen/text_size_game_label"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1" app:layout_constraintDimensionRatio="1:1"
@ -42,42 +42,22 @@
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout <LinearLayout
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:orientation="vertical"
android:gravity="center" android:gravity="center"
app:layout_constraintBottom_toBottomOf="@+id/gameLabel" android:orientation="vertical"
> app:layout_constraintBottom_toBottomOf="@+id/gameLabel">
<TextView <TextView
android:id="@+id/scoreLabel" android:id="@+id/scoreLabel"
android:layout_width="match_parent" style="@style/ScoreLabelStyle"
android:layout_height="0dp" android:text="@string/score" /> <TextView
android:layout_weight="1" android:id="@+id/highScoreLabel"
android:background="#F75E3E" style="@style/ScoreLabelStyle"
android:gravity="center" android:layout_marginTop="@dimen/margin_between_elements"
android:padding="8dp" android:text="@string/high_score" /> </LinearLayout>
android:text="@string/score"
android:textColor="#FFFFFF"
android:textSize="18sp" />
<TextView
android:id="@+id/highScoreLabel"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginTop="8dp"
android:background="#F75E3E"
android:gravity="center"
android:padding="8dp"
android:text="@string/high_score"
android:textColor="#FFFFFF"
android:textSize="18sp" />
</LinearLayout>
</LinearLayout> </LinearLayout>
@ -85,11 +65,11 @@
android:id="@+id/gameBoardContainer" android:id="@+id/gameBoardContainer"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_margin="16dp" android:layout_margin="@dimen/padding_general"
app:cardBackgroundColor="@android:color/transparent" app:cardBackgroundColor="@android:color/transparent"
app:cardCornerRadius="6dp" app:cardCornerRadius="@dimen/corner_radius"
app:cardElevation="0dp" app:cardElevation="0dp"
app:layout_constraintBottom_toTopOf="@+id/restartButton" app:layout_constraintBottom_toTopOf="@+id/multiplayerButton"
app:layout_constraintDimensionRatio="1:1" app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@ -99,60 +79,33 @@
android:id="@+id/gameBoard" android:id="@+id/gameBoard"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="#A3937D" android:background="@color/game_board_background"
android:padding="4dp" android:padding="@dimen/padding_game_board"
app:columnCount="4" app:columnCount="4"
app:rowCount="4"> app:rowCount="4" />
</androidx.gridlayout.widget.GridLayout>
</androidx.cardview.widget.CardView> </androidx.cardview.widget.CardView>
<Button <Button
android:id="@+id/restartButton" android:id="@+id/multiplayerButton"
style="?android:attr/buttonBarButtonStyle" style="@style/LargeButtonStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:text="@string/multiplayer"
android:layout_marginTop="16dp" app:layout_constraintBottom_toTopOf="@+id/buttons_layout"
android:layout_marginEnd="16dp"
android:backgroundTint="#4A443C"
android:text="@string/restart"
android:textColor="#FFFFFF"
app:layout_constraintBottom_toTopOf="@+id/statsButton"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/gameBoardContainer" /> app:layout_constraintTop_toBottomOf="@+id/gameBoardContainer" />
<Button
android:id="@+id/statsButton"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="16dp"
android:backgroundTint="#4A443C"
android:text="@string/stats"
android:textColor="#FFFFFF"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/menuButton"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent" />
<Button <include
android:id="@+id/menuButton" android:id="@+id/buttons_layout"
style="?android:attr/buttonBarButtonStyle" 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_marginStart="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:backgroundTint="#4A443C"
android:text="@string/menu"
android:textColor="#FFFFFF"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/statsButton" /> app:layout_constraintStart_toStartOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,39 @@
<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">  
<Button
android:id="@+id/restartButton"
style="@style/ButtonStyle"
android:text="@string/restart"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/statsButton"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
<Button
android:id="@+id/statsButton"
style="@style/ButtonStyle"
android:text="@string/stats"
app:layout_constraintStart_toEndOf="@+id/restartButton"
app:layout_constraintEnd_toStartOf="@+id/menuButton"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
<Button
android:id="@+id/menuButton"
style="@style/ButtonStyle"
android:text="@string/menu"
app:layout_constraintStart_toEndOf="@+id/statsButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,7 +0,0 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.Best2048" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your dark theme here. -->
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
</style>
</resources>

View File

@ -2,4 +2,24 @@
<resources> <resources>
<color name="black">#FF000000</color> <color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color> <color name="white">#FFFFFFFF</color>
<color name="text_tile_low">#776E65</color> </resources> <color name="text_tile_low">#776E65</color>
<color name="text_tile_high">#F9F6F2</color>
<color name="background_color">#FCFAEE</color>
<color name="game_label_background">#EDCC5F</color>
<color name="score_label_background">#F75E3E</color>
<color name="game_board_background">#A3937D</color>
<color name="button_background">#4A443C</color>
<color name="tile_empty_color">#C9BCAC</color>
<color name="tile_2_color">#EEE4DA</color>
<color name="tile_4_color">#EDE0C8</color>
<color name="tile_8_color">#F2B179</color>
<color name="tile_16_color">#F59563</color>
<color name="tile_32_color">#F67C5F</color>
<color name="tile_64_color">#F65E3B</color>
<color name="tile_128_color">#EDCF72</color>
<color name="tile_256_color">#EDCC61</color>
<color name="tile_512_color">#EDC850</color>
<color name="tile_1024_color">#EEC43F</color>
<color name="tile_2048_color">#EEC43F</color>
<color name="tile_super_color">#3C3A32</color>
</resources>

View File

@ -0,0 +1,11 @@
<resources>
<dimen name="padding_general">16dp</dimen>
<dimen name="margin_between_elements">8dp</dimen>
<dimen name="text_size_game_label">48sp</dimen>
<dimen name="text_size_score_label">18sp</dimen>
<dimen name="corner_radius">6dp</dimen>
<dimen name="padding_game_board">4dp</dimen>
<dimen name="tile_margin">4dp</dimen> <dimen name="text_size_tile_small">24sp</dimen>
<dimen name="text_size_tile_medium">20sp</dimen>
<dimen name="text_size_tile_large">16sp</dimen>
</resources>

View File

@ -1,7 +1,10 @@
<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="high_score">High Score :\n0</string> <string name="restart">Restart</string> <string name="score">Score :\n0</string>
<string name="high_score">High Score :\n0</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>
</resources> </resources>

View File

@ -0,0 +1,39 @@
<resources>
<style name="Base.Theme.Best2048" parent="Theme.Material3.DayNight.NoActionBar">
</style>
<style name="Theme.Best2048" parent="Base.Theme.Best2048" />
<style name="ScoreLabelStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">0dp</item>
<item name="android:layout_weight">1</item>
<item name="android:background">@color/score_label_background</item>
<item name="android:gravity">center</item>
<item name="android:padding">8dp</item>
<item name="android:textColor">@color/white</item>
<item name="android:textSize">@dimen/text_size_score_label</item>
</style>
<style name="ButtonStyle">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:backgroundTint">@color/button_background</item>
<item name="android:textColor">@color/white</item>
<item name="android:layout_marginBottom">@dimen/padding_general</item>
<item name="android:layout_marginTop">@dimen/padding_general</item>
<item name="android:layout_marginStart">@dimen/padding_general</item>
<item name="android:layout_marginEnd">@dimen/padding_general</item>
<item name="android:buttonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
</style>
<style name="LargeButtonStyle" parent="ButtonStyle">
<item name="android:layout_marginTop">@dimen/padding_general</item>
<item name="android:layout_marginBottom">@dimen/padding_general</item>
<item name="android:background">@drawable/button_multiplayer_background</item> <item name="android:textColor">@color/white</item>
<item name="android:textAllCaps">true</item>
<item name="android:textStyle">bold</item>
<item name="android:textSize">20sp</item>
</style>
</resources>

View File

@ -1,9 +0,0 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.Best2048" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your light theme here. -->
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
</style>
<style name="Theme.Best2048" parent="Base.Theme.Best2048" />
</resources>