Partage

[Exercices] Venez vous entraîner !

(v2)

28 juin 2011 à 20:54:31

Bonjour tout le monde :) !

Vous le savez certainement, pour progresser en informatique, il faut pratiquer le plus possible. C'est en forgeant qu'on devient forgeron. Malheureusement il est parfois difficile de trouver des exercices pour travailler un point particulier du langage.

Ce topic a pour but de vous proposer un ensemble d'exercices qui approfondissent des aspects du merveilleux langage qu'est le C++.

Comment ça marche ?



Chacun peut, si l'envie l'en prend, proposer un exercice sur ce topic. Si l'exercice est bien présenté (lisible, et non pas un pavé en fouillis), un lien vers lui sera alors ajouté à ce premier post, de telle sorte qu'il sera aisément accessible.

Je veux proposer un exercice, comment faire ?



Il vous suffit de poster un message sur ce topic, composé uniquement de l'exercice. Penser à respecter les conseils suivants.

Chaque exercice devra être composé de :
  • Un nom (par lequel il sera identifié) ;
  • Un groupe, un sujet (pour le classer et accéder plus facilement aux exercices intéressants);
  • Un énoncé, qui devra être clair et net ;


Les plus :
  • Un exercice découpé en niveau;
  • Un exercice sur un sujet encore jamais abordé par les autres exercices;
  • Une solution proposée dans un autre message (voir plus bas).


Les moins :
  • Une orthographe déplorable;
  • Une absence de présentation (le zCode est là pour vous !);
  • Un énième exercice sur le même sujet;
  • Un exercice aussi simple qu'un "Hello, World!" : il faut quand même devoir réfléchir un minimum !


Il est à noter que le niveau de difficulté sera apprécié par nos soins, vous n'avez donc pas à en mettre pour proposer vos exercices.


Je souhaite proposer une solution, comment faire ?



Chacun peut proposer la solution à un exercice sur ce topic en postant un message constitué uniquement de la solution. Si elle est bien présentée, un lien vers elle sera alors ajouté à ce premier post, de telle sorte qu'il sera aisément accessible.

Il n'y a pas qu'une seule solution possible ! Vous pouvez parfaitement proposer une solution à un exercice qui en possède déjà une à condition d'être différente de celles déjà proposées ;) !


Chaque solution devra être obligatoirement composée de :
  • un titre la présentant comme telle;
  • un lien vers l'exercice en question;
  • le code source de votre solution qui doit impérativement être compilable et commenté;
  • des explications sur la correction
  • la mention [C++11] si vous utilisez cette dernière version du langage


Les composants suivants sont facultatifs mais appréciés :
  • si l'exercice est découpé en niveau, une solution découpée elle aussi en niveaux;
  • des conseils pédagogiques;
  • des idées pour "aller plus loin";
  • la liste des propriétés du C++11 utilisée.


Les points négatifs :
  • Une orthographe déplorable;
  • Une absence de présentation (le zCode est là pour vous !);
  • Une énième solution sur le même exercice.


Les exercices



Voilà (enfin !) les exercices, classés par sujet. Les exercices de difficulté ? n'ont pas encore été notés. Les noms de langages entre parenthèse à côté d'un lien (ex: (Java)) indique que l'exercice a été proposé sur un autre sujet initialement prévu pour un autre langage, mais dont nous avons estimé que les explications étaient compréhensibles pour un programmeur C++; demandez de l'aide sur ce sujet si vous voulez avoir une réponse en C++ ;) .

Algorithmie



Nom de l'exerciceDifficultéAuteurSolutions possibles
Des chiffres ... ? Nanoc Par l'auteur
... et des lettres ? Nanoc Par l'auteur


Base de données



Nom de l'exerciceDifficultéAuteurSolutions possibles
Biblio++ Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur germino


Chaînes de caractère



Nom de l'exerciceDifficultéAuteurSolutions possibles
En lettres ! ? Chlab_lak Par Equinoxe


Réalisation d'un jeu



Nom de l'exerciceDifficultéAuteurSolutions possibles
Tic-Tac-Toe Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur Metallica-z80 Par lmghs (solution poussée)
Par DDR2
Le jeu du "football sur papier" Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur pie3636 Par germino
Puissance 4 Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur Metallica-z80 Par Nanoc
Par l'auteur


Réalisation d'un logiciel



Nom de l'exerciceDifficultéAuteurSolutions possibles
Javaquarium (Java) ? SpaceFox


Cryptologie



Nom de l'exerciceDifficultéAuteurSolutions possibles
Crypto 1 : Le chiffre de César Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur Nanoc Par Chlab_lak
Crypto 2 : Le chiffre de Vigénère Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur Nanoc Par iNaKoll
Crypto 3 : Le XOR Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur Nanoc Par l'auteur


Console



Nom de l'exerciceDifficultéAuteurSolutions possibles
Cowsay ! Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur Nanoc Par l'auteur
Figlet ? Nanoc
Triangle de Pascal Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur hilnius Par Equinoxe


Polymorphisme



Nom de l'exerciceDifficultéAuteurSolutions possibles
Le Site du Zéro Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur Nanoc Par l'auteur


Classes à sémantique de valeur



