card_game_vector

Table des matières

Le but de cet exercice est, dans un premier temps, de manipuler les vecteurs de la STL. Puis, vous utiliserez le framework GoogleTest pour faire les tests unitaires.

1 Partie 1 : Manipulation des vecteurs

Nous supposons qu'il y a une partie de coinche en cours entre deux joueurs : vous et l'ordinateur. L'idée est de savoir, pour une configuration donnée (c'est-à-dire une carte jouée par votre adversaire et les cartes de votre main), si vous allez prendre le pli ou pas. Pour ceux qui ne connaissent pas du tout la coinche, commencez par lire la section 1.4.

1.1 Règles

Les règles de notre jeu de coinche simplifié sont les suivantes:

  1. Vous disposez d'un jeu de 32 cartes.
  2. Vous prenez 8 cartes et l'adversaire pose une carte. Vous ne vous souciez pas du jeu de l'adversaire. En d'autres termes, cette carte est sélectionnée aléatoirement parmi les 24 cartes restantes.
  3. L'atout est choisi au hasard.
  4. Si vous avez au moins une carte de la même couleur :
    1. Si vous avez plusieurs cartes de valeurs supérieures, vous mettez la plus proche de la valeur de la carte posée et vous gagnez le pli.
    2. Sinon vous mettez la carte la plus petite (il en va de même si la carte posée est un atout) et vous perdez le pli.
  5. Si vous n'avez pas de carte de la même couleur et que vous avez des atouts, vous mettez le plus petit atout et vous gagnez le pli.
  6. Sinon vous mettez la carte la plus petite d'une autre couleur (si, par exemple, vous avez deux mêmes cartes de deux couleurs différentes (disons des septs), on suppose, par souci de simplicité, que coeur < carreau < pique < trefle. Dans ce cas vous perdez le pli.

Le but n'est pas de savoir qui gagne la partie. L'idée est de partir d'une configuration de base, c'est-à-dire une carte jouée et 8 cartes dans votre main et de savoir qui prend le pli. Ce qui signifie qu'il y aura un seul tour (et donc que vous ne jouerez pas vos 8 cartes).

1.2 Etapes

Les étapes du jeu sont les suivantes :

  1. Construire le jeu de carte
  2. Mélanger le jeu
  3. Tirer les huit premières cartes
  4. Choisir un atout au hasard et mettre à jour les valeurs des cartes (14 pour le 9 et 20 pour le valet).
  5. Tirer la 9e carte (parmi les 24 qui restent) qui sera jouée par l'adversaire.
  6. Jouer une carte en respectant les règles décrite ci-dessus.
  7. Afficher le gagnant de la manche.

1.3 Détails d'implémentation

