Le juste Prix, ma première application en kotlin

Waouh ! c’est fou, le bonheur que ça procure de réaliser sa propre application ! Ce qui encore plus fou c’est que je n’ai pas vu le temps passer. Je me suis surpassé, je suis aller au-delà des obstacles. J’ai même pris le temps de réaliser une deuxième version de ma première application. Une version qui pour moi est la plus aboutie , une version qui me ressemble. Je ne dis pas que c’est la meilleure application, je dis simplement que c’est la meilleure application que moi je peux faire en kotlin actuellement. Lancez-vous en toute confiance, vous verrez, vous serez fiers de vous. Cette deuxième version, ma permis de poursuivre l’apprentissage des connaissances que je vous avais introduites dans l’article “Mes découvertes sur kotlin”. En seulement deux semaines,  je commence déjà à assimiler beaucoup de choses. Je ne compte pas m’en arrêter là !

Dans cet article,  je vais vous présenter comment j’ai procédé pour réaliser l’application. Je vais vous expliquer les problèmes que j’ai rencontrés et les solutions que j’ai trouvées pour répondre à ces problèmes.

Le juste-prix

le principe

Si vous connaissez la célèbre émission animée par Vincent Lagaffe alors l’application va vous parler. c’est une bonne chose ! L’application reprend le principe du jeu final. Trouvez le plus rapidement le juste prix.

L’application va générer un nombre aléatoire qu’on appellera “juste prix” et l’utilisateur va devoir proposer des propositions de nombre entre 0 et 10000.

– Si l’utilisateur propose un nombre plus grand que le juste-prix, l’application va lui répondre “c’est  moins”

– Inversement, i l’utilisateur propose un nombre plus petit que le juste-prix, l’application va lui répondre “c’est  plus”

l’utilisateur pourra alors proposer autant de proposition, jusqu’à qu’il trouve le juste prix. Dans ce cas l’application, lui dira “Vous avez trouvé le juste prix” et la partie sera terminée. Il pourra relancer une nouvelle partie en proposant une nouvelle proposition de nombre.

les contraintes

Pour rendre le jeu plus juste Winking smile. J’ai mis en place une contrainte pour mieux orienter l’utilisateur : L’utilisateur ne peut pas proposer de nombre inférieur à 0 ou supérieur à 10 000.

La réalisation de l’application

Le visuel de l’application

j’ai commencé ma première séance, par le design de l’application. Entre la première version de l’application et la deuxième et il y a une sacrée différence. Il faut être méthodique ! Il faut avoir des idées claires et précises pour réaliser un bon visuel  sans perdre du temps. Je me rencontre maintenant que je ne l’étais pas. Ça aurait pu être utile de dessiner le design en amont sur une feuille de brouillon. J’ai perdu du temps à réagencer le visuel plusieurs fois. Un temps que j’ai aussi perdu sur la deuxième version de l’application. Au final, je trouve que j’ai quand même un bon résultat et c’est ça le principale.  Voici le visuel des deux applications, dites-moi la version que vous préférez !

Demo_Juste_Prix_V1      Demo_Juste_Prix_V2

Pour la suite de l’article, par souci de meilleure visibilité  je ne vais traiter que la version n°2. Cette version est pour moi la version la plus aboutie. Si vous souhaitez que je traite la version n°1 faite le moi savoir en commentaire, je la rajouterai.

Pour commencer facilement on va définir nos linearLayout pour avoir un visuel séparé en couche.  Si vous ne voyez pas de quoi, je parle je vous invite à aller voir l’article “Comment créer vos premiers composants graphiques ?”.

Visuel_juste_prix_V2_LinearLayout

J’ai décomposé mon application en 3 linearLayout soit  3 couches. Une première couche pour le titre “Trouvez le nombre…”, une deuxième couche pour la validation de la proposition de l’utilisateur et une troisième couche pour les boutons de propositions.

La première couche

Visuel_juste_prix_V2_LinearLayout_couche1

La première couche reste simpliste, une couche avec un titre (un TextView) pour rappeler l’objectif pour l’utilisateur. Si vous avez vu mon précèdent article sur “Comment créer vos premiers composants graphiques ?” vous savez mettre un TextView. En revanche, on va rajouter une petite subtilité. Vous pouvez voir ci-dessous le fichier XML pour la première couche.

Couche 1