Nom de l'exerciceDifficultéAuteurSolutions possibles
Le plus grand nombre ? Nanoc Par l'auteur
Fractions ? Nanoc Par l'auteur
Polynômes ? Nanoc Par l'auteur
Par lmghs (solution poussée)


Opérateurs



Nom de l'exerciceDifficultéAuteurSolutions possibles
Opérateur virgule ? Nanoc Par l'auteur


Fichiers



Nom de l'exerciceDifficultéAuteurSolutions possibles
Compression RLE ? Nanoc Par lanfeusst
Statistiques sur les fichiers ? Nanoc Par Leilo
Diff ? Nanoc


Langages, interpréteurs



Nom de l'exerciceDifficultéAuteurSolutions possibles
Interpréteur BrainFuck ? Nanoc

Par l'auteur

Par MatteX et Masthiks

Par Equinoxe (ahahah solution en befunge !)

P'tit langage ? bluestorm
Chiffres romains ? Nanoc Par l'auteur
Parseur de fonctions mathématiques ? Carma001
Interpréteur Befunge ? Hugooguh


Qui se cache derrière Exercice Cpp ?



Actuellement, ce sont germino et Equinoxe qui s'occupent de ce topic.
Ils tiennent régulièrement à jour ce sujet :)

Vous pouvez les aider en donnant votre avis sur ce sujet ;)
ou tout simplement en faisant les exercices dont la difficulté n'a pas été évaluée afin justement de les évaluer correctement :D


Note : les exercices proposés par Nanoc proviennent d'un sujet lui appartenant.

Merci de votre visite :)

-
Edité par Exercices Cpp 26 mars 2013 à 23:25:33

Vous êtes demandeur d'emploi ?
Sans diplôme post-bac ?

Devenez Développeur web junior

Je postule
Formation
en ligne
Financée
à 100%
28 juin 2011 à 21:19:08

On va compléter tout ça :)
28 juin 2011 à 21:28:35

germino : mis en secret la rubrique pour proposer des exercices.
germino : modifié le profil de Exercice Cpp
29 juin 2011 à 7:51:07

La classification est très claire, j'aime :D

Je m'en vais de ce pas faire (ou refaire) ces exercices et j'enverrais les notes par MP
29 juin 2011 à 10:41:00

Cool !
Les exercices sont-ils à proposer sur ce topic, ou sur l'ancien topic ?
29 juin 2011 à 10:51:03

Citation : Metallica-z80

Cool !
Les exercices sont-ils à proposer sur ce topic, ou sur l'ancien topic ?


Oups, on a oublié de préciser :D . Sur ce topic bien entendu !
29 juin 2011 à 10:58:08

OK, Je commence à rédiger un exercice et dès que j'ai fini je le poste.
29 juin 2011 à 11:42:44

germino : suppression de la partie Général et répartition de ses composants.
germino : ajout d'un lien vers le sujet méta.
germino : clarification de l'emplacement des exercices.
29 juin 2011 à 12:35:11

possible de mettre le post en static ?
29 juin 2011 à 12:50:47

En 'static' ??? En post-it, tu veux dire ?
29 juin 2011 à 13:04:25

oui en effet c'est le terme exacte du site du zéro ;) . Moi je me croyait entrain de coder :p .
A part ca, le plus important c'est de faire des nouveau exos en sortes de concours, et donc faire que l'on envoi les réponses à Exercice cpp ?
29 juin 2011 à 13:08:42

On va étudier le système à adopter sur le sujet méta indiqué en bas du premier post ;)
29 juin 2011 à 13:10:22

En effet, il serait intéressant de passer le topic en post-it (/summon modérateur).
29 juin 2011 à 13:17:58

Equinoxe : Corrigé la typo (Polinômes >>> Polynômes) annoncée par lmghs.
Equinoxe : Modifié le format de la difficulté, por éviter qu'elle soit considérée comme une note de "qualité".
Equinoxe : Envoyé l'image de difficulté (source) : Image utilisateur
29 juin 2011 à 14:06:53

Voilà l'exercice que je propose:

Tic-Tac-Toe



Énoncé


Le but de cet exercice est de réaliser le célèbre jeu de Tic-Tac-Toe (appelé Morpion par les incultes :p ). Si vous ne connaissez pas les règles : Go Wikipédia
Le jeu devra être jouable à 2 joueurs. Les joueurs choisiront chacun leurs tours où placer leurs symboles ("X" pour le joueur 1 et "O" pour le joueur 2). Vous devrez gérer l'affichage d'une grille en console. Je vous propose déjà celle que j'ai utilisé (bien évidemment, vous n'êtes pas obliger de faire la même):
1|2|3
-+-+-
4|5|6
-+-+-
7|8|9

Puis au cours de la partie:
X|2|O
-+-+-
X|O|6
-+-+-
O|X|9

(Ici, le joueur 2 a gagné)

Solution possible


#include <iostream>

using namespace std;

void Printboard(); // Fonction qui affiche la grille

char cSquare[3][3] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};

