begin process at 2013 05 24 21:58:31
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Jeux

 > [C++] DEMINEUR SOUS CONSOLE

[C++] DEMINEUR SOUS CONSOLE


 Information sur la source

Note :
Aucune note
Catégorie :Jeux Classé sous :démineur, console, complet Niveau :Initié Date de création :11/07/2012 Date de mise à jour :11/07/2012 15:30:48 Vu / téléchargé :2 048 / 96

Auteur : zenoobrider

Ecrire un message privé
Commentaire sur cette source (12)
Ajouter un commentaire et/ou une note

 Description

Simple jeu de Démineur qui tourne sous la console.
Je ne l'ai pas du tout optimisé, je voulais juste mettre en application mes quelques connaissances en C++.
Essayez de toujours envoyer une réponse en majuscules à la console ;)

Source

  • //******************
  • //*FICHIER MAIN.CPP*
  • //******************
  • #include <iostream>
  • #include <ctime> // Obligatoire
  • #include <cstdlib> // Obligatoire
  • #include <string>
  • #include "fonctions.hh"
  • #include <fstream>
  • #include <sstream>
  • #include <cmath>
  • #include <vector>
  • #include <algorithm>
  • void header()
  • {
  • std::cout << "\t\t\t *************************\n"
  • "\t\t\t *\t Demineur *\n"
  • "\t\t\t *\t By *\n"
  • "\t\t\t *\t Zenoo *\n"
  • "\t\t\t *************************\n" << std::endl;
  • }
  • std::string stockagePseudo(std::string nomJoueur)
  • {
  • std::cout << std::endl;
  • std::cout << " ****************************************************************\n"
  • " * *\n"
  • " * *\n"
  • " * *\n"
  • " * *\n"
  • " * *\n"
  • " * *\n"
  • " * ** ** ** ** ** ** ** *\n"
  • " ** ** ** ** Entrez votre pseudo (3 lettres) ** ** ** ***\n"
  • " * ** ** ** ** ** ** ** ** *\n"
  • " * *\n"
  • " * *\n"
  • " * *\n"
  • " * *\n"
  • " * *\n"
  • " * *\n"
  • " ****************************************************************\n" << std::endl;
  • std::cin >> nomJoueur;
  • std::cout << std::endl;
  • return nomJoueur;
  • }
  • void menu()
  • {
  • std::cout << " ****************************************************************\n"
  • " * *\n"
  • " * ** ** ** ** ** ** ** *\n"
  • " ** ** ** ** ** ** 1. Nouvelle partie ** ** ** ** ***\n"
  • " * ** ** ** ** ** ** ** ** *\n"
  • " * *\n"
  • " * *\n"
  • " * ** ** ** ** ** ** ** *\n"
  • " ** ** ** ** ** ** 2. Regles du jeu** ** ** ** ** ***\n"
  • " * ** ** ** ** ** ** ** ** *\n"
  • " * *\n"
  • " * *\n"
  • " * ** ** ** ** ** ** ** *\n"
  • " ** ** ** ** ** ** 3. Scores* ** ** ** ** ** ** ***\n"
  • " * ** ** ** ** ** ** ** ** *\n"
  • " * *\n"
  • " ****************************************************************\n" << std::endl;
  • }
  • void nouveauJeu(int positions[12][12], int positionsIf[12][12]) //positions = chiffres de la grille. positionsIf = vérif si joueur a déjà découvert des cases
  • {
  • std::string nomJoueur("---");
  • header();
  • nomJoueur = stockagePseudo(nomJoueur);
  • //INITIALISATION DES VARIABLES ALEATOIRES
  • for (int i(0) ; i<12 ; ++i)
  • {
  • for (int j(0) ; j<12 ; ++j)
  • {
  • positions[i][j] = 0; //Grille initialisée
  • }
  • }
  • int const nbBombes(10);
  • int bomb1[nbBombes];
  • int bomb2[nbBombes];
  • for (int i(0) ; i<10 ; ++i) //Choix des coordonnées des 10 bombes
  • {
  • bomb1[i] = ((rand() % 9)+1);
  • bomb2[i] = ((rand() % 9)+1);
  • }
  • for (int i(0) ; i<10 ; ++i) // Remplit environnement des 10 bombes
  • {
  • for (int n(1) ; n<11 ; ++n)
  • {
  • for (int m(1) ; m<10 ; ++m)
  • {
  • if (bomb1[i] == m && bomb2[i] == n)
  • {
  • ++positions[m-1][n-1];
  • ++positions[m-1][n];
  • ++positions[m-1][n+1];
  • ++positions[m][n-1];
  • positions[m][n]=9;
  • ++positions[m][n+1];
  • ++positions[m+1][n-1];
  • ++positions[m+1][n];
  • ++positions[m+1][n+1];
  • }
  • }
  • }
  • }
  • for (int i(0) ; i<12 ; ++i)
  • {
  • for (int j(0) ; j<12 ; ++j)
  • {
  • positionsIf[i][j] = 0; //INITIALISATION. Si = 1, on dévoile la case soncernée (sera modifiée par la suite)
  • }
  • }
  • //INITIALISATION DE DIVERSES VARIABLES UTILISEES DANS LA BOUCLE
  • std::string reponse("rien");
  • bool gain(true); // Si false, perdu
  • std::string ligneChoisie("null"); //Servira à stocker la ligne choisie par le joueur
  • std::string colonneChoisie("null"); // Servira à stocker la colonne choisie par le joueur
  • int ligneChoisieInt(0), colonneChoisieInt(0);
  • std::string alphabet("ABCDEFGHIJ"), alphabetMin("abcdefghij"); // Servira à faire le passage entre lettres/chiffres
  • int compteurCasesDevoilees(0), pointsGagnes(0);
  • //DEBUT BOUCLE AFFICHAGE TABLEAUX EVOLUTION DEMINEUR
  • while (gain)
  • {
  • //INTERFACE GRAPHIQUE
  • header();
  • std::cout << " ****************************************************************" << std::endl;
  • std::cout << " * *" << std::endl;
  • std::cout << " * A B C D E F G H I J *" << std::endl;
  • //Affichage des 10 lignes
  • for (int j(10) ; j>0 ; --j)
  • {
  • if (j == 10)
  • {
  • std::cout << " * " << j << " ";
  • }
  • else
  • {
  • std::cout << " * " << j << " ";
  • }
  • for (int i(1) ; i<11 ; ++i)
  • {
  • affichage(i, j, positions, positionsIf);
  • std::cout << " ";
  • }
  • std::cout << " *" << std::endl;
  • }
  • std::cout << " * *" << std::endl;
  • std::cout << " * *" << std::endl;
  • std::cout << " * *" << std::endl;
  • std::cout << " ****************************************************************" << std::endl;
  • //Si choix précédent = bombe
  • if (positions[colonneChoisieInt][ligneChoisieInt] >= 9)
  • {
  • // Comptage des points
  • for (int i(1) ; i<11 ; ++i)
  • {
  • for (int j(1) ; j<11 ; ++j)
  • {
  • if (positionsIf[i][j] == 1)
  • {
  • pointsGagnes += 1000;
  • }
  • }
  • }
  • std::cout << " Perdu ! Vous avez gagne " << pointsGagnes << " points !" << std::endl;
  • gain = (false);
  • //Stockage du score
  • std::string const fichier("scores.txt");
  • std::ofstream flux1(fichier.c_str(), std::ios::app);
  • if (flux1) //
  • {
  • flux1 << nomJoueur << " - " << pointsGagnes << std::endl;
  • }
  • else
  • {
  • std::cout << "ERREUR: Impossible d'ouvrir le fichier." << std::endl;
  • }
  • }
  • else
  • {
  • //Si tout le tableau (sauf les bombes) a été dévoilé.
  • compteurCasesDevoilees = 0;
  • for (int i(1) ; i<11 ; ++i)
  • {
  • for (int j(1) ; j<11 ; ++j)
  • {
  • if (positionsIf[i][j] == 1)
  • {
  • ++compteurCasesDevoilees;
  • }
  • }
  • }
  • if (compteurCasesDevoilees == 92)
  • {
  • std::cout << "Bravo, vous avez gagne avec 92.000 points !";
  • gain = (false);
  • pointsGagnes = 92000;
  • //Stockage du score
  • std::string const fichier("scores.txt");
  • std::ofstream flux1(fichier.c_str(), std::ios::app);
  • if (flux1)
  • {
  • flux1 << nomJoueur << " - " << pointsGagnes << std::endl;
  • }
  • else
  • {
  • std::cout << "ERREUR: Impossible d'ouvrir le fichier." << std::endl;
  • }
  • }
  • else
  • {
  • // Choix du joueur
  • std::cout << "Jouez. (de la forme A1, a1, d10 ou D10)" << std::endl;
  • std::cin >> reponse;
  • //Reconnaissance de la ligne choisie
  • ligneChoisie = reponse.substr(1);
  • if (ligneChoisie[0] == 0 )
  • {
  • ligneChoisie = ligneChoisie.substr(1);
  • }
  • else if (ligneChoisie == "10")
  • {
  • ligneChoisie = "10";
  • }
  • else
  • {
  • std::cout << "Choix incorrect." << std::endl;
  • }
  • //Reconnaissance de la colonne choisie
  • std::string stringI("null"); // Equivalent de (int i) en string
  • int j; // = i+1
  • for (int i(0) ; i<10 ; ++i)
  • {
  • j = i + 1;
  • stringI = convertInt(j);
  • if (reponse[0] == alphabet[i] || reponse[0] == alphabetMin[i])
  • {
  • colonneChoisie = stringI;
  • }
  • }
  • colonneChoisieInt=convertString(colonneChoisie);
  • ligneChoisieInt=convertString(ligneChoisie);
  • // Le prochain tableau affichera la case choisie, car dans le tableau positionsIf, une valeur 1 correspond à un affichage du tableau positions au lieu d'un #.
  • positionsIf[colonneChoisieInt][ligneChoisieInt] = 1;
  • }
  • }
  • }
  • }
  • void options()
  • {
  • header();
  • std::cout << " ****************************************************************" << std::endl;
  • std::cout << " * REGLES *" << std::endl;
  • std::cout << " * *" << std::endl;
  • std::cout << " * Le principe est simple. Comme son nom l'indique, le but du *" << std::endl;
  • std::cout << " * jeu est de deminer le terrain, symbolise par une grille. *" << std::endl;
  • std::cout << " * Une fois qu'une zone est decouverte il est possible de *" << std::endl;
  • std::cout << " * deduire la position des mines par rapport aux indications *" << std::endl;
  • std::cout << " * chiffrees donnees par les cases mises a jour. En effet ces *" << std::endl;
  • std::cout << " * cases sont numerotees de 1 a 8. Ce chiffre indique le nombre *" << std::endl;
  • std::cout << " * de mines se trouvant dans les 8 cases entourant celle *" << std::endl;
  • std::cout << " * contentant le chiffre. De cette maniere on peut (en théorie *" << std::endl;
  • std::cout << " * du moins) finir le jeu. *" << std::endl;
  • std::cout << " * La partie est terminee lorque vous avez decouvert toutes les *" << std::endl;
  • std::cout << " * mines du terrain, ou si vous avez malencontreusement pose la *" << std::endl;
  • std::cout << " * souris sur une case minee ! *" << std::endl;
  • std::cout << " * *" << std::endl;
  • std::cout << " ****************************************************************" << std::endl;
  • }
  • //Affichage des scores
  • void scores()
  • {
  • //Comptage nb lignes dans fichier scores.txt
  • int nbLignes(0);
  • nbLignes = nombreLignes();
  • int repeto(0); // Variable de répétition dans boucle while
  • std::string transit("null"); // variable temporaire
  • std::vector<int> tabPoints(nbLignes); // tableau pour stocker les points indiqués dans scores.txt
  • //Lecture de scores.txt et copie des points dans le tableau
  • std::ifstream chemin("scores.txt");
  • if (chemin)
  • {
  • while(getline(chemin, transit))
  • {
  • tabPoints[repeto] = convertString(transit.substr(6));
  • ++repeto;
  • }
  • }
  • else
  • {
  • std::cout << "ERREUR: Impossible d'ouvrir le fichier en lecture. (1)" << std::endl;
  • }
  • //Tableau trié du plus petit au plus grand.
  • std::sort (tabPoints.begin(), tabPoints.end());
  • //STOCKAGE DES PSEUDOS
  • std::string transit2("null"); //Variable de transit
  • std::string tabPseudos[nbLignes];
  • repeto = 0;
  • std::ifstream chemin2("scores.txt");
  • if (chemin2)
  • {
  • while(getline(chemin2, transit2))
  • {
  • tabPseudos[repeto] = transit2.substr(0,3);
  • ++repeto;
  • }
  • }
  • else
  • {
  • std::cout << "ERREUR: Impossible d'ouvrir le fichier en lecture. (2)" << std::endl;
  • }
  • //RATTACHEMENT DES PSEUDOS AUX SCORES CORRESPONDANTS
  • std::string transit3("null"); // Variable temporaire
  • repeto = 0;
  • int substrTransit3(0);
  • if (chemin)
  • {
  • while(getline(chemin, transit3))
  • {
  • substrTransit3 = convertString(transit3.substr(6)); // subsTransit3 = Points de la ligne lue
  • for (int i(nbLignes) ; i>0 ; --i)
  • {
  • if (tabPoints[i] == substrTransit3)
  • {
  • tabPseudos[repeto] = transit3.substr(0,3); // Si points de la ligne lue correspondent aux points de la ligne i du tableau des scores, alors on associe le pseudo de la ligne lue au score.
  • }
  • }
  • ++repeto;
  • }
  • }
  • header();
  • std::cout << " ****************************************************************\n"
  • << " * *\n"
  • << " * ** ** ** ** ** ** ** *\n"
  • << " ** ** ** ** ** ** ** *SCORES ** ** ** ** ** ** ***\n"
  • << " * ** ** ** ** ** ** ** ** *\n";
  • for (int i(1) ; i<11 ; ++i)
  • {
  • if (i ==10)
  • {
  • std::cout << " * " << i << ". " << tabPseudos[nbLignes-i] << " - " << tabPoints[nbLignes-i] << " *\n";
  • }
  • else
  • {
  • std::cout << " * " << i << ". " << tabPseudos[nbLignes-i] << " - " << tabPoints[nbLignes-i] << " *\n";
  • }
  • }
  • std::cout << " * *\n"
  • << " ****************************************************************\n" << std::endl;
  • }
  • int main()
  • {
  • int const taillepositionsi(12);
  • int positions[taillepositionsi][taillepositionsi]; // chiffres de la grille du démineur
  • int positionsIf[taillepositionsi][taillepositionsi]; // 1 ou 0, suivant l'utilisation du joueur
  • srand(time(0));
  • int boucleMenu(0);
  • std::string choix("0");
  • while (boucleMenu==0) //Repeat de la page d'accueil
  • {
  • std::cout << std::endl;
  • header();
  • menu();
  • std::cin >> choix;
  • std::cin.ignore();
  • if (choix=="1")
  • {
  • boucleMenu=1;
  • nouveauJeu(positions, positionsIf); // Affichage du démineur
  • std::cout << " Tapez 0 pour retourner au menu." << std::endl;
  • std::cin >> boucleMenu;
  • }
  • else if (choix=="2")
  • {
  • boucleMenu=2;
  • options();
  • std::cout << " Tapez 0 pour retourner au menu." << std::endl;
  • std::cin >> boucleMenu;
  • }
  • else if (choix=="3")
  • {
  • boucleMenu=3;
  • scores();
  • std::cout << " Tapez 0 pour retourner au menu." << std::endl;
  • std::cin >> boucleMenu;
  • }
  • }
  • return 0;
  • }
  • //***********************
  • //*FICHIER FONCTIONS.CPP*
  • //***********************
  • #include "fonctions.hh"
  • void affichage(int x, int y, int positions[12][12], int positionsIf[12][12])
  • {
  • std::string valeur("0");
  • int valeurDouble; // = valeur
  • if (positionsIf[x][y] == 0) //Joueur n'a pas encore vérifié cette case
  • {
  • valeur = "#";
  • }
  • else if (positionsIf[x][y] == 1) // Joueur a déjà vérifié la case
  • {
  • valeur = convertInt(positions[x][y]);
  • }
  • valeurDouble = convertString(valeur);
  • if (valeurDouble >= 9)
  • {
  • valeur = "°";
  • }
  • std::cout << valeur;
  • }
  • std::string convertInt(int number)
  • {
  • std::stringstream ss;//create a stringstream
  • ss << number;//add number to the stream
  • return ss.str();//return a string with the contents of the stream
  • }
  • int convertString (std::string texte)
  • {
  • int entier(0); // Entier de sortie
  • std::stringstream convert(texte); // stringstream used for the conversion initialized with the contents of Text
  • if ( !(convert >> entier) )//give the value to Result using the characters in the string
  • entier = 0;//if that fails set Result to 0
  • return entier;
  • }
  • int nombreLignes ()
  • {
  • int nombre(0);
  • std::ifstream chemin("scores.txt");
  • if(chemin)
  • {
  • //L'ouverture s'est bien passée. On peut donc lire
  • std::string lignes; //Une variable pour stocker les lignes
  • while(getline(chemin, lignes)) //Tant qu'on n'est pas a la fin, on lit
  • {
  • ++nombre;
  • }
  • }
  • else
  • {
  • std::cout << "ERREUR: Impossible d'ouvrir le fichier en lecture." << std::endl;
  • }
  • return nombre;
  • }
  • //**********************
  • //*FICHIER FONCTIONS.HH*
  • //**********************
  • #ifndef FONCTIONS_H_INCLUDED
  • #define FONCTIONS_H_INCLUDED
  • #include <iostream>
  • #include <ctime> // Obligatoire
  • #include <cstdlib> // Obligatoire
  • #include <string>
  • #include <fstream>
  • #include <sstream>
  • #include <cmath>
  • #include <vector>
  • //Gère l'affichage du dièse ou du chiffre
  • void affichage(int x, int y, int positions[12][12], int positionsIf[12][12]);
  • //Convertit les entiers en strings
  • std::string convertInt(int number);
  • //Convertir les strings en entiers
  • int convertString(std::string texte);
  • //Compte nombre lignes dans un fichier
  • int nombreLignes ();
  • #endif // FONCTIONS_H_INCLUDED
