Feat: Liaison UI-Logique et gestion des swipes

- Modification de MainActivity:
  - Récupération des vues (GridLayout, TextViews).
  - Implémentation de initGameBoardLayout et updateUI pour dessiner la grille
    en fonction de l'état de Game.
  - Création et attachement de OnSwipeTouchListener pour gérer les swipes.
- Modification de Game:
  - Ajout des getters: getGameBoard, getScore, getHighScore (placeholder).
- Création de OnSwipeTouchListener.java pour la détection des gestes.
This commit is contained in:
Augustin ROUX 2025-04-03 19:11:52 +02:00
parent 7eb597650c
commit 84ca7f9fc3
4 changed files with 248 additions and 50 deletions

View File

@ -37,6 +37,7 @@ dependencies {
implementation(libs.material)
implementation(libs.activity)
implementation(libs.constraintlayout)
implementation(libs.gridlayout)
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)

View File

@ -1,8 +1,9 @@
package legion.muyue.best2048;
import android.util.Log;
import java.util.ArrayList;
import java.util.Random;
import android.util.Log;
public class Game {
@ -15,6 +16,19 @@ public class Game {
random = new Random();
}
public int getGameBoard(int x, int y) {
return gameBoard[x][y];
}
public int getScore() {
return score;
}
public int getHighScore() {
return 0; // TODO: Implémentez la logique du meilleur score plus tard
}
// La méthode printArray est toujours présente dans l'extrait de Game.java pour l'étape 8
public void printArray() {
for (int[] row : gameBoard) {
String rowString = String.format("%6d%6d%6d%6d%n", row[0], row[1], row[2], row[3]);
@ -132,36 +146,35 @@ public class Game {
}
public void pushLeft() {
Log.d("Game", "Pushing Left"); // Pour le débogage
boolean[] alreadyCombined = new boolean[4]; // Tableau par ligne cette fois
Log.d("Game", "Pushing Left");
boolean[] alreadyCombined = new boolean[4];
for (int x = 0; x < 4; x++) { // Itère sur les *lignes* d'abord
alreadyCombined = new boolean[4]; // Réinitialise pour chaque ligne
for (int y = 1; y < 4; y++) { // Itère sur les *colonnes*, en commençant par la deuxième
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; // Suit la colonne
int currentY = y;
// Déplace vers la gauche
while (currentY > 0 && gameBoard[x][currentY - 1] == 0) {
currentY--;
}
if (currentY == 0) { // Arrivé tout à gauche
if (currentY == 0) {
gameBoard[x][0] = value;
if(currentY != y)
gameBoard[x][y] = 0;
} else if (gameBoard[x][currentY - 1] != value) { // Case à gauche différente
} else if (gameBoard[x][currentY - 1] != value) {
gameBoard[x][currentY] = value;
if(currentY != y)
gameBoard[x][y] = 0;
} else if (!alreadyCombined[currentY - 1]) { // Case à gauche identique et non fusionnée
gameBoard[x][currentY - 1] *= 2; // Fusionne
} else if (!alreadyCombined[currentY - 1]) {
gameBoard[x][currentY - 1] *= 2;
score += gameBoard[x][currentY - 1];
gameBoard[x][y] = 0;
alreadyCombined[currentY - 1] = true; // Marque comme fusionné
} else { // Case à gauche identique mais déjà fusionnée
gameBoard[x][currentY] = value; // Place à côté
alreadyCombined[currentY - 1] = true;
} else {
gameBoard[x][currentY] = value;
if(currentY != y)
gameBoard[x][y] = 0;
}
@ -171,36 +184,35 @@ public class Game {
}
public void pushRight() {
Log.d("Game", "Pushing Right"); // Pour le débogage
boolean[] alreadyCombined = new boolean[4]; // Tableau par ligne
Log.d("Game", "Pushing Right");
boolean[] alreadyCombined = new boolean[4];
for (int x = 0; x < 4; x++) { // Itère sur les *lignes*
alreadyCombined = new boolean[4]; // Réinitialise pour chaque ligne.
for (int y = 2; y >= 0; y--) { // Itère sur les *colonnes*, de droite à gauche (avant-dernière vers première)
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; // Suit la colonne
int currentY = y;
// Déplace vers la droite
while (currentY < 3 && gameBoard[x][currentY + 1] == 0) {
currentY++;
}
if (currentY == 3) { // Arrivé tout à droite
if (currentY == 3) {
gameBoard[x][3] = value;
if (currentY != y)
gameBoard[x][y] = 0;
} else if (gameBoard[x][currentY + 1] != value) { // Case à droite différente
} else if (gameBoard[x][currentY + 1] != value) {
gameBoard[x][currentY] = value;
if(currentY != y)
gameBoard[x][y] = 0;
} else if (!alreadyCombined[currentY + 1]) { // Case à droite identique et non fusionnée
gameBoard[x][currentY + 1] *= 2; // Fusionne
} else if (!alreadyCombined[currentY + 1]) {
gameBoard[x][currentY + 1] *= 2;
score += gameBoard[x][currentY + 1];
gameBoard[x][y] = 0;
alreadyCombined[currentY + 1] = true; // Marque comme fusionné
} else { // Case à droite identique mais déjà fusionnée
gameBoard[x][currentY] = value; // Place à côté
alreadyCombined[currentY + 1] = true;
} else {
gameBoard[x][currentY] = value;
if (currentY != y)
gameBoard[x][y] = 0;
}

View File

@ -1,41 +1,154 @@
package legion.muyue.best2048;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.Gravity;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.gridlayout.widget.GridLayout;
public class MainActivity extends AppCompatActivity {
private GridLayout gameBoardLayout;
private TextView scoreTextView;
private TextView highScoreTextView;
private Game game;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Game game = new Game();
gameBoardLayout = findViewById(R.id.gameBoard);
scoreTextView = findViewById(R.id.scoreLabel);
highScoreTextView = findViewById(R.id.highScoreLabel);
// Initialisation et tests des quatre directions
game.addNewNumbers();
game.addNewNumbers();
game.addNewNumbers();
game.printArray(); // Grille initiale
game = new Game();
game.pushUp();
game.printArray(); // Après pushUp
initGameBoardLayout();
game.addNewNumbers();
game.printArray(); // Avant pushDown
game.pushDown();
game.printArray(); // Après pushDown
game.addNewNumbers();
game.printArray(); // Avant pushLeft
game.pushLeft();
game.printArray(); // Après pushLeft
game.addNewNumbers();
game.printArray(); // Avant pushRight
updateUI();
game.pushRight();
game.printArray(); // Après pushRight
// Ajout des listeners de swipe
setupSwipeListener();
}
private void initGameBoardLayout() {
gameBoardLayout.removeAllViews();
gameBoardLayout.setColumnCount(4);
gameBoardLayout.setRowCount(4);
}
private void updateUI() {
gameBoardLayout.removeAllViews(); // Efface les tuiles précédentes
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);
// Choisir le bon drawable en fonction de la valeur
int drawableId;
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();
params.width = 0;
params.height = 0;
params.rowSpec = GridLayout.spec(x, 1f);
params.columnSpec = GridLayout.spec(y, 1f);
params.setMargins(10, 10, 10, 10); // Marges codées en dur selon l'extrait
tileTextView.setLayoutParams(params);
gameBoardLayout.addView(tileTextView);
}
}
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
}
private void setupSwipeListener() {
gameBoardLayout.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this) {
@Override
public void onSwipeTop() {
game.pushUp();
game.addNewNumbers();
updateUI();
}
@Override
public void onSwipeBottom() {
game.pushDown();
game.addNewNumbers();
updateUI();
}
@Override
public void onSwipeLeft() {
game.pushLeft();
game.addNewNumbers();
updateUI();
}
@Override
public void onSwipeRight() {
game.pushRight();
game.addNewNumbers();
updateUI();
}
});
}
}

View File

@ -0,0 +1,72 @@
package legion.muyue.best2048;
import android.content.Context;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
public class OnSwipeTouchListener implements View.OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener(Context ctx) {
gestureDetector = new GestureDetector(ctx, new GestureListener());
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
result = true;
}
} else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeBottom();
} else {
onSwipeTop();
}
result = true;
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeTop() {
}
public void onSwipeBottom() {
}
}