Commencez par créer un projet Console que vous appellerez Coinche. Un fichier Coinche.h vous est fourni ici. Vous pouvez l'étendre, mais pas modifier les prototypes des fonctions. Pour information, afin d'ajouter un fichier Coinche.h à votre projet Coinche, il suffit de faire un clic droit sur le projet Coinche (au niveau de l'explorateur de solution) -> add -> new item -> header file et donnez Coinche.h en nom. Copier les prototypes de fonctions et ce que vous jugez nécessaires dans ce fichier

Afin de représenter le jeu de cartes, vous utiliserez un vecteur. Chaque case du vecteur est une carte représentée par une structure. La structure est composée de :

  • La couleur de la carte représentée par un enum (coeur, carreau, pique, trefle)
  • La force de la carte représentée par un enum ("sept", "huit", …", "dame", "roi", "as")
  • Une valeur représentant le nombre de points (0, 0, …, 3, 4, 11). Notez que les points du 9 et du valet doivent être mis à jour si leur couleur est celle de l'atout.

1.4 Règle complète de la coinche (pour ceux qui n'y ont jamais joué)

Règle de la coinche (l'explication pour 2 joueurs seulement) :

  • 32 cartes, 8 cartes dans une main.
  • Les valeurs des cartes sont : 7, 8, 9 -> 0, 10 -> 10, Valet -> 2, Dame -> 3, Roi -> 4, As -> 11.
  • Même si 7, 8 et 9 valent 0, si une personne pose un 7 et une personne pose un 8 (de la même couleur) le 8 gagne.
  • Pour chaque partie, il y a une couleur d'atout. Le 9 et le Valet ont des valeurs différences dans ce cas (14 pour le 9 et 20 pour le valet). L'atout peut se jouer comme n'importe quelle autre carte. De plus, c'est une carte qu'on peut jouer lorsqu'on n'a pas une carte de la même couleur que la carte jouée et permet de prendre la main. Notez que si un atout est posé, le 2e joueur est obligé de mettre un atout d'une valeur supérieure lorsqu'il en a un.
  • Supposons que le joueur A pose une carte :
    1. Si le joueur B pose une carte de la même couleur, et qu'elle a une valeur supérieure, il prend le pli
    2. Sinon il perd le pli
    3. Si le joueur B n'a pas de carte de la même couleur, et qu'il a un atout, il pose son atout, et prend le pli.
    4. Si le jouer B n'a ni atout, ni carte de la même couleur, il joue une carte d'une autre couleur et perd le pli.

2 Partie 2 : Utilisation de GoogleTest

Dans cette section, nous allons mettre en oeuvre des tests unitaires.

2.1 Installation de l'environnement de tests unitaires

  • Décompressez l'archive SampleGoogleTest.zip dans le répertoire de votre choix (par exemple, dans C:\users\votre_login\CSC4526).
  • Exploitez le canevas de projet obtenu selon la procédure cmake de ce document.
  • Exécutez le test unitaire présent dans le canevas en exécutant la procédure Google Test de ce document.
  • Avant que vous n'écriviez vos propres tests unitaires, voyons comment tout cet environnement a été mis en place.

2.2 Présentation de l'environnement mis en place par cmake

Cette section décrit l'environnement mis en place par cmake :

  • CoincheAvecGoogleTest\CMakeLists.txt
    • déclare les 3 répertoires src, unitTests et mainLauncher dont nous nous servirons pour le codage de l'exercice.
  • Le répertoire src contient tous les sources (.h et .cpp) de notre application. CoincheAvecGoogleTest\src\CMakeLists.txt permet d'indiquer que nous utiliserons tous ces sources (définition et initialisation de la variable SOURCES par l'instruction (GLOB... CONFIGURE_DEPENDS...) et son utilisation dans l'instruction add_library()) pour générer la bibliothèque statique src (instruction add_library()). L'inclusion des fichiers sources par d'autres projets est rendue possible par l'(instruction target_include_directories). Le répertoire src ne contient pas de fichier codant la fonction C++ main(), mais un fichier myMain.h contenant la déclaration de la fonction myMain() et un fichier myMain.cpp contenant sa définition.
// Fichier myMain.h
#pragma once
int monMain();
// Fichier myMain.cpp
#include "monMain.h"
int monMain()
{
    // Inserer ici le code a appeler par myMain(). NB : rien a faire pour le present exercice.
    return 0; 
}
  • Le répertoire unitTests contient les tests unitaires. Dans ce répertoire, vous n'aurez besoin que de modifier unitTests.cpp. Après avoir été téléchargé GoogleTest, CoincheAvecGoogleTest\unitTests\CMakeLists.txt définit cet environnement de tests avec les instructionss add_executable() et add_test(). De plus, il indique que l'exécutable unitTests est contruit à l'aide des bibliothèques gtest, gtest_main et src (cf. les deux instructions target_link_libraries()). Notez que :
    1. Ces instructions target_link_libraries() permettent également d'indiquer à cmake qu'il doit générer les directives pour que le compilateur puisse retrouver les fichier d'include de googletest et src.
    2. La bibliothèqe gtest_main contient une fonction main(). C'est pourquoi nous avons sorti la fonction main() des fichiers sources de src. Ainsi, au moment de l'édition de liens entre les bibliothèques de googletest et la bibliothèque src, nous avons bien une seule fonction main().
  • Le répertoire mainLauncher contient le fichier mainLauncher.cpp. Ce fichier définit une fonction main() qui est chargé d'appeler la fonction myMain(). Grâce à l'instruction add_executable, CoincheAvecGoogleTest\unitTests\CMakeLists.txt spécifie la génération de l'exécutable mainLauncher en utilisant la bibliothèque src (cf. instruction target_link_libraries), src contenant la définition de la fonction myMain().
// Fichier mainLauncher.cpp
#include "myMain.h"
int main()
{
    return myMain();
}
  • L'exécution de la commande cmake dans le répertoire build permet de configurer les différents projets Visual Studio de votre application en configurant correctement les chemins d'accès aux répertoires d'include et aux bibliothèques utilisés.

2.3 Création de tests

Créez Coinche.h et Coinche.cpp dans le répertoire src. Recopiez dans ces fichiers le contenu des fichiers de votre projet Coinche initial.

Dans Coinche.cpp, renommez main() en myMain().

Dans l'explorateur de solutions, cliquez droit sur mainLauncher, puis sélectionnez "Définir comme projet par défaut". Ensuite, exécutez votre application et vérifier qu'elle fonctionn comme précédemment.

Mettez à jour le fichier unitTests\unitTests.cpp avec quelques tests, comme par exemple : exemple de test est présenté ci-dessous

  /* Test : la valeur du 9 d'atout est 14*/
TEST(TestAtout, TestUpdate9Atout)
{
	card played;
	std::vector<card> jeu(1);
	std::vector<card> deck(0);
	Couleur atout = pique;
	jeu[0].force = neuf;
	jeu[0].value = 0;
	jeu[0].couleur = pique;
	update_values(atout, deck, jeu);
	EXPECT_EQ(14, jeu[0].value);
}