//******************
//*FICHIER MAIN.CPP*
//******************
#include <iostream>
#include <ctime> // Obligatoire
#include <cstdlib> // Obligatoire
#include <string>
#include "fonctions.hh"
#include <fstream>
#include <sstream>
#include <cmath>
#include <vector>
#include <algorithm>


void header()
{
std::cout << "\t\t\t    *************************\n"
             "\t\t\t    *\t     Demineur       *\n"
             "\t\t\t    *\t        By          *\n"
             "\t\t\t    *\t       Zenoo        *\n"
             "\t\t\t    *************************\n" << std::endl;
}

std::string stockagePseudo(std::string nomJoueur)
{
    std::cout << std::endl;
    std::cout << "        ****************************************************************\n"
                 "        *                                                              *\n"
                 "        *                                                              *\n"
                 "        *                                                              *\n"
                 "        *                                                              *\n"
                 "        *                                                              *\n"
                 "        *                                                              *\n"
                 "        *      **      **      **      **      **      **      **      *\n"
                 "        **   **  **  **  Entrez votre pseudo (3 lettres) **  **  **  ***\n"
                 "        *  **      **      **      **      **      **      **      **  *\n"
                 "        *                                                              *\n"
                 "        *                                                              *\n"
                 "        *                                                              *\n"
                 "        *                                                              *\n"
                 "        *                                                              *\n"
                 "        *                                                              *\n"
                 "        ****************************************************************\n" << std::endl;
    std::cin >> nomJoueur;
    std::cout << std::endl;
    return nomJoueur;
}