int main() {

	int iPlayerTurn(1);
	bool bGameOver(true);

	// Boucle Principal
	do {
		// Affichage de la grille
		Printboard();

		// Symbole utilisé par les joueurs: Joueur1='X' Joueur2='O' 
		char cPlayerMark;
		if (iPlayerTurn == 1) {
			cPlayerMark = 'X';
		} else {
			cPlayerMark = 'O';
		}

		// Demande où le joueur souhaite placer son Symbole
		cout << "Player" << iPlayerTurn << "'s move:" << endl;
		bool bValidMove;
		// Boucle jusqu'à ce que le placement soit valide
		do {
			char cNextMove;
			cin >> cNextMove;
			bValidMove = true;

			// Vérifie la validité du placement
			if (cNextMove == '1' && cSquare[0][0] == '1') {
				cSquare[0][0] = cPlayerMark;
			} else if (cNextMove == '2' && cSquare[0][1] == '2') {
				cSquare[0][1] = cPlayerMark;
			} else if (cNextMove == '3' && cSquare[0][2] == '3') {
				cSquare[0][2] = cPlayerMark;
			} else if (cNextMove == '4' && cSquare[1][0] == '4') {
				cSquare[1][0] = cPlayerMark;
			} else if (cNextMove == '5' && cSquare[1][1] == '5') {
				cSquare[1][1] = cPlayerMark;
			} else if (cNextMove == '6' && cSquare[1][2] == '6') {
				cSquare[1][2] = cPlayerMark;
			} else if (cNextMove == '7' && cSquare[2][0] == '7') {
				cSquare[2][0] = cPlayerMark;
			} else if (cNextMove == '8' && cSquare[2][1] == '8') {
				cSquare[2][1] = cPlayerMark;
			} else if (cNextMove == '9' && cSquare[2][2] == '9') {
				cSquare[2][2] = cPlayerMark;
			} else {
				cout << "Invalid Move. Try again." << endl;
				bValidMove = false;
			}
		} while (!bValidMove);

		bGameOver = false;
		bool bWinGame = true;

		// Vérification pour savoir si le jeu est fini
		if (cSquare[0][0] != '1') {
			if (cSquare[0][1] == cSquare[0][0] && cSquare[0][2] == cSquare[0][0]) {
				bGameOver = true;
			}
			if (cSquare[1][0] == cSquare[0][0] && cSquare[2][0] == cSquare[0][0]) {
				bGameOver = true;
			}
		}
		if (cSquare[1][1] != '5') {
			if (cSquare[0][0] == cSquare[1][1] && cSquare[2][2] == cSquare[1][1]) {
				bGameOver = true;
			}
			if (cSquare[0][1] == cSquare[1][1] && cSquare[2][1] == cSquare[1][1]) {
				bGameOver = true;
			}
			if (cSquare[1][0] == cSquare[1][1] && cSquare[1][2] == cSquare[1][1]) {
				bGameOver = true;
			}
			if (cSquare[0][2] == cSquare[1][1] && cSquare[2][0] == cSquare[1][1]) {
				bGameOver = true;
			}
		}
		if (cSquare[2][2] != '9') {
			if (cSquare[0][2] == cSquare[2][2] && cSquare[1][2] == cSquare[2][2]) {
				bGameOver = true;
			}
			if (cSquare[2][0] == cSquare[2][2] && cSquare[2][1] == cSquare[2][2]) {
				bGameOver = true;
			}
		}
		// Vérification si la grille est pleine (pas de vainqueurs)
		if (cSquare[0][0] != '1' && cSquare[0][1] != '2' && cSquare[0][2] != '3' &&
			cSquare[1][0] != '4' && cSquare[1][1] != '5' && cSquare[1][2] != '6' &&
			cSquare[2][0] != '7' && cSquare[2][1] != '8' && cSquare[2][2] != '9' && !bGameOver)
		{
			bGameOver = true;
			bWinGame = false;
		}

		if (bGameOver) {
			// Affichage de la grille final
			Printboard();
			if (bWinGame) {
				cout << "Player" << iPlayerTurn << " wins!" << endl;
			} else {
                cout << "Egalité" << endl;
			}



			cout << "Game Over!" << endl;
			cout << "Play again (y/n)?" << endl;
			char cPlayAgain;
			cin >> cPlayAgain;

			if (cPlayAgain == 'y') {
				bGameOver = false;
				// Remise à zéro de la grille
				cSquare[0][0] = '1';
				cSquare[0][1] = '2';
				cSquare[0][2] = '3';
				cSquare[1][0] = '4';
				cSquare[1][1] = '5';
				cSquare[1][2] = '6';
				cSquare[2][0] = '7';
				cSquare[2][1] = '8';
				cSquare[2][2] = '9';
			}
			iPlayerTurn = 1;
		} else {
			// Changement de joueur
			if (iPlayerTurn == 1) {
				iPlayerTurn = 2;
			} else {
				iPlayerTurn = 1;
			}
		}
	} while (!bGameOver);

	return 0;
}

void Printboard() {
    cout << cSquare[0][0] << "|" << cSquare[0][1] << "|" << cSquare[0][2] << endl;
	cout << "-+-+-"<< endl;
	cout << cSquare[1][0] << "|" << cSquare[1][1] << "|" << cSquare[1][2] << endl;
	cout << "-+-+-"<< endl;
	cout << cSquare[2][0] << "|" << cSquare[2][1] << "|" << cSquare[2][2] << endl;
}


