Des chiffres sans les lettres (win32)

Description

Dans le meme style que "des chiffres et les lettres", seulement c'est seulement les chiffres ici.
le programme sort un jeu de 6 nombres ainsi qu'un nombre cible a trouver.
Si l'ordi trouve le bon resultat, il affiche tout les calculs lorsqu'on clique sur le bouton.
Si il ne trouve pas le bon resultat, il affiche les calculs du nombre le plus proche qu'il a trouvé.

Une fonction recursive essaye tout les calculs possible entre les 6 nombres avec les 4 operateurs (+-*/).
Je suis pas un pro en algo, mais ca a l'air de bien fonctionner.
Bien evidemment il n'affiche pas le calcul le plus simple, mais seulement un calcul qui permet d'atteindre le resultat.

J'ai testé une centaine de fois, et je crois qu'il n'y a plus de bug.
Merci d'avances pour les remarques/idées ou les bugs trouvés.

[UPDATE] correction du bug qui faisait que de temp en temp l'affichage du jeu de nombre + de la valeur a chercher se bloquait.

Source / Exemple :


#include <stdio.h>
#include <windows.h>
#include "resource.h"

#define CNB 6 // nombre de nombre
#define DIF(a,b) ((a)<(b) ? ((b)-(a)) : ((a)-(b))) // diffence entre 2 nbres, positif

HWND hOK, hTarget, hCalculs;
HWND hDialog;
char operateurs[4] = {'+','-','*','/'};
char szRes[1024];    // calculs
char szResult[2048]; // calculs qu'on affichera
int NB_Array[CNB] = {0,0,0,0,0,0};
int iTarget = 0;
int NearestDif = 9999;
int NearestResult = 0;
BOOL bInGame = FALSE; // suivant cette valeur, le bouton hOK lance une nouvelle partie ou affiche le resultat de la partie précédente

BOOL CALLBACK AppDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
int CalcTarget(int iTarget, int * NB, int cNB, char * szRes);
int Calc(int a, int b, int iOperateur);
int InitGame(int * pArray);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
srand(GetTickCount());
DialogBox(hInstance, "MainDialog", 0, AppDlgProc);
return 0;
}

BOOL CALLBACK AppDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch(uMsg) 
	{
	case WM_INITDIALOG:
		hDialog = hDlg;
		hOK = GetDlgItem(hDlg, IDC_OK);
		hCalculs = GetDlgItem(hDlg, IDC_CALCULS);
	return 0;
	case WM_COMMAND:
		switch(LOWORD(wParam)) 
		{
		case IDC_OK:
			if(!bInGame){ // FALSE: nouveau jeu de nbre, et on fait les calculs
				bInGame = TRUE;
				SetWindowText(hCalculs, NULL);
				EnableWindow(hOK, FALSE); // on desactive le bouton pendant le calcul
				NearestDif = 9999;
				InitGame((int*)&NB_Array);
				memset(szRes, 0, sizeof(szRes));
				if(0==CalcTarget(iTarget,(int*) &NB_Array, CNB, szRes)){
					CalcTarget(NearestResult,(int*) &NB_Array, CNB, szRes);
					strcpy(szResult, "Le résultat n'a pas été trouvé, voici le resultat le plus proche:\r\n");
					strcat(szResult, szRes);
				}else strcpy(szResult, szRes);
				EnableWindow(hOK, TRUE);
				SetWindowText(hOK, "Afficher la solution");}
			else{ // TRUE: on affiche le resultat
				SetDlgItemText(hDlg, IDC_CALCULS, szResult);
				SetWindowText(hOK, "Rejouer");
				bInGame = FALSE;}
		return 0;
		case IDCANCEL: 
			EndDialog(hDlg, 0);
		}
	}
return 0;
}

int CalcTarget(int iTarget, int * NB, int cNB, char * szRes)
{
	int i = 0;  // boucle d'un nombre de la liste
	int j = 0;  // boucle d'un autre nombre de la liste
	int op = 0; // boucle pour les 4 types d'operateurs 
	// petite chaine pour copier le calcul courant dans la chaine qui contient tout les calculs
	char szCalcul[64]; 

	for(i=0; i<cNB-1; i++)
		for(j=i+1; j<cNB; j++)
			for(op=0; op<4; op++)
			{
				int iCResult = Calc(*(NB+i), *(NB+j), op);
				if(!iCResult) continue;
				// si on trouve le bon nombre, c'est fini
				if(iCResult == iTarget){
					sprintf(szCalcul,"%d %c %d = %d\r\n", *(NB+i), operateurs[op], *(NB+j), iTarget);
					strcpy(szRes, szCalcul);
					return iTarget;
				}else{
					// sinon, on garde une trace du resultat le + proche
					if(DIF(iTarget, iCResult) <= NearestDif) {
						NearestDif = DIF(iTarget, iCResult);
						NearestResult = iCResult;}
				}
				sprintf(szCalcul,"%d %c %d = %d\r\n", *(NB+i), operateurs[op], *(NB+j), iCResult);
				strcpy(szRes, szCalcul);

				// on refais un tableau de nombre sans copier NB[i] et NB[j], mais en rajoutant iCResult
				// puis on rappelle la fonction avec ce tableau (recursif)
				int NB_2[CNB] = {0,0,0,0,0,0};
				int a=0, b=0;
				for(a=0; a<cNB; a++){
					if(*(NB+a) == *(NB+i) || *(NB+a) == *(NB+j)) continue;
					NB_2[b++] = *(NB+a);}
				NB_2[b] = iCResult;
				if(CalcTarget(iTarget,(int*) &NB_2, b+1, szRes+strlen(szRes))) return iTarget;
			}
return 0;
}
// fonction qui calcule operation de base, serait mieux inline
int Calc(int a, int b, int iOperateur)
{
	switch(iOperateur)
	{
	case 0: return (a+b);
	case 1: return (a-b);
	case 2: return (a*b);
	case 3: if(0 == a%b) return (a/b);
	}
return 0;
}

// choisi 6 nouveaux nombres + nouveau nombre a trouver
// affiche le tout dans les fenetres appropriées
int InitGame(int * pArray) 
{
	int i = 0; // pour les boucles
	int i2= 0; //
	int iValue = 0;
	int NB_Values[14] = {1,2,3,4,5,6,7,8,9,10,25,50,75,100}; // valeurs de depart possibles
	for(i=0; i<6; i++) *(pArray+i) = 0; // tableau a 0
	// nouvelles valeurs dans le tableau, et on empeche qu'une valeur se retrouve 2 fois dans le tableau
	for(i=0; i<6; i++){
NewValue:
		iValue = rand()%14;
		for(i2=0; i2<6; i2++) if(*(pArray+i2) == NB_Values[iValue]) goto NewValue;
		SetDlgItemInt(hDialog, IDC_NBRES+i, NB_Values[iValue], FALSE);

  • (pArray+i) = NB_Values[iValue];}
iTarget = (rand()%900) + 100; // entre 100 et 999 SetDlgItemInt(hDialog, IDC_TARGET, iTarget, FALSE); return 0; }

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.