void menu()
{
    std::cout << "        ****************************************************************\n"
                 "        *                                                              *\n"
                 "        *      **      **      **      **      **      **      **      *\n"
                 "        **   **  **  **  **  **  1. Nouvelle partie  **  **  **  **  ***\n"
                 "        *  **      **      **      **      **      **      **      **  *\n"
                 "        *                                                              *\n"
                 "        *                                                              *\n"
                 "        *      **      **      **      **      **      **      **      *\n"
                 "        **   **  **  **  **  **  2. Regles du jeu**  **  **  **  **  ***\n"
                 "        *  **      **      **      **      **      **      **      **  *\n"
                 "        *                                                              *\n"
                 "        *                                                              *\n"
                 "        *      **      **      **      **      **      **      **      *\n"
                 "        **   **  **  **  **  **  3. Scores*  **  **  **  **  **  **  ***\n"
                 "        *  **      **      **      **      **      **      **      **  *\n"
                 "        *                                                              *\n"
                 "        ****************************************************************\n" << std::endl;
}

void nouveauJeu(int positions[12][12], int positionsIf[12][12]) //positions = chiffres de la grille. positionsIf = vérif si joueur a déjà découvert des cases
{
    std::string nomJoueur("---");
    header();
    nomJoueur = stockagePseudo(nomJoueur);

    //INITIALISATION DES VARIABLES ALEATOIRES
    for (int i(0) ; i<12 ; ++i)
    {
        for (int j(0) ; j<12 ; ++j)
        {
            positions[i][j] = 0;        //Grille initialisée
        }
    }

    int const nbBombes(10);
    int bomb1[nbBombes];
    int bomb2[nbBombes];
    for (int i(0) ; i<10 ; ++i) //Choix des coordonnées des 10 bombes
    {
        bomb1[i] = ((rand() % 9)+1);
        bomb2[i] = ((rand() % 9)+1);
    }

    for (int i(0) ; i<10 ; ++i) // Remplit environnement des 10 bombes
    {
        for (int n(1) ; n<11 ; ++n)
        {
            for (int m(1) ; m<10 ; ++m)
            {
                if (bomb1[i] == m && bomb2[i] == n)
                {
                    ++positions[m-1][n-1];
                    ++positions[m-1][n];
                    ++positions[m-1][n+1];
                    ++positions[m][n-1];
                    positions[m][n]=9;
                    ++positions[m][n+1];
                    ++positions[m+1][n-1];
                    ++positions[m+1][n];
                    ++positions[m+1][n+1];
                }
            }
        }
    }



    for (int i(0) ; i<12 ; ++i)
    {
        for (int j(0) ; j<12 ; ++j)
        {
            positionsIf[i][j] = 0;   //INITIALISATION. Si = 1, on dévoile la case soncernée (sera modifiée par la suite)
        }
    }


    //INITIALISATION DE DIVERSES VARIABLES UTILISEES DANS LA BOUCLE
    std::string reponse("rien");
    bool gain(true); // Si false, perdu
    std::string ligneChoisie("null");  //Servira à stocker la ligne choisie par le joueur
    std::string colonneChoisie("null"); // Servira à stocker la colonne choisie par le joueur
    int ligneChoisieInt(0), colonneChoisieInt(0);
    std::string alphabet("ABCDEFGHIJ"), alphabetMin("abcdefghij"); // Servira à faire le passage entre lettres/chiffres
    int compteurCasesDevoilees(0), pointsGagnes(0);

        //DEBUT BOUCLE AFFICHAGE TABLEAUX EVOLUTION DEMINEUR
    while (gain)
    {
        //INTERFACE GRAPHIQUE
        header();
        std::cout << "        ****************************************************************" << std::endl;
        std::cout << "        *                                                              *" << std::endl;
        std::cout << "        *                      A B C D E F G H I J                     *" << std::endl;
        //Affichage des 10 lignes
        for (int j(10) ; j>0 ; --j)
        {
            if (j == 10)
            {
                std::cout << "        *                   " << j << " ";
            }
            else
            {
                std::cout << "        *                   " << j << "  ";
            }

            for (int i(1) ; i<11 ; ++i)
            {
                affichage(i, j, positions, positionsIf);
                std::cout << " ";
            }
            std::cout << "                    *" << std::endl;
        }
        std::cout << "        *                                                              *" << std::endl;
        std::cout << "        *                                                              *" << std::endl;
        std::cout << "        *                                                              *" << std::endl;
        std::cout << "        ****************************************************************" << std::endl;


        //Si choix précédent = bombe
        if (positions[colonneChoisieInt][ligneChoisieInt] >= 9)
        {
            // Comptage des points
            for (int i(1) ; i<11 ; ++i)
            {
                for (int j(1) ; j<11 ; ++j)
                {
                   if (positionsIf[i][j] == 1)
                   {
                       pointsGagnes += 1000;
                   }
                }
            }
            std::cout << " Perdu ! Vous avez gagne " << pointsGagnes << " points !" << std::endl;
            gain = (false);

            //Stockage du score
            std::string const fichier("scores.txt");
            std::ofstream flux1(fichier.c_str(), std::ios::app);

            if (flux1) //
            {
                flux1 << nomJoueur << " - " << pointsGagnes << std::endl;
            }
            else
            {
                std::cout << "ERREUR: Impossible d'ouvrir le fichier." << std::endl;
            }
        }
        else
        {
            //Si tout le tableau (sauf les bombes) a été dévoilé.
            compteurCasesDevoilees = 0;
            for (int i(1) ; i<11 ; ++i)
            {
                for (int j(1) ; j<11 ; ++j)
                {
                    if (positionsIf[i][j] == 1)
                    {
                        ++compteurCasesDevoilees;
                    }
                }
            }
            if (compteurCasesDevoilees == 92)
            {
                std::cout << "Bravo, vous avez gagne avec 92.000 points !";
                gain = (false);
                pointsGagnes = 92000;

                //Stockage du score
                std::string const fichier("scores.txt");
                std::ofstream flux1(fichier.c_str(), std::ios::app);

                if (flux1)
                {
                    flux1 << nomJoueur << " - " << pointsGagnes << std::endl;
                }
                else
                {
                    std::cout << "ERREUR: Impossible d'ouvrir le fichier." << std::endl;
                }

            }
            else
            {
                // Choix du joueur
                std::cout << "Jouez. (de la forme A1, a1, d10 ou D10)" << std::endl;
                std::cin >> reponse;


                //Reconnaissance de la ligne choisie
                ligneChoisie = reponse.substr(1);

                if (ligneChoisie[0] == 0 )
                {
                    ligneChoisie = ligneChoisie.substr(1);
                }
                else if (ligneChoisie == "10")
                {
                    ligneChoisie = "10";
                }
                else
                {
                    std::cout << "Choix incorrect." << std::endl;
                }

                //Reconnaissance de la colonne choisie
                std::string stringI("null"); // Equivalent de (int i) en string
                int j; // = i+1
                for (int i(0) ; i<10 ; ++i)
                {
                    j = i + 1;
                    stringI = convertInt(j);
                    if (reponse[0] == alphabet[i] || reponse[0] == alphabetMin[i])
                    {
                        colonneChoisie = stringI;
                    }
                }

                colonneChoisieInt=convertString(colonneChoisie);
                ligneChoisieInt=convertString(ligneChoisie);
                // Le prochain tableau affichera la case choisie, car dans le tableau positionsIf, une valeur 1 correspond à un affichage du tableau positions au lieu d'un #.
                positionsIf[colonneChoisieInt][ligneChoisieInt] = 1;
            }
        }
    }
}