<android.widget.LinearLayout
xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:tools=”http://schemas.android.com/tools”
xmlns:app=”http://schemas.android.com/apk/res-auto”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:weightSum=”100″
android:orientation=”vertical”
tools:context=”.MainActivity”>

<LinearLayout
android:orientation=”vertical”
android:layout_width=”match_parent”
android:layout_height=”0dp”
android:layout_weight=”20″>
<TextView
android:text=”@string/PRIX”
android:gravity=”center”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:id=”@+id/textView” android:textStyle=”bold” android:textSize=”24sp”
/>
</LinearLayout>

Vous pouvez observer qu’il y a un petit changement pour le paramètre “texte” la valeur correspond à “@string/PRIX “. Ici nous avons défini un raccourci vers la valeur de notre paramètre, dans un autre fichier XML (voir l’image ci-dessous).

fichier_xml_string

Mais pourquoi fait tu ça ? bonne question ! placer nos textes dans un autre fichier XML va permettre à notre application d’être indépendant à la langue, à la taille de l’écran ou à l’orientation de l’écran. il serait inutile de créer une application pour chaque langue, ça prendrait du temps. Au lieu de ça, on passera par un fichier XML  différent selon un cas précis (langue anglaise par exemple). Nous verrons ça dans un prochain article. Dans notre cas, ça n’a pas d’intérêt c’est seulement pour vous exprimer les possibilités immenses d’une application.

Fichier xml string

<resources>
<string name=”app_name”>Juste Prix</string>
<string name=”PRIX”>Trouvez le nombre entre 0 et 10000</string>
<string name=”Valider”>Valider</string>
</resources>

La deuxième couche

Visuel_juste_prix_V2_LinearLayout_couche2

La deuxième couche va contenir l’affichage de la proposition de l’utilisateur et le bouton de validation de cette proposition. lorsque l’utilisateur viendra cliquer sur le bouton, l’application viendra comparer le nombre proposé par l’utilisateur au juste-prix généré aléatoirement.

Couche 2

<LinearLayout
android:orientation=”vertical”
android:layout_width=”match_parent”
android:layout_height=”0dp”
android:layout_weight=”30″
android:paddingLeft=”10dp”
android:paddingRight=”10dp”>
<LinearLayout
android:orientation=”horizontal”
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:background=”@android:color/holo_blue_dark”>

<TextView
android:layout_width=”match_parent”
android:textSize=”22dp”
android:layout_height=”wrap_content”
android:textAlignment=”center”
android:id=”@+id/MonNombre”
android:textStyle=”bold”/>
</LinearLayout>
<Button
android:text=”@string/Valider”
android:layout_gravity=”center”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” android:id=”@+id/buttonValider” android:textStyle=”bold”
android:textSize=”18sp”/>
</LinearLayout>

La troisième couche

Visuel_juste_prix_V2_LinearLayout_couche3

La troisième couche porte un aspect de grille ou de tableau. Les couches se superposent les unes dans les autres et forment ce clavier tactile . Les boutons permettent  de diminuer au d’augmenter le nombre proposer par l’utilisateur. Pour réaliser ce tableau, il faut dans un premier temps placer une couche principale horizontale (linearlayout). Cette couche horizontale va permettre de former les colonnes. Dans ces colonnes on va placer un linearlayout vertical pour former les lignes du tableau. Voilà, la grille est formée ! Pour finir ils vous restent à placer les boutons dans les linearlayout verticales. Les boutons se placeront alors de façon verticale c’est-à-dire les uns en dessous des autres.

Couche 3

<LinearLayout
android:orientation=”horizontal”
android:layout_width=”match_parent”
android:layout_height=”0dp”
android:layout_weight=”50″
android:weightSum=”100″>

<LinearLayout
android:orientation=”vertical”
android:layout_width=”0dp”
android:layout_height=”match_parent”
android:layout_weight=”20″>
<Button
android:text=”+5000″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/p5000″/>
<Button
android:text=”+1000″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/p1000″/>
<Button
android:text=”+200″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/p200″/>
<Button
android:text=”+50″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/p50″/>
<Button
android:text=”+5″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/p5″/>
</LinearLayout>
<LinearLayout
android:orientation=”vertical”
android:layout_width=”0dp”
android:layout_height=”match_parent”
android:layout_weight=”25″>
<Button
android:text=”+2000″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/p2000″/>
<Button
android:text=”+500″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/p500″/>
<Button
android:text=”+100″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/p100″/>
<Button
android:text=”+10″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/p10″/>
<Button
android:text=”+1″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/p1″/>
</LinearLayout>
<LinearLayout
android:orientation=”vertical”
android:layout_width=”0dp”
android:layout_height=”match_parent”
android:layout_weight=”25″>
<Button
android:text=”-5000″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/m5000″/>
<Button
android:text=”-1000″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/m1000″/>
<Button
android:text=”-200″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/m200″/>
<Button
android:text=”-50″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/m50″/>
<Button
android:text=”-5″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/m5″/>
</LinearLayout>
<LinearLayout
android:orientation=”vertical”
android:layout_width=”0dp”
android:layout_height=”match_parent”
android:layout_weight=”25″>
<Button
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/m2000″ android:text=”-2000″/>
<Button
android:text=”-500″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/m500″/>
<Button
android:text=”-100″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/m100″/>
<Button
android:text=”-10″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/m10″/>
<Button
android:text=”-1″
android:layout_width=”match_parent”
android:layout_height=”wrap_content” android:id=”@+id/m1″/>
</LinearLayout>

Le code de l’application

Le code de l’application reste simple, une classe qu’on appelle activité. Cette classe permet d’interagir avec les composants graphiques de l’application. La fonction OnCreate est à la fonction principale de l’activité c’est elle qui va associer les variables aux composants graphiques de l’application et d’effectuer les appelle aux autres méthodes. Avant de vous présenter la fonction Oncreate, je vais vous parler des variables globales et les autres méthodes que j’ai mises en place.

code_justeprix

Les variables globales

variable_globale_juste_prix

Les variables globales sont globales à une classe, elles pourront être appelées par n’importe quel moment dans n’importe quelle méthode de cette classe. Dans mon précèdent article, je vous avais fait part que je rencontrais des problèmes sur mon application. Ces problèmes étaient dus à l’initialisation de certaines variables, notamment les variables liées aux composants graphiques (button, TextView). Je me suis aperçu que la déclaration de ces variables avec leurs initialisations (déclaration avec une valeur par défaut) en dehors de la fonction onCreate, posait  problème et faisait crasher l’application. Ces variables particulières on besoin d’être initialisées mais ne peuvent être initialisées seulement dans la méthode onCreate.

Malheureusement, j’ai besoin de déclarer ces variables en dehors d’une fonction pour que je puisse les appeler dans d’autres méthodes. Problématique n’est ce pas ? Après quelle recherche, j’ai finalement trouvé la solution, le mot-clé “lateinit”.  Ce mot-clé permet de faire comprendre à l’application que la variable déclarée sera initialisée plus tard. J’ai donc placé ce mot-clé devant mes variables (mon TextView et mon button) et j’ai ensuite initialisé ces deux variables dans la fonction OnCreate. Le tour est joué, l’application fonctionne de nouveau.

Code

class MainActivity : AppCompatActivity() {

//Variable Globale
lateinit var monNombre:TextView
lateinit var ButonValider:Button
var JustePrix:Int = 0
var prix:Int = 0

}

La variable monNombre est du type textview elle va me permettre d’interagir sur la valeur du chiffre que proposera l’utilisateur (modifier ou lire le nombre pour le comparer).

la variable ButtonValider est du type Button elle va me permettre d’interagir sur le bouton pour vérifier et avertir l’utilisateur que le juste-prix a été trouvé ou non.

la variable JustePrix est un entier qui contiendra la valeur du chiffre aléatoire qui restera mystérieux jusqu’à la fin de la partie.

la variable prix est un entier elle permettra de stocker la valeur sous la forme d’un entier de notre variable monNombre.

La méthode VerificationPrix

funtion_verificationPrix

Cette méthode permet de placer la condition suivante : la proposition de nombre faite par l’utilisateur ne peut pas être inférieur à 0 et supérieur à 10000. Si la condition est respectée alors on ajoute l’entier positif ou négatif mis en paramètre à notre variable prix.

Code

fun VerificationPrix (ajout:Int) {
if (prix+ajout>=0 && prix+ajout<=10000 )
{
prix+=ajout
}
}

La méthode nombreAleactoire

methode_nombreAleactoire

Cette méthode comme son nom l’indique permet d’initialiser la variable justePrix par un nombre aléatoire.

Code