Les explications sont dans le code.

PS : J'utilise des noms de variables en Anglais si cela pose problème, je modifierais mon code.
29 juin 2011 à 14:09:11

@Metallica : non, c'est mieux qu'il soient en anglais, le français n'est pas fait pour ça.
29 juin 2011 à 14:13:42

D'accord.
(Le sujet est en post-it ;) )
29 juin 2011 à 14:16:28

germino : ajout de l’interpréteur Befunge, du triangle de Pascal
germino : ajout d'une partie "Réalisation d'un jeu"
germino : ajout du Tic-Tac-Toe
29 juin 2011 à 14:21:21

le tic tac toe, je l'avait déjà fait ;) (mais en moins propre)
sinon cool le sujet est en post-it, dommage que l'ancien le reste (source de confusions ;) ).

29 juin 2011 à 14:25:57

germino : ajout d'une colonne "Solutions possibles"
germino : ajout de quelques solutions
germino : ajout d'une colonne "Auteur"
29 juin 2011 à 16:08:15

j'ai une idée d'exercice, une sorte de suite de l'exo "fractions" qui permet de gérer les réels (sous forme exacte et simplifiée) mais bon c'est peut être un peut dur pour un exo non ?
EDIT : comme je sais pas trop comment je pourais faire, je laisse juste l'idée et si quelqu'un veut l'exploiter, gogogo :D
Anonyme
29 juin 2011 à 19:06:19

Metallica-z80 ton code est horrible a lire, fait de petites fonctions qui exectuent chacune une tache bien precise. Le main n'est pas la pour contenir tout le programme et au lieu de faire ton:
if (...)

else if(...)
...
...
...
else

de malade tu peux faire une petite fonction et une boucle qui reproduirait exactement la meme chose et ne brulerait pas les yeux de ceux qui lisent ton code.

(Desole pour les accents j'ai un clavier qwerty)
29 juin 2011 à 20:33:46

C'est vrai qu’un peu d'OO n'aurait peut-être pas fait de mal... :)
29 juin 2011 à 21:36:34

On doit poster nos solutions aux exercices ici pour avoir des conseils pour améliorer le code ?
29 juin 2011 à 21:38:30

A la limite, l'OO n'est pas nécessaire, mais simplement déjà changer le code de "rien sur la case" pour ' ', et demander à l'utilisateur une position X, Y ; ça permettrait de :
- Simplifier la suite de "if"
- Clarifier l'affichage d'une partie en cours

De même, il serait possible de clarifier beaucoup de code. J'essaie de faire quelque chose de plutôt joli et je reviens. :)

@Dumpy: Laisser la réponse ici permettra d'avoir des conseils, et si la solution est bonne, d'avoir un lien pointant vers la solution. Bref, bénéfice pour tout le monde. :)
29 juin 2011 à 21:48:15

Ma solution pour Crypto : Le chiffre de César
#include <iostream>
#include <fstream>
#include <map>

using namespace std;

string UpToLow(string str)
{
    for (int i=0;i<strlen(str.c_str());i++)
        if (str[i] >= 0x41 && str[i] <= 0x5A)
            str[i] = str[i] + 0x20;
    return str;
}

void crypter(string &texte, const int decalage)
{
    if(decalage<=0)
        return;

    for(int i = 0; i<texte.size(); i++)
    {
        int a = int(texte[i]);

        if((a>=65 && a<=90) || (a>=97 && a<=122))
        {
            int min, max;

            if(a>=65 && a<=90)
            {
                min = 65;
                max = 90;
            }
            else if(a>=97 && a<=122)
            {
                min = 97;
                max = 122;
            }

            a += decalage;

            while(a>max)
                a = min + a - max - 1;

            texte[i] = char(a);
        }
    }
}

void decrypter(string &texte)
{
    map<int, int> frequences;

    string t = UpToLow(texte);

    for(int i = 0; i<t.size(); i++)
    {
        int a = int(t[i]);

        if(a>=97 && a<=122)
        {
            frequences[a]++;
        }
    }

    int max = 0;
    char c;

    for(int j = 97; j <= 122; j++)
    {
        if(frequences[j] > max)
        {
            max = frequences[j];
            c = char(j);
        }
    }

    int decalage;

    if(int(c)<=int('e'))
        decalage = int('e') - int(c);
    else
        decalage = int('e') + 26 - int(c);

    crypter(texte, decalage);
}

void crypterMessage(const string type)
{
    string texte;
    int decalage = -1;

    cout << "Message a " + type + " : ";
    cin.ignore(numeric_limits<int>::max(), '\n');
    getline(cin, texte);
    cout << "Decalage : ";

    while(decalage<0)
        cin >> decalage;

    crypter(texte, decalage);
    cout << endl << texte;
}

void crypterFichier(const string type)
{
    string texte;
    string chemin;
    int decalage = -1;

    cout << "Chemin du fichier : ";
    cin.ignore(numeric_limits<int>::max(), '\n');
    getline(cin, chemin);
    cout << "Decalage : ";

    while(decalage <0)
        cin >> decalage;

    ifstream f(chemin.c_str(),ios::in);

    if(f)
    {
        f.seekg(0, ios::beg);

        string ligne;
        getline(f, ligne);

        texte += ligne;

        while(getline(f, ligne))
            texte += "\n" + ligne;

        f.close();

        crypter(texte, decalage);

        ofstream f2(chemin.c_str(), ios::out | ios::trunc);

        if(!f2)
        {
            cout << "ERREUR: Une erreur est survenue lors de l'ecriture du fichier" << endl;
            return;
        }

        f2 << texte;

        f2.close();

        cout << endl << "Le fichier a ete "+ type + "." << endl << endl;
    }
    else
    {
        cout << "\nERREUR: Une erreur est survenue lors de l'ouverture du fichier" << endl;
        return;
    }

}

void decrypterMessage()
{
    string texte;
    cout << "Message a decrypter : ";
    cin.ignore(numeric_limits<int>::max(), '\n');
    getline(cin, texte);

    decrypter(texte);

    cout << endl << texte << endl << endl;
}

void decrypterFichier()
{
    string texte;
    string chemin;

    cout << "Chemin du fichier : ";
    cin.ignore(numeric_limits<int>::max(), '\n');
    getline(cin, chemin);

    ifstream f(chemin.c_str(),ios::in);

    if(f)
    {
        f.seekg(0, ios::beg);

        string ligne;
        getline(f, ligne);

        texte += ligne;

        while(getline(f, ligne))
            texte += "\n" + ligne;

        f.close();

        decrypter(texte);

        ofstream f2(chemin.c_str(), ios::out | ios::trunc);

        if(!f2)
        {
            cout << "ERREUR: Une erreur est survenue lors de l'ecriture du fichier" << endl;
            return;
        }

        f2 << texte;

        f2.close();

        cout << endl << "Le fichier a ete decrypte." << endl << endl;
    }
    else
    {
        cout << "\nERREUR: Une erreur est survenue lors de l'ouverture du fichier" << endl;
        return;
    }

}

int main()
{
        bool continuer = true;

    do
    {
        int choix;

        do
        {
            cout << "Cryptage Cesar" << endl << endl;
            cout << "1. Crypter" << endl;
            cout << "2. Decrypter" << endl;
            cout << "3. Quitter" << endl;
            cin >> choix;
            cout << endl;
        }while (choix < 1 || choix > 3);

        if(choix==1)
        {
            choix = 0;

            do
            {
                cout << "1. Crypter un message" << endl;
                cout << "2. Crypter un fichier texte" << endl;
                cin >> choix;
                cout << endl;
            }while (choix < 1 || choix > 2);

            if(choix == 1)
                crypterMessage("crypter");
            else if(choix == 2)
                crypterFichier("crypte");
        }
        else if(choix == 2)
        {
            choix = 0;

            do
            {
                cout << "1. Decrypter manuellement un message" << endl;
                cout << "2. Decrypter manuellement un fichier texte" << endl;
                cout << "3. Decrypter automatiquement un message" << endl;
                cout << "4. Decrypter automatiquement un fichier texte" << endl;
                cin >> choix;
                cout << endl;
            }while(choix < 1 || choix > 4);

            if(choix == 1)
                crypterMessage("decrypter");
            else if(choix == 2)
                crypterFichier("decrypte");
            else if(choix == 3)
                decrypterMessage();
            else if(choix == 4)
                decrypterFichier();
        }
        else if(choix == 3)
            continuer = false;

    }while(continuer);

    return 0;
}


Ma solution pour le Tic Tac Toe:
main.cpp
#include <iostream>
#include "Grille.h"
#include <time.h>

using namespace std;

void afficherGrille(Grille &grille);
void changerPseudos(string &pseudo1, string &pseudo2);

int main()
{
    string joueurs[2];
    joueurs[0] = "Joueur1";
    joueurs[1] = "Joueur2";

    cout << "*** Morpion ***" << endl << endl;

    changerPseudos(joueurs[0], joueurs[1]);

    bool recommencer = false;

    do
    {
        Grille grille(joueurs[0], joueurs[1]);

        int i = rand()%2;

        cout << joueurs[i] << " commence !" << endl;

        while(!grille.estFini())
        {
            afficherGrille(grille);

            cout << endl;

            int choix;
            bool bon;

            do
            {
                do
                {
                    cout << joueurs[i] << " : ";
                    cin >> choix;

                    if(choix <1 || choix >9)
                        cout << endl << "Choix incorrect" << endl << endl;

                }while(choix<1 || choix>9);

            bon = grille.jouer(joueurs[i], choix);

                if(!bon)
                    cout << "Choix incorrect, un pion est deja place a cet endroit" << endl << endl;

            }while(!bon);

            //Au 2e joueur de jouer
            i = 1 - i;
        }

        afficherGrille(grille);

        if(grille.getStatut()=="nul")
            cout << endl << "Partie nule !" << endl << endl;
        else
            cout << endl << grille.getGagnant() << " a gagne !" << endl << endl;

        string choix;

        cout << "Voulez-vous recommencer ? o ou n : ";
        cin >> choix;
        cout << endl;

        if(choix=="o")
        {
            string c2;
            cout << "Voulez-vous changer les pseudos ? o ou n : ";
            cin >> c2;

            cout << endl;

            if(c2=="o")
            {
                changerPseudos(joueurs[0], joueurs[1]);
            }

            recommencer = true;
        }

    }while(recommencer);

    return 0;
}

void changerPseudos(string &pseudo1, string &pseudo2)
{
    string j1;
    string j2;

    cout << "Pseudo pour le joueur 1 : ";
    cin >> j1;
    cout << "Pseudo pour le joueur 2 : ";
    cin >> j2;
    cout << endl;

    pseudo1 = j1;
    pseudo2 = j2;
}

void afficherGrille(Grille &grille)
{
    int ligne = 0;

    for(int i = 0; i<3; i++)
    {
        for(int j = 0; j<3; j++)
        {
            cout << grille.getValue(ligne*3 + j);
        }

        cout << endl;

        ligne++;
    }
}


Grille.cpp
#include "Grille.h"

using namespace std;

Grille::Grille(string joueur1, string joueur2)
{
    fini = false;
    statut = "";

    joueurs[joueur1] = 'x';
    joueurs[joueur2] = 'o';

    for(int i = 0; i < 9; i++)
    {
        m_grille.push_back('.');
    }
}

char Grille::getValue(int pos)
{
    return m_grille[pos];
}

bool Grille::aGagne()
{
        if ((m_grille[0] == m_grille[1] && m_grille[0] == m_grille[2] && m_grille[0]!='.')||
            (m_grille[3] == m_grille[4] && m_grille[3] == m_grille[5]&& m_grille[3]!='.')||
            (m_grille[6] == m_grille[7] && m_grille[6] == m_grille[8]&& m_grille[6]!='.')||
            (m_grille[0] == m_grille[3] && m_grille[0] == m_grille[6]&& m_grille[0]!='.')||
            (m_grille[1] == m_grille[4] && m_grille[1] == m_grille[7]&& m_grille[1]!='.')||
            (m_grille[2] == m_grille[5] && m_grille[2] == m_grille[8]&& m_grille[2]!='.')||
            (m_grille[0] == m_grille[4] && m_grille[0] == m_grille[8]&& m_grille[0]!='.')||
            (m_grille[2] == m_grille[4] && m_grille[2] == m_grille[6]&& m_grille[2]!='.')){

            return true;
            }
        else
            return false;
}

string Grille::getGagnant()
{
    return gagnant;
}

bool Grille::isFull()
{
    bool isFull = true;

    for(int i = 0; i<10; i++)
    {
        if(m_grille[i]=='.')
            isFull = false;
    }

    return isFull;
}

string Grille::getStatut()
{
    return statut;
}

bool Grille::jouer(string joueur, int pos)
{
    if(m_grille[pos - 1]=='.')
    {
        m_grille[pos - 1]=joueurs[joueur];
        if(aGagne())
        {
            fini = true;
            gagnant = joueur;
        }
        else if(isFull())
        {
            fini = true;
            statut = "nul";
        }

        return true;
    }
    else
        return false;
}

bool Grille::estFini()
{
    return fini;
}


Grille.h
#ifndef DEF_GRILLE
#define DEF_GRILLE

#include <iostream>
#include <map>
#include <vector>

class Grille
{
    public:
    Grille(std::string joueur1, std::string joueur2);
    char getValue(int pos);
    bool jouer(std::string joueur, int pos);
    bool estFini();
    bool aGagne();
    bool isFull();
    std::string getStatut();
    std::string getGagnant();

    private:
    std::vector<char> m_grille;
    std::map<std::string, char> joueurs;
    bool fini;
    std::string gagnant;
    std::string statut;
};

#endif
29 juin 2011 à 22:41:08

J'ai fini le TicTacToe, avec une solution qui me semble plus élégante (la lourdeur étant principalement dans la gestion de la fin de partie) :
#include <iostream>
#include <vector>

typedef std::vector<char> line;
typedef std::vector<line> board;

void display   (const board & b);
char the_winner(const board & b);

int main(int, char**) {
    char player = 'X', winner;
    board tic_tac_toe(3, line(3, ' '));

    display(tic_tac_toe);
    while ((winner = the_winner(tic_tac_toe)) == '?') {
        int x = -1, y = -1;
        while (x > 3 || x < 1 || y > 3 || y < 1 || tic_tac_toe[y - 1][x - 1] != ' ') {
            std::cout << "Joueur " << player << ", où voulez-vous jouer ?" << std::endl;
            std::cout << "X : ";
            std::cin >> x;
            std::cout << "Y : ";
            std::cin >> y;
        }
        tic_tac_toe[y - 1][x - 1] = player;
        display(tic_tac_toe);
        player = (player == 'X' ? 'O' : 'X');
    }

    if (winner == '!') {
        std::cout << "Match nul !" << std::endl;
    } else {
        std::cout << "Le gagnant est le joueur " << winner << " !" << std::endl;
    }

    return 0;
}

void display(const board & b) {
    std::cout << " |1|2|3|" << std::endl;
    std::cout << "-+-+-+-+" << std::endl;
    std::cout << "1|" << b[0][0] << "|" << b[0][1] << "|" << b[0][2] << "|" << std::endl;
    std::cout << "-+-+-+-+" << std::endl;
    std::cout << "2|" << b[1][0] << "|" << b[1][1] << "|" << b[1][2] << "|" << std::endl;
    std::cout << "-+-+-+-+" << std::endl;
    std::cout << "3|" << b[2][0] << "|" << b[2][1] << "|" << b[2][2] << "|" << std::endl;
    std::cout << "-+-+-+-+" << std::endl;
}

char the_winner(const board & b) {
    char player;
    bool found;
    // Check lines
    for (int l = 0 ; l < 3 ; ++l) { // l = numero de ligne
        player = b[l][0];
        found = true;
        for (int c = 1 ; c < 3 ; ++c) { // c = numero de colonne
            if (b[l][c] != player) {
                found = false;
                break;
            }
        }
        if (found && player != ' ') {
            return player;
        }
    }
    // Check columns
    for (int c = 0 ; c < 3 ; ++c) {
        player = b[0][c];
        found = true;
        for (int l = 1 ; l < 3 ; ++l) {
            if (b[l][c] != player) {
                found = false;
                break;
            }
        }
        if (found && player != ' ') {
            return player;
        }
    }
    // Check diagonal topleft - bottomright
    player = b[0][0];
    found = true;
    for (int i = 1 ; i < 3 ; ++i) {
        if (b[i][i] != player) {
            found = false;
            break;
        }
    }
    if (found && player != ' ') {
        return player;
    }
    // Check diagonal topright - bottomleft
    player = b[0][2];
    found = true;
    for (int i = 1 ; i < 3 ; ++i) {
        if (b[i][2 - i] != player) {
            found = false;
            break;
        }
    }
    if (found && player != ' ') {
        return player;
    }
    // Check ex-aeco - if true, return '!'
    found = true;
    for (int l = 0 ; l < 3 ; ++l) {
        for (int c = 0 ; c < 3 ; ++c) {
            if (b[l][c] == ' ') {
                found = false;
                break;
            }
        }
        if (!found) {
            break;
        }
    }
    if (found) {
        return '!';
    }
    // Nothing - return '?'
    return '?';
}

Edit : Petite précision : Pour la recherche du gagnant, j'ai préféré conserver un code générique, mais il est évident qu'un listage bruteforce-like pourrait également fonctionner.

@Dumpy:

Chiffre de César :

- La fonction UpToLow pourrait utiliser des caractères, plus compréhensibles que les codes hexa :
if (str[i] >= 'A' && str[i] <= 'Z')
    str[i] = str[i] + 'a' - 'A';

- Pourquoi interdire un décalage négatif ? Il pourrait être utilisé pour décrypter simplement.
- Même remarque pour les 'X' au niveau de la fonction crypter - et, d'ailleurs, tout le long du code.
- Il serait possible d'utiliser la fonctions tolower (cctype) pour simplifier le code de UpToLow, par exemple.
- Les lignes 22 à 45 sont vraiment tordues, pourquoi ne pas faire simplement :
char & c = texte[i]; // Référence pour propager automatiquement la modification
if (isupper(c)) c = (((c - 'A') + decalage) % 26) + 'A';
if (islower(c)) c = (((c - 'a') + decalage) % 26) + 'a';
if (isdigit(c)) c = (((c - '0') + decalage) % 10) + '0'; // Retirable, c'est pour crypter aussi les numeros

- La fonction decrypter devrait s'appeller casser
- Il devrait y avoir une fonction decrypter contenant uniquement : crypter(texte, -decalage);


Je dois malheureusement m'arrêter là pour ce soir, à bientôt !
29 juin 2011 à 23:21:20

moi ce que j'avait fait, (pour pas m'embéter) c'est un objet Grille, avec un char[3][3] en argument qui prend soit ' ', 'o', 'x'. et ensuite je l'affiche dedans, je fait une méthode qui test si l'utilisateur à gagné (peut largement gagner en performances car l'algoritgme est du style : "je test tout les cas un par un" :p )
mais sinon ca me paraît le bon plan de faire comme ca.

EDIT :
je l'ai refait (enfin juste la classe) en niveau très basique, le plus propre possible (et j'en ai souffert :p ) mais j'ai la flemme de coder le main pour le moment ;) . Voici :
grille.h :
#ifndef GRILLE_H
#define GRILLE_H

#include <iostream>

class Grille
{
    public:
        Grille(char starting = 'o');// génère la grille remplit par défaut par les nombre 1, 2, 3, ..., 7, 8, 9
        void afficher();// affiche la grille
        void init();// initialise toute les cases de m_grille à ' '
        bool playAt(int x, int y = -1);// soit les coordonnées de m_grille, soit un nombre entre 1 et 9
        int won();// 0 si personne, 1 si o, 2 si x
        char next();
    private:
        char m_grille[3][3];// la grille
        char m_next;// le prochain "joueur" à jouer : 'o' ou 'x'
};

#endif


grille.cpp :
#include "grille.h"

using namespace std;

Grille::Grille(char starting) : m_next(starting)
{
    for(int i = 0 ; i < 9 ; i++)
        m_grille[i/3][i%3] = i+'1';
}

void Grille::afficher()
{
    cout << "     |     |" << endl;
    cout << "  " << m_grille[2][0] << "  |  " << m_grille[2][1] << "  |  " << m_grille[2][2] << endl;
    cout << "_____|_____|_____" << endl;
    cout << "     |     |" << endl;
    cout << "  " << m_grille[1][0] << "  |  " << m_grille[1][1] << "  |  " << m_grille[1][2] << endl;
    cout << "_____|_____|_____" << endl;
    cout << "     |     |" << endl;
    cout << "  " << m_grille[0][0] << "  |  " << m_grille[0][1] << "  |  " << m_grille[0][2] << endl;
    cout << "     |     |" << endl;
}

void Grille::init()
{
    for(int i = 0 ; i < 9 ; i++)
        m_grille[i/3][i%3] = ' ';
}

char Grille::next()
{
    return m_next;
}

bool Grille::playAt(int x, int y)
{
    if(y < 0)
    {
        x--;
        y = x/3;
        x %= 3;
    }

    if(m_grille[y][x] == 'o' || m_grille[y][x] == 'x' || x < 0 || x > 2 || y < 0 || y > 2)
        return false;

    m_grille[y][x] = m_next;
    m_next = (m_next == 'o')?'x':'o';
    return true;
}

int Grille::won()
{
    if(((m_grille[0][0] == m_grille[1][1] && m_grille[1][1] == m_grille[2][2]) || (m_grille[0][2] == m_grille[1][1] && m_grille[1][1] == m_grille[2][0])) && (m_grille[1][1] == 'o' || m_grille[1][1] == 'x'))
    {
        return (m_next == 'o')?1:2;
    }
    else
    {
        for(int i = 0 ; i < 3 ; i++)
        {
            if(m_grille[i][0] == m_grille[i][1] && m_grille[i][1] == m_grille[i][2] && (m_grille[i][1] == 'o' || m_grille[i][1] == 'x'))
                return (m_next == 'o')?1:2;
            else if(m_grille[0][i] == m_grille[1][i] && m_grille[1][i] == m_grille[2][i] && (m_grille[1][i] == 'o' || m_grille[1][i] == 'x'))
                return (m_next == 'o')?1:2;
        }
        return 0;
    }
}


main.cpp :
#include <iostream>
#include <cstdlib>
#include "grille.h"

using namespace std;

int main()
{
    Grille g;
    int choix = 0;
    cout << "bienvenu dans ce Tix-Tac-Toe, voici la grille numérotée" << endl;
    g.afficher();
    g.init();
    while(!g.won())
    {
        cout << "c'est à '" << g.next() << "' de jouer" << endl;
        do
        {
            choix = 0;
            cout << "quel est votre choix '" << g.next() << "' ?" << endl;
            cin >> choix;
        }while(!g.playAt(choix));
        system("clear");// pas sur que c'est portable ...
        g.afficher();
    }
    cout << ((g.won() == 2)?"'o'":"'x'") << "a gagné la partie" << endl;
    return 0;
}


le main est absolument facile à faire (si quelqu'un veut le faire) il suffit de faire une boucle puis de faire jouer normalement en testant won() à chaques fois. Si won() = 1 : "'o' à gagné" et si won() = 2 : "'x' à gagné"

EDIT 2 : je devait PITETRE être fatigué mais ca marche tous juste pas (encore un piti pb), je règle ca tout de suite je réactualise le code précédent

EDIT 3 : voila, le seul problème, c'est si on autre choses qu'une lettre, il fait une boucle infinie sans faire le cin ... :euh:
30 juin 2011 à 4:55:11

Je verrais plutôt un code de ce genre pour le chiffrement de César :
#include <iostream>
#include <string>
#include <cstdlib>
#include<cstdio>
using namespace std;

void Cesar(string& str, int decalage)
{
   size_t i;
   string alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   for(i=0;str[i];i++)
      str[i] = alpha.at((alpha.find_first_of(str[i])+decalage)%26);
}

int main (int argc, char** argv)
{
   int decalage, i;
   string str = "";
   if(argc>1)
      str += argv[1];
   else
      cin >> str;
   if(argc>2)
      sscanf(argv[2], "%d", &decalage);
   else
      cin >>decalage;
   for(i=0;str[i];i++)
      str[i] = toupper(str[i]);
   
   Cesar(str, decalage);
   cout << str;
   return EXIT_SUCCESS;
}


Afin d'obtenir un code indépendant de tout Char-set. Et donc qui fonctionne aussi pour les non ascii.Mais je n'ai pas pris en compte les caractères non alpha, c'est réglable en 1 if.
Étudiant - Codeur en C | Articles                                                                 ache.one         Copying is an act of love.    -   
30 juin 2011 à 10:33:18

Effectivement, comme on me l'a fait remarquer mon code est loin d'être le plus propre car je suis encore débutant (~1 mois). (cela reste tout de même une solution possible)

Sinon, merci d'avoir posté des solutions plus propre, ça me permettra sans doute de progresser, surtout en POO.

[Exercices] Venez vous entraîner !

× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
  • Editeur
  • Markdown