void options()
{
    header();
    std::cout << "        ****************************************************************" << std::endl;
    std::cout << "        *                             REGLES                           *" << std::endl;
    std::cout << "        *                                                              *" << std::endl;
    std::cout << "        * Le principe est simple. Comme son nom l'indique, le but du   *" << std::endl;
    std::cout << "        * jeu est de deminer le terrain, symbolise par une grille.     *" << std::endl;
    std::cout << "        * Une fois qu'une zone est decouverte il est possible de       *" << std::endl;
    std::cout << "        * deduire la position des mines par rapport aux indications    *" << std::endl;
    std::cout << "        * chiffrees donnees par les cases mises a jour. En effet ces   *" << std::endl;
    std::cout << "        * cases sont numerotees de 1 a 8. Ce chiffre indique le nombre *" << std::endl;
    std::cout << "        * de mines se trouvant dans les 8 cases entourant celle        *" << std::endl;
    std::cout << "        * contentant le chiffre. De cette maniere on peut (en théorie  *" << std::endl;
    std::cout << "        * du moins) finir le jeu.                                      *" << std::endl;
    std::cout << "        * La partie est terminee lorque vous avez decouvert toutes les *" << std::endl;
    std::cout << "        * mines du terrain, ou si vous avez malencontreusement pose la *" << std::endl;
    std::cout << "        * souris sur une case minee !                                  *" << std::endl;
    std::cout << "        *                                                              *" << std::endl;
    std::cout << "        ****************************************************************" << std::endl;

}

//Affichage des scores
void scores()
{
    //Comptage nb lignes dans fichier scores.txt
    int nbLignes(0);
    nbLignes = nombreLignes();

    int repeto(0); // Variable de répétition dans boucle while
    std::string transit("null"); // variable temporaire
    std::vector<int> tabPoints(nbLignes); // tableau pour stocker les points indiqués dans scores.txt

    //Lecture de scores.txt et copie des points dans le tableau
    std::ifstream chemin("scores.txt");
    if (chemin)
    {
        while(getline(chemin, transit))
        {
            tabPoints[repeto] = convertString(transit.substr(6));
            ++repeto;
        }
    }
    else
    {
        std::cout << "ERREUR: Impossible d'ouvrir le fichier en lecture. (1)" << std::endl;
    }

    //Tableau trié du plus petit au plus grand.
    std::sort (tabPoints.begin(), tabPoints.end());
    //STOCKAGE DES PSEUDOS
    std::string transit2("null"); //Variable de transit
    std::string tabPseudos[nbLignes];
    repeto = 0;
    std::ifstream chemin2("scores.txt");
    if (chemin2)
    {
        while(getline(chemin2, transit2))
        {
            tabPseudos[repeto] = transit2.substr(0,3);
            ++repeto;
        }
    }
    else
    {
        std::cout << "ERREUR: Impossible d'ouvrir le fichier en lecture. (2)" << std::endl;
    }

    //RATTACHEMENT DES PSEUDOS AUX SCORES CORRESPONDANTS
    std::string transit3("null"); // Variable temporaire
    repeto = 0;
    int substrTransit3(0);
    if (chemin)
    {
        while(getline(chemin, transit3))
        {
            substrTransit3 = convertString(transit3.substr(6)); // subsTransit3 = Points de la ligne lue

            for (int i(nbLignes) ; i>0 ; --i)
            {
                if (tabPoints[i] == substrTransit3)
                {
                    tabPseudos[repeto] = transit3.substr(0,3); // Si points de la ligne lue correspondent aux points de la ligne i du tableau des scores, alors on associe le pseudo de la ligne lue au score.
                }
            }
            ++repeto;
        }
    }

    header();
    std::cout << "        ****************************************************************\n"
              << "        *                                                              *\n"
              << "        *      **      **      **      **      **      **      **      *\n"
              << "        **   **  **  **  **  **  **  *SCORES **  **  **  **  **  **  ***\n"
              << "        *  **      **      **      **      **      **      **      **  *\n";
    for (int i(1) ; i<11 ; ++i)
    {
        if (i ==10)
        {
            std::cout << "        *                        " << i << ". " << tabPseudos[nbLignes-i] << " - " << tabPoints[nbLignes-i] << "                       *\n";
        }
        else
        {
            std::cout << "        *                        " << i << ". " << tabPseudos[nbLignes-i] << " - " << tabPoints[nbLignes-i] << "                        *\n";
        }
    }
    std::cout << "        *                                                              *\n"
              << "        ****************************************************************\n" << std::endl;
}

int main()
{
    int const taillepositionsi(12);
    int positions[taillepositionsi][taillepositionsi]; // chiffres de la grille du démineur
    int positionsIf[taillepositionsi][taillepositionsi]; // 1 ou 0, suivant l'utilisation du joueur

    srand(time(0));
    int boucleMenu(0);
    std::string choix("0");


    while (boucleMenu==0) //Repeat de la page d'accueil
    {
        std::cout << std::endl;
        header();
        menu();
        std::cin >> choix;
        std::cin.ignore();

        if (choix=="1")
        {
            boucleMenu=1;
            nouveauJeu(positions, positionsIf);  // Affichage du démineur
            std::cout << " Tapez 0 pour retourner au menu." << std::endl;
            std::cin >> boucleMenu;
        }
        else if (choix=="2")
        {
            boucleMenu=2;
            options();
            std::cout << " Tapez 0 pour retourner au menu." << std::endl;
            std::cin >> boucleMenu;
        }
        else if (choix=="3")
        {
            boucleMenu=3;
            scores();
            std::cout << " Tapez 0 pour retourner au menu." << std::endl;
            std::cin >> boucleMenu;
        }
    }


    return 0;
}




//***********************
//*FICHIER FONCTIONS.CPP*
//***********************
#include "fonctions.hh"

void affichage(int x, int y, int positions[12][12], int positionsIf[12][12])
{

    std::string valeur("0");
    int valeurDouble; // = valeur
    if (positionsIf[x][y] == 0) //Joueur n'a pas encore vérifié cette case
    {
        valeur = "#";
    }
    else if (positionsIf[x][y] == 1) // Joueur a déjà vérifié la case
    {
        valeur = convertInt(positions[x][y]);
    }
    valeurDouble = convertString(valeur);
    if (valeurDouble >= 9)
    {
        valeur = "°";
    }

    std::cout << valeur;
}


std::string convertInt(int number)
{
   std::stringstream ss;//create a stringstream
   ss << number;//add number to the stream
   return ss.str();//return a string with the contents of the stream
}
int convertString (std::string texte)
{
    int entier(0); // Entier de sortie

    std::stringstream convert(texte); // stringstream used for the conversion initialized with the contents of Text

    if ( !(convert >> entier) )//give the value to Result using the characters in the string
    entier = 0;//if that fails set Result to 0
    return entier;
}

int nombreLignes ()
{
    int nombre(0);
    std::ifstream chemin("scores.txt");
    if(chemin)
    {
         //L'ouverture s'est bien passée. On peut donc lire

        std::string lignes;     //Une variable pour stocker les lignes


        while(getline(chemin, lignes))    //Tant qu'on n'est pas a la fin, on lit
        {
            ++nombre;
        }
    }
    else
    {
        std::cout << "ERREUR: Impossible d'ouvrir le fichier en lecture." << std::endl;
    }
    return nombre;
}



//**********************
//*FICHIER FONCTIONS.HH*
//**********************
#ifndef FONCTIONS_H_INCLUDED
#define FONCTIONS_H_INCLUDED
#include <iostream>
#include <ctime> // Obligatoire
#include <cstdlib> // Obligatoire
#include <string>
#include <fstream>
#include <sstream>
#include <cmath>
#include <vector>

//Gère l'affichage du dièse ou du chiffre
void affichage(int x, int y, int positions[12][12], int positionsIf[12][12]);

//Convertit les entiers en strings
std::string convertInt(int number);

//Convertir les strings en entiers
int convertString(std::string texte);

//Compte nombre lignes dans un fichier
int nombreLignes ();


#endif // FONCTIONS_H_INCLUDED


 Conclusion

J'attends vos améliorations :)

N'hésitez surtout pas à m'aider à alléger mon code !

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !
  •   bin
    •   Release
      • Demineur.ex_Télécharger ce fichier [Réservé aux membres club]531 456 octets
  • Demineur.cbpTélécharger ce fichier [Réservé aux membres club]861 octets
  • Demineur.dependTélécharger ce fichier [Réservé aux membres club]667 octets
  • Demineur.layoutTélécharger ce fichier [Réservé aux membres club]454 octets
  • fonctions.cppTélécharger ce fichier [Réservé aux membres club]Voir ce fichier1 658 octets
  • fonctions.hhTélécharger ce fichier [Réservé aux membres club]621 octets
  • main.cppTélécharger ce fichier [Réservé aux membres club]Voir ce fichier17 832 octets
  • scores.txtTélécharger ce fichier [Réservé aux membres club]Voir ce fichier178 octets

Télécharger le zip


 Historique

11 juillet 2012 02:05:34 :
11/07/2012 : Indication de l'emplacement du .exe
11 juillet 2012 11:24:15 :
11/07/2012 : Le .exe était supprimé à l'upload, il est donc sous la forme .ex_ à partir de maintenant.
11 juillet 2012 15:30:49 :
11/07/2012 : Code allégé + Correction chemins absolus vers relatifs.

 Sources de la même categorie

Source avec Zip ASCII_PHYSIX par BuuG63
Source avec Zip EAT GAME - AFFRONTEZ VOS AMIS par Nebur97232
Source avec Zip Source avec une capture FRUTISNAKE 1.0 par ringo73
Source avec Zip Source avec une capture BRIQUES GAME par xtreen
RÉSOLUTION DU JEU RUSH HOUR PARFOIS APPELÉ UNBLOCK par pabbati

 Sources en rapport avec celle ci

Source avec Zip SLITHER_LINK_JEUX par kossitykossity
Source avec Zip Source avec une capture SHOP MANAGER CONSOLE SUR WINDOWS par antho974
Source avec Zip CARNET D'ADRESSE MODE CONSOLE par chikusa
Source avec Zip Source avec une capture DÉMINEUR AVEC SON par remi100756
Source avec Zip SNAKE CONSOLE par fboivin63

Commentaires et avis

Commentaire de CptPingu le 11/07/2012 11:23:44 administrateur CS

Bonjour.

Au niveau conptuel:
- Lorsque l'on tombe sur un 0, il est d'usage de dévoiler tous les 0 autour jusqu'à tomber sur des "chiffres".
- Titre/décoration trop grande. C'est plus pénible qu'autre chose.
- Ne pas prendre en compte la casse serait mieux (d10 et D10 accepté, par exemple).
- "Options" n'est pas un menu d'option. C'est une explication. Devrait s'appeler "Règle du jeu".

Au niveau technique (pleins de choses qui me choquent dans ton code):
- Évite les using namespace ! Voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace
- Commenter, ce n'est pas "paraphraser". Voir: http://0217021.free.fr/portfolio/axel.berardino/articles/ecrire-de-bons-commentaires
- N'utilise pas de chemin absolu ! "C:/Users/Genevieve/Documents/C++/Projet/Perso/scores.txt" ne fonctionnera que chez toi...
- Un header en C++, c'est .hh ou .hpp, mais pas .h (réservé au C).
- Tu peux enchainer les écritures au lieu de refaire des std::cout de partout...

std::cout << "\t\t\t *************************" << std::endl;
std::cout << "\t\t\t *\t Demineur *" << std::endl;
std::cout << "\t\t\t *\t By *" << std::endl;
std::cout << "\t\t\t *\t Zenoo *" << std::endl;
std::cout << "\t\t\t *************************" << std::endl;
std::cout << std::endl;

devrait être:

std::cout << "\t\t\t *************************\n"
          << "\t\t\t *\t Demineur *\n"
          << "\t\t\t *\t By *\n"
          << "\t\t\t *\t Zenoo *\n"
          << "\t\t\t *************************\n" << std::endl;

Comme en plus, ce ne sont que des string, on pourrait même écrire:
std::cout << "\t\t\t *************************\n"
          "\t\t\t *\t Demineur *\n"
          "\t\t\t *\t By *\n"
          "\t\t\t *\t Zenoo *\n"
          "\t\t\t *************************\n" << std::endl;

- Une fonction dépasse rarement 50 lignes. Tu ne découpes pas assez ton code en petite fonction.
- Plutôt que de faire plein de tableau, fais un seul tableau contenant des structures. La structure contenant des informations sur la case en cours.
- Dans la fonction main, "boucleMenu" devrait être un booléen. Les tests sur cette variable devrait être factorisé en dehors des "if". Il y a redondance pour rien.
- Au lieu d'écrire chacun des membres du tableau, utilise une boucle (je pense notamment à l'affichage du score).
- Plutôt que de donner une taille fixe au std::vector, utilise la méthode ".push_back" (à la limite avec un ".reserve" pour l'optimisation). Si la taille est fixe, utilise un std::array (attention C++0x seulement).
- pointsGagnes = (pointsGagnes + 1000); => pointsGagnes += 1000;
- Trop de redondance dans la méthode qui pose les bombes. Tu as une série de "else if" qui peut aisément se factoriser... De plus, pas besoin de faire des tableaux pour les bombes (surtout que faire deux tableaux, je ne vois vraiment pas l'intérêt). Il suffit de poser ta bombe (si il n'y en a pas déjà une) et d'incrémenter de 1 tous les bords de celle-ci. Ça peut se faire dans une boucle, sans utiliser de tableaux.
- "void tri_bulles(vector<int>& tab)" => Préfère un std::sort, bien plus performant que ton tri à bulles.
- L'affichage de la grille est perfectible. Tu utilises 10 fois la même boucle. Une double boucle aurait grandement facilité la chose.
- "int gain(1); // Si 0, perdu." C'est ici un booléen et non "int" qui devrait être utilisé.


Au niveau architectural:
- Une classe aurait été adaptée pour gérer la grille.

Y a beaucoup de chose à améliorer, et j'ai surement oublié des choses. Mais je te laisse déjà corriger tout cela.

Commentaire de CptPingu le 11/07/2012 11:24:44 administrateur CS

Merci de ne pas joindre dans ton zip les fichiers inutiles (les *.o par exemple).

Commentaire de zenoobrider le 11/07/2012 11:57:38

Merci pour ton aide, je m'en vais de ce pas régler tous ces problèmes.
Comme tu as sans doute pu le constater, je débute en C++, ce qui fait que je suis loin de connaitre toutes les syntaxes des mots clefs du C++.
-Pour le using namespace, je me charge de tout modifier.
-De même pour les commentaires, je vais essayer de les éclaircir ^^
-Au niveau de la casse, je peux gérer aussi.
-J'ai changé Options en Règles du jeu.
-Le chemin absolu est remplacé par "scores.txt"
-J'ai changé l'extension du header en .hh
-Pour le cout, j'avoue que j'ignorais que l'on pouvait enchainer des strings sans "<< endl", je règle ça de suite

J'arrive maintenant au problème des fonctions.
Au départ, je voulais tout découper en petites fonctions, mais j'ai été confronté à un problème de variables.
Comme je débute, j'ai surement dû louper quelque chose, mais je n'arrive pas à réutiliser des variables utilisées dans les fonctions en dehors...
Vu que j'en utilise beaucoup, il faudrait que j'intègre touuuuuuutes les variables en paramètres des fonctions, et ça serait long, très long ...
J'ai entendu parler de variables globales, mais je ne sais pas comment les utiliser ni les mettre en place :/

-Je vais introduire des booléens à la place de mes entiers de vérification
-Je rassemble en ce moment même mon placement des bombes en plusieurs boucles for qui raccourcissent fortement le code
-Pour le std::sort, là encore, j'ignorais même jusqu'à son existence x)
-Je mets en place la double boucle au niveau de l'affichage de la grille

Et pour finir, je ne maitrise pas encore assez bien les classes pour me permettre de les utiliser ^^

Bref, je m'occupe de tout, sauf du découpage en fonctions, que je n'arrive pas à gérer sans savoir initialiser des variables globales :/

Commentaire de CptPingu le 11/07/2012 12:14:29 administrateur CS

>> Et pour finir, je ne maitrise pas encore assez bien les classes pour me permettre de les utiliser ^^
Pas gênant, ce n'est pas obligatoire pour le projet que tu présentes.

>> Bref, je m'occupe de tout, sauf du découpage en fonctions, que je n'arrive pas à gérer sans savoir initialiser des variables globales :/
Ne fait jamais de variables globales, tout simplement :).
Pour le découpage des fonctions, je te laisse mettre à jour ton code, et j'essaierais de te proposer un découpage propre.

Commentaire de zenoobrider le 11/07/2012 15:32:12

Voilà, j'ai tout corrigé, merci pour ton aide :)

Le .zip et le code source sont actualisés.

Commentaire de zenoobrider le 11/07/2012 15:33:54

Désolé pour le double post, mais je viens de me rendre compte que mon bout de code qui est censé associer le pseudo du joueur au résultat dans les scores ne fonctionne pas, Les pseudos ne vont pas du tout avec les scores, sauf que je ne vois pas pourquoi, mon code a l'air d'être bon ...

Commentaire de nikau le 11/07/2012 17:04:16

Salut,
Utiliser des class te permettrait de ne pas avoir à utiliser des variables globales et ça serait plus propre.
Les class en C++, au début, et si tu n'a jamais utilisé un langage objet auparavant, ça n'est pas facile de bien en comprendre le concept, mais il faudra bien que tu t'y mettes, sinon autant faire du C.  Lance toi ! Même si tu n'as pas tout bien compris, force toi à en faire une dans ton programme, c'est le meilleur moyen d'apprendre. Tu verras que tu vas vite comprendre et te rendre compte que finalement c'est très facile.
Quand tu  auras bien compris comment ça fonctionne, tu ne pourras plus t'en passer.

Commentaire de CptPingu le 11/07/2012 19:24:40 administrateur CS

@nikau: Pas tout à fait d'accord avec toi. Ce n'est pas parce que tu as de l'objet que tu évites les variables globales et inversement. Ce sont deux notions complètement différentes...

@zenoobrider:
Je te propose une version corrigé de ton travail. Voilà ce que j'ai fait:
- Allégement du code (tellement de trucs inutiles ou un peu lourd :p)
- Correction des bugs
- Vraie dimension variable (en changeant les constantes taille de la grille et de nombre de bombe, ça fonctionne. (Il est aisément possible de l'ajouter en option).
- Lorsqu'un utilisateur tombe sur une case vide (0), alors toutes les cases annexes sont rendues visibles (comme le vrai démineur).
- Pour gérer les alignements, je t'invite à lire cette source: http://www.cppfrance.com/codes/ALIGNER-TEXTE-CONSOLE_50571.aspx

J'ai esssayé de faire en sorte que le code ne soit pas trop difficile à comprendre. J'ai posé un commentaire sur les notions/astuces les plus difficiles.
Il reste surement un peu de travail à faire pour gérer l'affichage correctement ou rajouter des options. Je te laisse le faire :)


#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <limits>

static const unsigned int GRID_SIZE = 10;
static const unsigned int NB_BOMBS = 10;

struct Cell
{
  Cell()
    : mineNumber(0), visible(false)
  {
  }

  unsigned char mineNumber;
  bool          visible;
};

void showHeader()
{
  std::cout <<
    "\t\t\t    *************************\n"
    "\t\t\t    *\t     Demineur       *\n"
    "\t\t\t    *\t        By          *\n"
    "\t\t\t    *\t       Zenoo        *\n"
    "\t\t\t    *************************\n" << std::endl;
}

std::string getPseudo()
{
  std::cout << std::endl <<
    "        ****************************************************************\n"
    "        *                                                              *\n"
    "        *                                                              *\n"
    "        *                                                              *\n"
    "        *                                                              *\n"
    "        *                                                              *\n"
    "        *                                                              *\n"
    "        *      **      **      **      **      **      **      **      *\n"
    "        **   **  **  **        Entrez votre pseudo        **  **  **  ***\n"
    "        *  **      **      **      **      **      **      **      **  *\n"
    "        *                                                              *\n"
    "        *                                                              *\n"
    "        *                                                              *\n"
    "        *                                                              *\n"
    "        *                                                              *\n"
    "        *                                                              *\n"
    "        ****************************************************************\n" << std::endl;
  std::string nomJoueur;
  std::cin >> nomJoueur;
  std::cin.clear();
  std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

  return nomJoueur;
}

void menu()
{
  std::cout <<
    "        ****************************************************************\n"
    "        *                                                              *\n"
    "        *      **      **      **      **      **      **      **      *\n"
    "        **   **  **  **  **  **  1. Nouvelle partie  **  **  **  **  ***\n"
    "        *  **      **      **      **      **      **      **      **  *\n"
    "        *                                                              *\n"
    "        *                                                              *\n"
    "        *      **      **      **      **      **      **      **      *\n"
    "        **   **  **  **  **  **  2. Regles du jeu**  **  **  **  **  ***\n"
    "        *  **      **      **      **      **      **      **      **  *\n"
    "        *                                                              *\n"
    "        *                                                              *\n"
    "        *      **      **      **      **      **      **      **      *\n"
    "        **   **  **  **  **  **  3. Scores*  **  **  **  **  **  **  ***\n"
    "        *  **      **      **      **      **      **      **      **  *\n"
    "        *                                                              *\n"
    "        ****************************************************************\n" << std::endl;
}

void saveScore(const std::string& playerName, unsigned int score)
{
  const std::string filename = "scores.txt";
  std::ofstream file(filename.c_str(), std::ios::app);

  if (!file)
  {
    std::cout << "ERREUR: Impossible d'ouvrir le fichier: " << filename << std::endl;
    return;
  }

  file << playerName << " " << score << std::endl;
}

void drawCell(Cell positions[GRID_SIZE][GRID_SIZE], int x, int y)
{
  if (!positions[x][y].visible)
    std::cout << "#";
  else
  {
    if (positions[x][y].mineNumber == 9)
      std::cout << '°';
    else
      std::cout << static_cast<char>(positions[x][y].mineNumber + '0');
  }
}

void drawGrid(Cell positions[GRID_SIZE][GRID_SIZE])
{
  std::cout << "        ****************************************************************" << std::endl
            << "        *                                                              *" << std::endl
            << "        *                      ";
  for (unsigned int x = 0; x < GRID_SIZE; ++x)
    std::cout << static_cast<char>('A' + x) << " ";
  std::cout << "                    *" << std::endl;
  for (unsigned int x = 0; x < GRID_SIZE; ++x)
  {
    std::cout << "        *                   " << std::setfill(' ') << std::setw(2) << x + 1 << " ";
    for (unsigned int y = 0; y < GRID_SIZE; ++y)
    {
      drawCell(positions, x, y);
      std::cout << " ";
    }
    std::cout << "                    *" << std::endl;
  }
  std::cout << "        *                                                              *" << std::endl
            << "        *                                                              *" << std::endl
            << "        *                                                              *" << std::endl
            << "        ****************************************************************" << std::endl;
}

void putBomb(Cell positions[GRID_SIZE][GRID_SIZE], unsigned int x, unsigned int y)
{
  if (x > 0 && y > 0 && positions[x - 1][y - 1].mineNumber != 9)
    ++positions[x - 1][y - 1].mineNumber;
  if (x > 0 && positions[x - 1][y].mineNumber != 9)
    ++positions[x - 1][y].mineNumber;
  if (x > 0 && y < GRID_SIZE - 1 && positions[x - 1][y + 1].mineNumber != 9)
    ++positions[x - 1][y + 1].mineNumber;
  if (y > 0 && positions[x][y - 1].mineNumber != 9)
    ++positions[x][y - 1].mineNumber;
  positions[x][y].mineNumber = 9;
  if (y < GRID_SIZE - 1 && positions[x][y + 1].mineNumber != 9)
    ++positions[x][y + 1].mineNumber;
  if (x < GRID_SIZE - 1 && y > 0 && positions[x + 1][y - 1].mineNumber != 9)
    ++positions[x + 1][y - 1].mineNumber;
  if (x < GRID_SIZE - 1 && positions[x + 1][y].mineNumber != 9)
    ++positions[x + 1][y].mineNumber;
  if (x < GRID_SIZE - 1 && y < GRID_SIZE - 1 && positions[x + 1][y + 1].mineNumber != 9)
    ++positions[x + 1][y + 1].mineNumber;
}

void generateBomb(Cell positions[GRID_SIZE][GRID_SIZE])
{
  int nbBombs = NB_BOMBS;
  while (nbBombs > 0)
  {
    unsigned int x = rand() % GRID_SIZE;
    unsigned int y = rand() % GRID_SIZE;
    if (positions[x][y].mineNumber != 9)
    {
      putBomb(positions, x, y);
      --nbBombs;
    }
  }
}

void selectCell(unsigned char& c, unsigned int& i)
{
  bool finished = false;

  while (!finished)
  {
    std::cout << "Jouez. (de la forme A 1, a 1, d 10 ou D 10)" << std::endl;
    std::cin >> c >> i;
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    --i; // Conversion numéro visuel vers numéro réel.
    c |= 32; // Met en minuscule.

    if (c < 'a' || c > GRID_SIZE + 'a' || i > GRID_SIZE)
      std::cout << "Erreur de saisie" << std::endl;
    else
      finished = true;
  }
}

unsigned int checkVisibleCell(Cell positions[GRID_SIZE][GRID_SIZE])
{
  unsigned int nb = 0;
  for (unsigned int x = 0; x < GRID_SIZE; ++x)
    for (unsigned int y = 0; y < GRID_SIZE; ++y)
      if (positions[x][y].visible)
        ++nb;

  return nb;
}

void expandSelection(Cell positions[GRID_SIZE][GRID_SIZE], unsigned int x, unsigned int y)
{
  positions[x][y].visible = true;

  // Cette partie là peut être désactivée. Elle ne sert qu'à afficher tous les 0 qui sont
  // proches de celui qu'on vient de trouver.
  if (positions[x][y].mineNumber > 0)
    return;

  if (x > 0 && y > 0 && !positions[x - 1][y - 1].visible == 0)
    expandSelection(positions, x - 1, y - 1);
  if (x > 0 && !positions[x - 1][y].visible)
      expandSelection(positions, x - 1, y);
  if (x > 0 && y < GRID_SIZE - 1 && !positions[x - 1][y + 1].visible)
      expandSelection(positions, x - 1, y + 1);
  if (y > 0 && !positions[x][y - 1].visible )
      expandSelection(positions, x, y - 1);
  if (y < GRID_SIZE - 1 && !positions[x][y + 1].visible)
      expandSelection(positions, x, y + 1);
  if (x < GRID_SIZE - 1 && y > 0 && !positions[x + 1][y - 1].visible)
      expandSelection(positions, x + 1, y - 1);
  if (x < GRID_SIZE - 1 && !positions[x + 1][y].visible)
      expandSelection(positions, x + 1, y);
  if (x < GRID_SIZE - 1 && y < GRID_SIZE - 1 && !positions[x + 1][y + 1].visible)
      expandSelection(positions, x + 1, y + 1);
}

void play(const std::string& playerName, Cell positions[GRID_SIZE][GRID_SIZE])
{
  bool finished = false;
  bool win = false;
  unsigned int score = 0;

  while (!finished)
  {
    drawGrid(positions);
    unsigned char c;
    unsigned int x;
    selectCell(c, x);
    unsigned int y = c - 'a';

    std::cout << x << " " << y << std::endl;
    expandSelection(positions, x, y);
    score = checkVisibleCell(positions);
    if (positions[x][y].mineNumber == 9)
    {
      win = false;
      finished = true;
    }
    else if (score >= GRID_SIZE * GRID_SIZE - NB_BOMBS)
    {
      win = true;
      finished = true;
    }
  }

  drawGrid(positions);
  std::cout << (win ? " Bravo" : "Perdu") << " ! Vous avez gagné " << score * 1000 << " points !";
  saveScore(playerName, score * 1000);
}

void nouveauJeu()
{
  Cell positions[GRID_SIZE][GRID_SIZE];
  std::string nomJoueur = getPseudo();
  showHeader();
  generateBomb(positions);
  play(nomJoueur, positions);
}

void rules()
{
  showHeader();
  std::cout << "        ****************************************************************" << std::endl
            << "        *                             REGLES                           *" << std::endl
            << "        *                                                              *" << std::endl
            << "        * Le principe est simple. Comme son nom l'indique, le but du   *" << std::endl
            << "        * jeu est de deminer le terrain, symbolise par une grille.     *" << std::endl
            << "        * Une fois qu'une zone est decouverte il est possible de       *" << std::endl
            << "        * deduire la position des mines par rapport aux indications    *" << std::endl
            << "        * chiffrees donnees par les cases mises a jour. En effet ces   *" << std::endl
            << "        * cases sont numerotees de 1 a 8. Ce chiffre indique le nombre *" << std::endl
            << "        * de mines se trouvant dans les 8 cases entourant celle        *" << std::endl
            << "        * contentant le chiffre. De cette maniere on peut (en théorie  *" << std::endl
            << "        * du moins) finir le jeu.                                      *" << std::endl
            << "        * La partie est terminee lorque vous avez decouvert toutes les *" << std::endl
            << "        * mines du terrain, ou si vous avez malencontreusement pose la *" << std::endl
            << "        * souris sur une case minee !                                  *" << std::endl
            << "        *                                                              *" << std::endl
            << "        ****************************************************************" << std::endl;

}

void scores()
{
  std::ifstream file("scores.txt");
  if (!file)
  {
    std::cout << "ERREUR: Impossible d'ouvrir le fichier en lecture." << std::endl;
    return;
  }

  showHeader();
  std::cout << "        ****************************************************************\n"
            << "        *                                                              *\n"
            << "        *      **      **      **      **      **      **      **      *\n"
            << "        **   **  **  **  **  **  **  *SCORES **  **  **  **  **  **  ***\n"
            << "        *  **      **      **      **      **      **      **      **  *\n";

  unsigned int i = 0;
  std::string line;
  while (getline(file, line))
    std::cout << "        *                        " << ++i << ". " << line << "                       *\n";
  std::cout << "        *                                                              *\n"
            << "        ****************************************************************\n" << std::endl;
}

int main()
{
  srand(time(0));

  bool finished = false;
  char choix;

  while (!finished)
  {
    std::cout << std::endl;
    showHeader();
    menu();
    std::cin >> choix;
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    switch (choix)
    {
      case '1':
        nouveauJeu();
        break;
      case '2':
        rules();
        break;
      case '3':
        scores();
        break;
      default:
        std::cout << "Choix inconnu" << std::endl;
    }

    std::cout << "Tapez 0 pour retourner au menu." << std::endl;
    std::cin >> finished;
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
  }

  return 0;
}

Commentaire de CptPingu le 11/07/2012 19:28:20 administrateur CS

Une petite coquille s'est glissée dans mon code. Il faut remplacer cette ligne:
if (x > 0 && y > 0 && !positions[x - 1][y - 1].visible == 0)

Par celle-ci:
if (x > 0 && y > 0 && !positions[x - 1][y - 1].visible)


(Dans la fonction "expandSelection")

Commentaire de nikau le 11/07/2012 19:29:35

Évidement que c'est différent !! Je n'ai jamais dis le contraire!!
Mais dans le cas de son programme, avec des class, il n'aurait pas besoin de variables globale pour faire des plus petite fonction comme tu le lui a conseillé.

Commentaire de zenoobrider le 11/07/2012 20:16:32

Merci beaucoup ! :)

Seulement, il y a quelques parties de codes que je ne comprends pas trop :

-Le struct cell : Je me doute que c'est un constructeur, et que ça initialise les cellules de la grille, mais je ne vois pas trop comment.

-le (std::numeric_limits<std::streamsize>::max(), '\n') que tu rajoutes après chaque cin. D'ailleurs, un cin.ignore() ne suffit-il pas, il faut aussi rajouter le cin.clear()?

-Dans ton drawCell, ici : std::cout << static_cast<char>(positions[x][y].mineNumber + '0'), le cast est là pour passer d'un int à un char? Je pense que le .mineNumber est une sorte de fonction sans paramètres (?). Mais le '0', je vois pas ce qu'il fait là ^^'

-Tout cette partie du drawGrid :
  for (unsigned int x = 0; x < GRID_SIZE; ++x)
    std::cout << static_cast<char>('A' + x) << " ";
  std::cout << "                    *" << std::endl;
  for (unsigned int x = 0; x < GRID_SIZE; ++x)
  {
    std::cout << "        *                   " << std::setfill(' ') << std::setw(2) << x + 1 << " ";
    for (unsigned int y = 0; y < GRID_SIZE; ++y)
Je n'ai rien, mais alors rien compris x)

-Dans selectCell, que représente le 'a' ? (if (c < 'a' || c > GRID_SIZE + 'a' || i > GRID_SIZE))

-Dans expandSelection, tu appelles cette même fonction, pourquoi cela ne risque-t-il pas de provoquer une boule infinie? (Je m'explique, quand tu appelles pour la 1ere fois expandSelection, les instructions s'effectuent, et au moment où celles-ci appellent expandSelection, la fonction devrait repartir au début et tout relire ... et ceci à l'infini, non?)

Sinon, tu as oublié de trier le fichier scores.txt selon le score, mais je m'en occupe ^^

Dernière petite chose : Les variables initialisées au tout début, ce sont des variables globales, qui fonctionnent dans toutes les fonctions?

En tout cas, merci beaucoup :)

Commentaire de CptPingu le 12/07/2012 11:24:09 administrateur CS

>> -Le struct cell : Je me doute que c'est un constructeur, et que ça initialise les cellules de la grille, mais je ne vois pas trop comment.
"struct Cell", ça équivaut à "class Cell + public". En gros je créer un type personnalisé qui contient deux variables. Le constructeur est là pour dire: par défaut les variables valent "ceci".
Lorsque je fais Cell tab[size][size], ça créer un tableau de "Cell". Chacune des cases appelent automatiquement le constructeur, lors de la création.

>> -le (std::numeric_limits<std::streamsize>::max(), '\n') que tu rajoutes après chaque cin.
Dans certains cas (par exemple lorsque tu rentres un texte à la place d'un chiffre) tu peux partir en boucle infinie. Pour éviter cela, il faut utiliser un "ignore" pour dire: "je veux ignorer certains caractères". Par défaut ce n'est pas un saut de ligne '\n' mais une fin de fichier "eof". J'ai donc spécifié que je voulais ignorer l'appui sur la touche entrée (puisqu'elle insère un \n). Le "std::numeric_limits<std::streamsize>::max()," sert à dire: donne moi la valeur maximale d'une valeur entière. Ici ça serait 2^32. Je veux éviter autant de \n que possible, je met donc la plus grande valeur qui existe. J'aurais aussi pu faire: ignore(10, '\n'). Je pense que ça aurait aussi fonctionné.

>> D'ailleurs, un cin.ignore() ne suffit-il pas, il faut aussi rajouter le cin.clear()?
Ce n'est pas parce que tu ignores certains caractères que ton flux ne peut pas être pourri. Lorsque tu lis une entrée et que celle-ci n'est pas correcte, il faut "nettoyer" le flux avant de le réutiliser.
C'est ce que fait le clear. Il remet les flags internes à leurs valeurs de base.

>> -Dans ton drawCell, ici : std::cout << static_cast<char>(positions[x][y].mineNumber + '0'), le cast est là pour passer d'un int à un char?
Je passe d'un entier vers son code ASCII. '0' équivaut à 32. Donc si j'ai 0 et que je veux écrire '0' il faut que j'ajoute 32 ou 0 pour que ça donne '0'. Si tu préfères, chaque caractères existant porte un numéro, et les chiffress sont numérotés à partir de 32.

Le cast est la pour forcer le type char. mineNumber étant de type "int", si je le passe dans un std::cout, il m'écrira 32 au lieu de '0'.
Exemple:
char c1 = 32;
int i1 = 32;
char c2 = '0';
int i2 = '0';

std::cout << c1 << " " << i1 << " " << c2 << " " << i2 << std::endl; // affichera 0 32 0 32


>> Je pense que le .mineNumber est une sorte de fonction sans paramètres (?).
Non, c'est une simple variable.

>> Mais le '0', je vois pas ce qu'il fait là ^^'
Cf plus haut. C'est une astuce pour obtenir la version textuelle du nombre.


>>  for (unsigned int x = 0; x < GRID_SIZE; ++x)
>>    std::cout << static_cast<char>('A' + x) << " ";
Génère l'affichage de l'alphabet.
'A' + 0 => 'A'
'A' + 1 => 'B'
etc...


>>    std::cout << "        *                   " << std::setfill(' ') << std::setw(2) << x + 1 << " ";
Pour ceci, voir le lien que j'ai mis. En gros setfill et setw sont des modificateurs de flux qui permettent de gérer l'affichage. Par exemple, tu peux faire un alignement à gauche ou à droite, forcer un nombre à tenir dans deux espaces, etc...

>> -Dans selectCell, que représente le 'a' ? (if (c < 'a' || c > GRID_SIZE + 'a' || i > GRID_SIZE))
Lorsque l'utilisateur rentre une coordonnée de type "a 7" je récupère le caractère et je vérifie qu'il est valide. Pour être valide le caractère doit être >= à 'a' (si c'est un caractère plus petit que 'a' il y a un problème, non :p ?) et doit être inférieur à la taille de la grille. Si la taille de ta grille vaut 26, alors le caractère doit être plus petit ou égale à 'z'.
GRID_SIZE + 'a', si GRID_SIZE vaut 0, alors => 'a'
GRID_SIZE + 'a', si GRID_SIZE vaut 1, alors => 'b'
...
GRID_SIZE + 'a', si GRID_SIZE vaut 26, alors => 'z'

>> Dernière petite chose : Les variables initialisées au tout début, ce sont des variables globales, qui fonctionnent dans toutes les fonctions?
Non, il ne faut jamais faire de variables globales. Ici, ce sont des constantes globales. Elles sont effectivement "visibles" partout dans le fichier.

>> -Dans expandSelection, tu appelles cette même fonction, pourquoi cela ne risque-t-il pas de provoquer une boule infinie? (Je m'explique, quand tu appelles pour la 1ere fois expandSelection, les
>> instructions s'effectuent, et au moment où celles-ci appellent expandSelection, la fonction devrait repartir au début et tout relire ... et ceci à l'infini, non?)
C'est une fonction récursive. Rappeler une fonction au sein d'elle même ne te fait pas revenir au début de celle-ci. La fonction "se gèle" jusqu'à ce que tu ais fini l'exécution de la fonction appelée. Qu'elle est le même nom n'est pas gênant, c'est tout de même considéré comme une autre fonction indépendante.
C'est une notion un peu difficile pour ton niveau actuel. C'est pour ça que je t'ai mis un commentaire expliquant que l'on peut retirer les appels récursifs pour simplifier le code (bien évidemment on perd la fonctionnalité qui découvre toutes les cases adjacentes qui sont de type 0).

Je te met un exemple de fonction récursive simple:
int facto(int nb)
{
  if (nb == 0)
   return 1;

  return facto(nb - 1) * nb;
}

Si je fais facto(3), en gros ça donnerait quelque chose comme ceci:

int facto(3)
{
  if (3 == 0)
   return 1;

  return facto(3 - 1) * 3;
  // appel de facto(2)
  int facto(2)
  {
     if (2 == 0)
       return 1;
     return facto(2 - 1) * 2;
     // appel de facto(1)
     int facto(1)
     {  
       if (1 == 0)
         return 1;
       return facto(1 - 1) * 1;
       // appel de facto(0)
       int facto(0)
       {
        if (0 == 0)
          return 1; // fin de facto(0), pas d'autre appel, alors on remonte juste avant le "gel" de facto(1)
       }
  }
}

Après le return 1, tu te retrouves alors avec facto(1 -1) * 1 qui est 1 * 1. Tu remontes alors avant le "gel" de facto(2).
Tu te retrouves alors avec "return facto(2 - 1) * 2;" qui devient "return 1 * 2;". Tu remontes alors avant le "gel" de facto(3).
Tu te retrouves alors avec "return facto(3 - 1) * 3;" qui devient "return 2 * 3;". Tu renvois alors 6.

Je t'invite à te renseigner sur ce qu'est la récursivité.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

effacer l'ecran de la console dos en C [ par gollum ] Comment effecer l'ecran de la console DOS en C ? [VC++] Taille du text dans une application console [ par Cybmat ] SalutVoila je voudrai savoir comment on change la taille du text ecrit dans uneapplication console avec printf() .Merci d'avance BCBv3. Utilisation de AnsiString en mode console [ par jm14d ] Pour utiliser la classe AnsiString sous Borland v3, en mode graphique c'est OK : j'inclus VCL.h et ça fonctionne. Par contre en mode console je ne m'e comment utilise t on les couleurs sous la console [ par psycho ] j aimerais savoir quels sont les instructions qui permettent d incorporer de la couleur sous la console(j utilise visual studio), ainsi que les fichie Propriété de la fenetre de console [ par Orkblutt ] Salut,j'aimerai fixer les parametres de la fenetre de console: largeur, hauteur, tampon...Quelle est la classe à utiliser pour configurer ces parametr Du son sous console dos (devcpp) ? [ par dionysos ] Bonjour,Quelles fonctions et quelles bibliotheques utiliser pour emettre des sons (de differentes tonalites ou de differentes frequences), en C, conso Du son sous console dos...? [ par dionysos ] Bonjour,Quelles fonctions et quelles bibliotheques utiliser pour emettre des sons (de differentes tonalites ou de differentes frequences), en C, conso Du son sous console dos???? [ par dionysos ] bonjour,avec devcpp quelles fonctions et quelles bibliotheques utiliser pour générer du son en console dos, et en C.Merci focus console [ par jmz ] Bonjour,J'ai une appli avec 1 fenetre principale et la console qui me sert de "trace".Tout marche bien, j'écris plein de chose en couleurs dans ma con Récuperer un hwnd de fenêtre [ par andros ] Bonjour,Je n'ai pas trouvé la réponse sur le forum au pb que voici :(ss Bor C++6) -d'une part j'ai un programme éxécutable en mode console Dos.-d'autr


Nos sponsors


Sondage...

CalendriCode

Mai 2013
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Photothèque

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,936 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales