#include <iostream>
#include <sstream>

// Mastermind des chiffres
//
// Olivier Garet 2009
//
// code sous licence GPL
//
// compilation : g++ -o mastermind mastermind.cpp
//
// Testé avec g++ 3.3,3.4,4.1
//

using namespace std; 

struct reponse
{ int noir[2],blanc[2] ; };

const int leplus=43;
const int lemoins=45;
const int lefois=42;
const int lesur=47;



int valeur(string s)
{ int a,b,c,r;
 bool entier,dbz,incorrect,ok;
  a=(int)(s[0])-48;
  b=(int)(s[2])-48;
  c=(int)(s[4])-48;
  dbz=false;
  entier=true;
  incorrect=(s.length()!=5) ||  (a<0) || (a>9) || (b<0) || (b>9) || (c<0) || (c>9); 
  //  cout << a << endl;
  //cout << b << endl;
  //cout << c << endl;

 switch(s[1]) 
  {
  case leplus: //cout << "+" ; 
	      switch (s[3])
		{   case leplus: r=a+b+c;  break;
                    case lemoins: r=a+b-c;  break;
                    case lefois: r=a+b*c;  break;
                    case lesur: if (c>0) {r=a+b/c; entier=((b%c)==0); } else {dbz=true;};  break;
		default: incorrect=true;   
		}; break; 
  case lemoins: //cout << "-" ; 
	      switch (s[3])
		{   case leplus: r=a-b+c;  break;
                    case lemoins: r=a-b-c;  break;
                    case lefois: r=a-b*c;  break;
                    case lesur: if (c>0) {r=a-b/c; entier=((b%c)==0); } else {dbz=true;} ;  break;
		default: incorrect=true; 
  }; break; 
  case lefois: //cout << "*" ; 
	      switch (s[3])
		{   case leplus: r=a*b+c;  break;
                    case lemoins: r=a*b-c;  break;
                    case lefois: r=a*b*c;  break;
                    case lesur: if (c>0)  {r=a*b/c; entier=(((a*b)%c)==0); } else {dbz=true;} ;  break;
		default: incorrect=true; 
  }; break; 
  case lesur:  //cout << "/" ;
    if (b>0) { 
	      switch (s[3])
		{   case leplus: r=a/b+c;  break;
                    case lemoins: r=a/b-c;  break;
                    case lefois: r=a/b*c;  break;
		    case lesur: if (c>0)  {r=a/b/c; entier=((b%c)==0);} 
                                else {dbz=true;};  break;
   		    default: incorrect=true;   
		}; entier=entier && ((a%b)==0);} else {dbz=true;}; break; 
  default: incorrect=true;
} 
 if (!entier) { r=-3; };
 if (dbz) {r=-1;}; 
 if (incorrect) {r=-2;}; 
 return r;
}

string hasard()
{ string s="";
 string l="+-*/";
  float q;
  q = float(random())/float(RAND_MAX);
  s+=char(int(10*q)+48);
  q = float(random())/float(RAND_MAX);
  s+=l[int(4*q)];
  q = float(random())/float(RAND_MAX);
  s+=char(int(10*q)+48);
  q = float(random())/float(RAND_MAX);
  s+=l[int(4*q)];
  q = float(random())/float(RAND_MAX);
  s+=char(int(10*q)+48);
  return s;
}

reponse compare(string reel, string proposition)
 
{  int n;
   int b;
   int k;
   reponse r;
   int lp=proposition.length();
   int lr=reel.length();
   for(int par=0; par<2; par++)
     { n=0; b=0;
   for(int i=par; i<lp; i+=2)
     { // k=(int)(proposition[i]);
     //     cout << k << " ";
       if (proposition[i]==reel[i]) {n++; }
       else 
	 {  int a=0;
            for(int j=par; j<lr; j+=2)
            if (proposition[i]==reel[j]) { a=1;};
	    b+=a;
         }
     }
   r.noir[par]=n;
   r.blanc[par]=b;
   //   cout << n << " " << b << endl ;
     };   
   return r;
}