fun nombreAleactoire() {
val rand = Random()
JustePrix = rand.nextInt(10000)
}

La méthode ModificationPrix

fonction_ModificationPrix

Cette méthode a pour but de modifier la variable prix en fonction de l’identifiant du bouton cliqué. La méthode ModificationPrix demande en paramètre une vue (View). Ce type est une classe, pour être plus précis c’est un objet. Cet objet permet d’appeler un ensemble de méthodes liées à un composant graphique. Pour notre part, l’objet en paramètre sera un de nos boutons. Avec la méthode getId() on va récupérer l’identifiant de ce bouton. À partir de cet identifiant, on va pouvoir déterminer quel bouton a été appelé et venir appeler la méthode VerificationPrix pour modifier notre variable prix. Et pour finir, on met à jour notre textview pour qu’il affiche notre modification.

exemple_fonction_ModificationPrix

Exemple : sur cette ligne, on vérifie que l’identifiant du bouton qui vient d’être cliqué correspond bien à l’identifiant du bouton qui enlève 5000. Si les deux identifiants correspondent alors on appelle la méthode VerificationPrix avec un ajout de –5000 à notre variable prix.

Code

fun ModificationPrix(view: View){
when
{
view.getId() === R.id.p5000 -> VerificationPrix(5000)
view.getId() === R.id.p2000 -> VerificationPrix(2000)
view.getId() === R.id.p1000 -> VerificationPrix(1000)
view.getId() === R.id.p500 -> VerificationPrix(500)
view.getId() === R.id.p200 -> VerificationPrix(200)
view.getId() === R.id.p100 -> VerificationPrix(100)
view.getId() === R.id.p50 -> VerificationPrix(50)
view.getId() === R.id.p10 -> VerificationPrix(10)
view.getId() === R.id.p5 -> VerificationPrix(5)
view.getId() === R.id.p1 -> VerificationPrix(1)

view.getId() === R.id.m5000 -> VerificationPrix(-5000)

view.getId() === R.id.m2000 -> VerificationPrix(-2000)
view.getId() === R.id.m1000 -> VerificationPrix(-1000)
view.getId() === R.id.m500 -> VerificationPrix(-500)
view.getId() === R.id.m200 -> VerificationPrix(-200)
view.getId() === R.id.m100 -> VerificationPrix(-100)
view.getId() === R.id.m50 -> VerificationPrix(-50)
view.getId() === R.id.m10 -> VerificationPrix(-10)
view.getId() === R.id.m5 -> VerificationPrix(-5)
view.getId() === R.id.m1 -> VerificationPrix(-1)
else -> 0
}
monNombre.setText(prix.toString())
}

La méthode VerifierJustePrix

fonction_verifierJustePrix

cette méthode va venir lire le textview, le convertir en entier puis le comparer à la valeur du justePrix. la méthode retournera :

  • La valeur 1 (entier de type int) si la valeur du textView est plus petite que le juste prix
  • La valeur 2 si la valeur est plus grande
  • La valeur 3 si la valeur est égale
Code

fun verifierJustePrix () :Int {
val nombre:String = monNombre.text.toString()
return when {
nombre.toInt()<JustePrix -> 1
nombre.toInt()>JustePrix -> 2
else -> 3
}
}

La méthode JustePrix

Cette méthode s’appuie sur la méthode vérificationPrix. Lorsque qu’on appelle la méthode JustePrix, la méthode affiche sous la forme d’un pop-up un message à l’utilisateur. Le message change selon la valeur renvoyée par la méthode vérificationPrix.

  • Si la valeur est 1 alors le message “C’est plus” s’affichera
  • Si c’est la valeur 2 alors le message “C’est moins” s’affichera
  • Si c’est la valeur 3 alors le message “Vous avez trouvé le juste Prix” s’affichera et le nombre aléatoire changera pour que l’utilisateur puisse de nouveau rejouer.
Code

fun JustePrix () {
val comparateur = verifierJustePrix()
when (comparateur) {
1 -> Toast.makeText(this, “C’est plus”, Toast.LENGTH_LONG).show()
2 -> Toast.makeText(this, “C’est moin”, Toast.LENGTH_LONG).show()
3 -> { Toast.makeText(this, “Vous avez trouver le juste Prix”, Toast.LENGTH_LONG).show()
nombreAleactoire()
}
}
}

La méthode onCreate

Fonction_OnCreate_kotlin

La méthode onCreate est la fonction principale de la classe elle est exécuter au lancement de l’application. Son rôle dans cette application, c’est d’appliquer les 6 étapes ci-dessous :

  1. Appeler la méthode nombreAleactoire pour générer le nombre aléatoire dès la première partie.
  2. Initialisation mon textview avec son identifiant pour pouvoir interagir avec lui.
  3. Déclaration et initialisation de l’ensemble de mes boutons.
  4. Appelle des différentes méthodes setOnClickListener qui vont me permettre d’appeler la méthode JustePrix pour le bouton valider et les méthodes ModificationPrix pour les autres boutons lors d’un clic sur l’un des boutons
  5. La méthode ModificationPrix  va venir modifier la valeur de mon textview
  6. La méthode JustePrix  va venir comparer la proposition de l’utilisateur au juste-prix et lui indiquer si la valeur est plus élevéE, moins élevéE ou si l’utilisateur a trouvé le juste-prix
Code

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

//appelle de la méthode nombreAleactoire pour définir le nombre à trouver
nombreAleactoire()

//initialisation de notre TextView qui contient la prposition de l’utilisateur
monNombre= findViewById(R.id.MonNombre)

//Déclaration et initialisation des boutons qui ajoutent de la valeur
val p5000 = findViewById<Button>(R.id.p5000)
val p2000 = findViewById<Button>(R.id.p2000)
val p1000 = findViewById<Button>(R.id.p1000)
val p500 = findViewById<Button>(R.id.p500)
val p200 = findViewById<Button>(R.id.p200)
val p100 = findViewById<Button>(R.id.p100)
val p50 = findViewById<Button>(R.id.p50)
val p10 = findViewById<Button>(R.id.p10)
val p5 = findViewById<Button>(R.id.p5)
val p1 = findViewById<Button>(R.id.p1)

//Déclaration et initialisation des boutons qui enlève de la valeur
val m5000 = findViewById<Button>(R.id.m5000)
val m2000 = findViewById<Button>(R.id.m2000)
val m1000 = findViewById<Button>(R.id.m1000)
val m500 = findViewById<Button>(R.id.m500)
val m200 = findViewById<Button>(R.id.m200)
val m100 = findViewById<Button>(R.id.m100)
val m50 = findViewById<Button>(R.id.m50)
val m10 = findViewById<Button>(R.id.m10)
val m5 = findViewById<Button>(R.id.m5)
val m1 = findViewById<Button>(R.id.m1)

// un click sur le bouton déclanche la méthode ModificationPrix
//addiction
p5000.setOnClickListener {ModificationPrix(p5000)}
p2000.setOnClickListener {ModificationPrix(p2000)}
p1000.setOnClickListener {ModificationPrix(p1000)}
p500.setOnClickListener {ModificationPrix(p500)}
p200.setOnClickListener {ModificationPrix(p200)}
p100.setOnClickListener {ModificationPrix(p100)}
p50.setOnClickListener {ModificationPrix(p50)}
p10.setOnClickListener {ModificationPrix(p10)}
p5.setOnClickListener {ModificationPrix(p5)}
p1.setOnClickListener {ModificationPrix(p1)}
//soustraction
m5000.setOnClickListener {ModificationPrix(m5000)}
m2000.setOnClickListener {ModificationPrix(m2000)}
m1000.setOnClickListener {ModificationPrix(m1000)}
m500.setOnClickListener {ModificationPrix(m500)}
m200.setOnClickListener {ModificationPrix(m200)}
m100.setOnClickListener {ModificationPrix(m100)}
m50.setOnClickListener {ModificationPrix(m50)}
m10.setOnClickListener {ModificationPrix(m10)}
m5.setOnClickListener {ModificationPrix(m5)}
m1.setOnClickListener {ModificationPrix(m1)}

//initialisation de notre bouton valider
ButonValider = findViewById(R.id.buttonValider)
//un click sur le bouton valider déclenche la méthode justePrix
ButonValider.setOnClickListener {
JustePrix()
}

}

Merci d’avoir lu cet article ! j’espère que cela vous a aidé et je vous invite à partager cet article sur les réseaux sociaux pour qu’il puisse aider d’autres personnes.

Crédit : photo de victorio marasigan

Partager l'article :
  •  
  •  
  •  
  •  
  •  
  • 11
    Partages

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *