May 19, 2024

Wiki

Python

Aide

edit SideBar

Search

Plateau Jeu

Objectifs et prérequis

Ce TP s'inspire du livre "Hello, Android: Introducing Google's Mobile Development Platform (Broché)". On y crée l'activité GridActivity contrôlant la grille principale du jeux de sudoku gridview (xml) et son modèle JeuxModel. Avant tout, reprendre le projet sudoku précédent.

Le modèle : JeuxModele

On mémorise la grille à l'aide d'un tableau grid d'entier de 9 * 9 et la case sélectionnée à l'aide d'une variable entière caseselec. Les valeurs par défaut de ces deux attribut sont définies comme des constantes def_grid et def_sel.

  public class JeuxModel {
	private final int [] def_grid = {0,0,0,0,8,0,0,3,0,8,0,0,1,
         9,0,5,0,0,1,7,0,0,0,0,8,6,0,0,0,0,4,0,0,3,0,0,0,9,0,0,0,0,
         0,1,0,0,0,6,0,0,5,0,0,0,0,3,7,0,0,0,0,9,2,0,0,9,0,6,3,0,0,
         7,0,1,0,0,7,0,0,0,0}; 
	private final int def_sel = 15;
	private int[][] grid = null;
	private int caseselec = def_sel;

Travaux pratiques

Développer les méthodes suivantes:

  1. un constructeur qui alloue le tableau et le remplit avec les valeurs par défaut
  2. setDefault : qui réinitialise les valeurs par défaut
  3. valueAt(int i, int j) qui renvoie sous forme de chaine de caractère le nombre présent dans la case de coordonnées (i,j)
  4. getCaseselec qui retourne caseselec
  5. setCaseselec(int caseX, int caseY) qui mémorise la case sélectionnée donnée par les coordonnées caseX et caseY.

Accéder à l'unique modèle (Singleton)

Le modèle de données doit être partagé entre de nombreuses classes, notamment :

  • l'activité Sudoku qui doit être capable de le réinitialiser
  • l'activité GridActivity qui doit être capable de le modifier pour prendre en compte ce que le joueur a saisi

De plus il ne doit y avoir qu'une seule occurrence de d'objet de type JeuxModele dans l'application. On utilise pour cela le patron Singleton qui garanti ceci simplement comme suit

  public class JeuxModelSingleton {
    private static JeuxModel jm =null;
    private static int jeton = 0;

    public static JeuxModel recup(){
      if (JeuxModelSingleton.jeton == 0){
	  jm = new JeuxModel();
	  jeton = 1;
      }
      return jm; 
    }	

};

Travaux pratiques.

  1. Qu'est ce qui garantit qu'il n'existe qu'une seule instance de JeuxModèle ?
  2. Comment ailleurs dans l'application récupérer l'unique instance ?
  3. Comment ailleurs dans l'application effectuer getCaseselec sur cette unique instance ?
  4. Dans l'activité Sudoku, comment va-t-on réinitialiser le jeux lorsque l'utilisateur appuiera sur nouvelle partie ?
  5. Implanter cette classe et la question précédente.

La vue XML de la grille : gridvue.xml

La vue est définie dans le fichier xml gridvue.xml. Celle-ci peut être construite comme un tableau de trois lignes et trois colonnes où chaque grosse cellule est elle-même un tableau de trois lignes et trois colonnes. Les cellules les plus à l'intérieur sont des TextView. Pour représenter correctement le tableau on peut

  • définir une couleur d'arrière plan pour le tableau et pour chaque Textview
  • étirer au maximum toutes les cellules des tableaux (stretchColumns="*")
  • ajouter des marges autours des tableaux et des Textviews (layout_margin="1dip")
  • augmenter la hauteur des Textviews en augmentant (paddingBottom="@dimen/mb") où mb est une dimension définie dans un fichier xml
  • centrer le text (gravity="center")
  • choisir une police à empatement fixe (typeface="monospace")
 <?xml version="1.0" encoding="utf-8"?>
 <TableLayout
 android:id="@+id/table"
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_height="fill_parent"
 android:layout_width="fill_parent"
 android:background="@color/m_bleu"
 android:stretchColumns="*">
    <TableRow >
      <TableLayout android:layout_margin="1dip" 
      android:stretchColumns="*" android:layout_height="fill_parent">
        <TableRow>
          <TextView android:paddingTop="@dimen/mt" 
          android:paddingBottom="@dimen/mb" android:id="@+id/TextView0"
          android:background="@color/m_noir" android:typeface="monospace"
          android:layout_margin="1dip" android:gravity="center" />
          <TextView android:paddingTop="@dimen/mt" 
          android:paddingBottom="@dimen/mb" android:id="@+id/TextView1"  
          android:background=""@color/mon_noir"" android:typeface="monospace" 
          android:layout_margin="1dip" android:gravity="center" />
          <TextView android:paddingTop="@dimen/mt" 
          android:paddingBottom="@dimen/mb" android:id="@+id/TextView2" 
          android:background="@color/m_noir" android:typeface="monospace" 
          android:layout_margin="1dip" android:gravity="center" />
        </TableRow>
        <TableRow> ... </TableRow> <!-- sec. ligne du premier tableau -->
        <TableRow> ... </TableRow> <!-- tr. ligne du premier tableau -->
      </TableLayout>  
      <TableLayout ...> ... </TableLayout> <!--second tableau -->
      <TableLayout ...> ... </TableLayout> <!--troisi. tableau -->
    </TableRow > 
    <TableRow> ... </TableRow> <!-- seconde ligne -->
    <TableRow> ... </TableRow> <!-- troisi. ligne -->
<TableLayout

Travaux pratiques

Dans le dossier res, créer les fichiers

  1. layout/gridvue.xml : qui complète le fichier ci-dessus
  2. values/dimension.xml : qui définit les dimensions
  3. values/color.xml : qui définit les couleurs

Une Vue modifiable : GridView.java

La vue doit pouvoir se modifier elle-même lorsqu'on sélectionne une case ou bien lorsqu'on saisit un nouveau nombre dans une case. Pour respecter ceci, on crée le pendant en Java du TableLayout déclaré en XML. Cette classe est uniquement composée

  • d'un constructeur
  • d'une méthode onDraw(...) invoquée dès que la vue est invalidée et doit être réaffichée.
  public class GridView extends TableLayout {
    TextView tv[][]= null;

    public GridView(Context context) {
      super(context);
      LayoutInflater li = ((Activity)context).getLayoutInflater();
      li.inflate(R.layout.gridvue, this);

      this.setWillNotDraw(false); 

      this.tv = new TextView[9][9];
      for (int i=0; i< 9 ; i++){
        for (int j=0; j< 9 ; j++){
          String tid = "TextView"+new Integer(i*9+j).toString();
          int resID = getResources().getIdentifier(tid,"id",context.getPackageName());
          tv[i][j] = (TextView) this.findViewById(resID);
        }
      }
    }
@Override
  protected void onDraw(Canvas canvas) {
    for (int i=0; i< 9 ; i++){
      for (int j=0; j< 9 ; j++){
      this.tv[i][j].setText(JeuxModelSingleton.recup().valueAt(i,j));
      int col = (i*9+j == JeuxModelSingleton.recup().getCaseselec()) ? 
      getResources().getColor(R.color.mon_ocean):
      getResources().getColor(R.color.mon_noir);
      this.tv[i][j].setBackgroundColor(col);
      }	
     }
   }
  }

Travaux Pratiques

  1. Dans le code précédent, quel est l'intérêt d'une variable tv ?
  2. Expliquer chaque instruction du constructeur et de la méthode onDraw
  3. implanter la classe GridView

GridActivity : l'activité gérant la grille

Il ne reste plus qu'à construire l'activité demandant l'affichage de la grille : GridActivity. Comme toute activité, elle contient une méthode onCreate(...) et puisqu'elle gère la grille, elle est capable de récupérer les événements de type pression sur l'écran.

Les méthodes

L'activité contient un attribut v qui est de type GridView. La méthode onCreate instancie v et définie sa vue comme étant v.

La méthode onTouchEvent(MotionEvent event) vise à récupérer les événements dont l'action est MotionEvent.ACTION_DOWN. Le cas échéant, elle effectue le traitement suivant :

  1. récupération de coordonnées de l'événement: event.getX(), event.getY()
  2. modification du modèle, particulièrement la case sélectionnée
  3. invalide la vue : this.v.invalidate(). Dans ce cas, la vue se redessine automatiquement en appelant la méthode onDraw()

Travaux pratiques

  1. Implanter la classe GridVue;
  2. Exécuter le programme android de sudoku;
  3. vérifier la robustesse du développement vis à vis du cycle de vie des activités android.

Page Actions

Recent Changes

Group & Page

Back Links