void affiche(reponse s)
{ for(int j=0; j<s.noir[0]+s.noir[1]; j++) { cout << "X" ; };
  for(int j=0; j<s.blanc[0]+s.blanc[1]; j++) { cout << "O" ; };
}

void affichesympa(reponse s)
{ for(int j=0; j<s.noir[1]; j++) { cout << "X" ; };
  for(int j=0; j<s.blanc[1]; j++) { cout << "O" ; };
  for(int j=s.noir[1]+s.blanc[1]; j<2;j++) { cout << ".";};
  cout << " "; 
  for(int j=0; j<s.noir[0]; j++) { cout << "X" ; };
  for(int j=0; j<s.blanc[0]; j++) { cout << "O" ; };
  for(int j=s.noir[0]+s.blanc[0]; j<3;j++) { cout << ".";};
  cout << " (";
  if (s.noir[1]==1) { cout << "1 signe bien placé ";};
  if (s.noir[1]==2) { cout << "2 signes bien placés ";};
  if (s.blanc[1]==1) { cout << "1 signe mal placé ";};
  if (s.blanc[1]==2) { cout << "2 signes mal placés ";};
  if (s.noir[0]==1) { cout << "1 chiffre bien placé ";};
  if (s.noir[0]>1) { cout << s.noir[0] << " chiffres bien placés ";};
  if (s.blanc[0]==1) { cout << "1 chiffre mal placé ";};
  if (s.blanc[0]>1) { cout <<  s.blanc[0] << " chiffres mal placés ";};
  cout << " )";
}


int main()
{ cout << "Le but du jeu est de deviner une opération avec 3 chiffres et deux opérateurs dont le résultat est donné." << endl << "Par exemple 3+2*5 est une opération possible." << endl << "Pour chaque proposition, l'ordinateur donne " << endl << 
  "- le nombre de signes bien placés" << endl <<   
  "- le nombre de signes mal placés"  << endl << 
  "- le nombre de chiffres bien placés" << endl <<  
    "- le nombre de chiffres mal placés." << endl << " Ainsi, dans notre exemple, la proposition 3*5-2 a " << endl  <<
    "- 1 signe mal placé (le *)" << endl << "- un chiffre bien placé (le 3)" << endl << "- un chiffre mal placé (le 2)." << endl << "A vous de jouer !" << endl;    



 string a,b,encore ;
 int re,v=-1;
 reponse t;

 encore="oui";
 /*   cout << "chaine 1" << endl ;
   cin >> a ;
   cout << "chaine 1" << endl ;
   cin >> b ;
t=compare(a,b);
 cout << t.noir[0] << " " << t.noir[1]  << " " <<  t.blanc[0]  << " " << t.blanc[1] << endl ;
  return 0;
 */
 srandom(time(NULL));
 while (encore=="oui"){ 
 t.noir[0]=0;
 t.noir[1]=0;
 re=-1; while (re<0) { a=hasard(); re=valeur(a); };
 while (t.noir[0]+t.noir[1]<5) { 
  cout << "Le résultat est " << re <<endl ;
  cin >> b ;
  if (b=="abandon") {t.noir[0]=3; t.noir[1]=2; cout << " C'était " << a << endl ; }
  else {v=valeur(b);  if (v==re)
    {
  t=compare(a,b);
  affichesympa(t); }
  else { switch(v){
  case -2: cout << "proposition  incorrecte. " << endl ; break;
  case -1: cout << "On ne peut pas diviser par 0. " << endl ; break;
  case -3: cout << "Résultat partiel non entier" << endl ; break;
  default: cout << "tu t'es trompé, ça ne fait pas " << re << "." << endl ; }
  }
  } }cout << endl ;
  //  cout << valeur(a);
 cout << "une autre partie ? (oui/non)" << endl ;
 cin >> encore ;
 }
}
