Un algo qui marche, sauf à la fin.

eaatmaan Messages postés 1 Statut Membre -  
 eaatmaan -
Bonjour,
J'ai fait un petit programme en C pour la résolution des sudoku.
Je sais que je n'innove pas mais malgré tout ce que j'ai pu lire ici, j'ai une erreur que je n'arrive pas à résoudre:
J'ai voulu travailler sur différentes étapes de difficultés.
1: Les sudokus simples où on peux remplir toutes les cases en regardant simplement les lignes/colonne/carrés où une seule valeur est manquante. (Ici, tout fonctionne)
2: Les sudokus un peu plus difficiles où des plusieurs valeurs sont manquantes et où je regarde si une valeur possible est seule dans une ligne/colonne/carré.
Et là, tout se passe bien jusqu'à ce qu'il reste 5 ou 6 cases, dès lors mon algo me met plusiseurs 7,8 ou 9 dans une ligne et une colonne...

Mon sudoku est stocké dans un tableau de 9*9 cases de type cellule comprenant la valeur et un tableau de 9 booléens permettant de stocker les valeurs possibles.

PS: dans le menu, la lettre v permet de voir les possibilités d'une case en particulier.

Voici mon code, si une âme généreuse à un peu de temps je lui en serait fort reconnaissant!

#include <stdio.h>

typedef struct Cellule	//Structure Cellule
{//Definition d'une case du tableau.
	int val;	//une case valeur.
	int sol[9];	//Un tableau contenant les possibilités.
} cellule;	//type cellule.


void initialiser_val();	//0 dans toutes les cases.
void initialiser_sol(); //1 dans toutes les cases du tableau solution.
void menu();	//Le menu d'actions.
void afficher();	//Affiche simplement le tableau.
void remplir();	//Remplis des cases du tableau.
void solution();	//Tente de remplir les cases vides.
void no_sol(int i, int j);	//Supprime toutes les solution dans la case i.j.
void ellim_poss();	//Supprime les valeurs impossibes.
void sol_unique_poss();	//Affecte la valeur si unique solution.
void voir();	//Donne la valeur et les possibilités d'une case.
int sol_mul_car (int lig, int col, int valm);
int sol_mul_lig (int ligne, int valm);
int sol_mul_col (int colonne, int valm);
void ellim_poss_multiple();


cellule Sudoku[9][9];	//Le tableau en variable globale.

int main (int argc, char **argv)
{

	initialiser_val();
	initialiser_sol();

	menu();



return 0;
}

void initialiser_val()
{
	int i,j;
	for (i=0; i<9; i++)
	{//Parcours de lignes.
		for (j=0; j<9; j++)
		{//Parcours de collones.
			(Sudoku[i][j]).val = 0;
		}
	}
}

void initialiser_sol()
{
	int i,j,k;
	for (i=0; i<9; i++)
	{//Parcours de lignes.
		for (j=0; j<9; j++)
		{//Parcours de collones.
			for (k=0; k<9; k++)
			{
				(Sudoku[i][j]).sol[k] = 1;
			}
		}
	}
}

void menu()
{
	char commande = 0;
	int cont = 1;
	do
	{
	printf("r pour remplir; a pour afficher; s pour la solution; q pour quitter;");
	scanf("%c", &commande);
	
		switch (commande)
		{	
			case 'r':
			{
				initialiser_sol();
				do		//---------------------------------------------------------------------------------------//
				{									//
					remplir();							//
					printf("\nContinuer à remplir? o/n\t");				//Boucle de remplissage de tableau.
					scanf("%i", &cont);						//
					printf("\n");							//
				} while (cont);	//---------------------------------------------------------------------------------------//
			break;
			}

			case 'a':
			{
				afficher();
				break;
			}

			case 'q':
			{
				break;
			}

			case 's':
			{
				/*changement = solution();
				if (changement == 0)
				{
					printf("Pas de changement effectués\n");
				}*/
				solution();
				break;
			}
			
			case 'v':
			{
				voir();
				break;
			}
		}
	 getchar();
	} while (commande != 'q');
}

void afficher()
{
	int i,j;
	printf("\n");
	for (i=0; i<9; i++)
	{//Parcours de lignes.
		for (j=0; j<9; j++)
		{//Parcours de collones.
			if (Sudoku[i][j].val != 0)
			{//Si la case n'est pas vide.
				printf(" %i ", Sudoku[i][j].val);	//On affiche la valeur.
			}
			else 
			{//Si la case est vide.
				printf(" . ");	//On affiche un point.
			}
			if ((j+1)%3 == 0)
			{//3eme ou 6eme colonne.
				printf(" ");
			}
			else
			{//Autres colonnes.
				printf("|");
			}
		}
		printf("\n");
		if ((i+1)%3 == 0)
		{//Lignes 3 et 6, un espace.
			printf("\n");
		}
	}
}

void remplir(){
	int i,j,k;

	printf("Quelle ligne?\t");
	scanf("%i", &i);	//On choisit la ligne.

	printf("Quelle colonne?\t");
	scanf("%i", &j);	//On choisit la colonne.

	printf("Quelle valeur?\t");
	scanf("%i", &k);	//On choisit la valeur.

	if (i<10 && i>0 && j<10 && j>0 && k<10 && k>=0)	//Si on est bien entre 1 et 9 pour i,j et entre 0 et 9 pour k.
	{
		Sudoku[i-1][j-1].val = k;	//On affecte k à la valeur de la case.
	}
	else
		printf("Mauvaises valeurs\n");
}

void no_sol(int i, int j)
{
	int a;
	for (a=0; a<9; a++)
	{
		(Sudoku[i][j]).sol[a]=0;	//Toutes les possibilités sont mise à 0.
	}
}

void solution()
{
	ellim_poss();	
	sol_unique_poss();
	ellim_poss_multiple();
	sol_unique_poss();

}

void ellim_poss()
{
	int i,j;	//Des variables de parcours global.
	int a,b;	//Des varaibles de parcours internes.
	int var;	//Une variable de stockage.
	for (i=0; i<9; i++)
	{//Parcours des lignes.
		for (j=0; j<9; j++)
		{//Parcours des colonnes.
			if (Sudoku[i][j].val != 0)
			{//Si la case n'est pas vide.
				no_sol(i,j);	//On supprime toutes les possibilités de changements.
				var = Sudoku[i][j].val;
				for (a=0; a<9; a++)			//----------------------------------------------------------//
				{					//
					Sudoku[a][j].sol[var-1] = 0;	//	On enlève la valeur dans la ligne et dans la colonne.
					Sudoku[i][a].sol[var-1] = 0;	//
				}					//----------------------------------------------------------//
				
				for (a=0; a<3; a++)
				{//Parcours des lignes du carre de 3*3
					for (b=0; b<3; b++)
					{//Parcours des colonnes du carre de 3*3
						Sudoku[(3*(i/3))+((i+a)%3)][(3*(j/3))+((j+b)%3)].sol[var-1] = 0;	//Enleve poss carre.
					}
				}
			}
		}
	}
}

void sol_unique_poss()
{
	int i,j;
	int a;
	int s, temp;
	for (i=0; i<9; i++)
	{//Parcours des lignes
		for (j=0; j<9; j++)
		{//Parcours des colonnes.
			s = 0; temp = 0;
			for (a=0; a<9; a++)
			{//Parcours des possibilites.
				s += Sudoku[i][j].sol[a];	//Somme des booleens de possibilites.
				if (Sudoku[i][j].sol[a])
				{//Si la S[i][j].sol[a] n'est pas nulle.
					temp = a;	//temp garde l'indice.
				}
			}
			if (s == 1)
			{//Si il n'y a qu'une seule possibilité.
				Sudoku[i][j].val = temp+1;	//On affecte la seule valeur possible.
			}
		}
	}
}


void ellim_poss_multiple()
{
	int i,j,k;
	for (i=0; i<9; i++)
	{//Parcours des lignes.
		for (j=0; j<9; j++)
		{//Parcours des colonnes.				
			if (Sudoku[i][j].val == 0)
			{//Si la case est vide.
				for (k=0; k<9; k++)
				{//Parcours des solutions
					if (Sudoku[i][j].sol[k] == 1)
					{//k+1 est une valeur possible.
						if (sol_mul_lig(i,k) || sol_mul_col(j,k) || sol_mul_car(i,j,k) )
						{//Si valeur possible une seule fois
							Sudoku[i][j].val = k+1;
							no_sol(i,j);
							solution();
						}
					}
				}
			}
		}
	}
}

int sol_mul_lig(int ligne, int valm)
{
	int j, retour = 0;
	for (j=0; j<9; j++)
	{//Parcours des cases de la lignes.
		if (Sudoku[ligne][j].val == 0)
		{//Si une case de la ligne est vide.
			if (Sudoku[ligne][j].sol[valm] == 1)
			{//Si dans cette case vide, la valeur est possible.
				retour ++;
			}
		}
	}
return (retour == 1);
}

int sol_mul_col(int colonne, int valm)
{
	int i, retour = 0;
	for (i=0; i<9; i++)
	{//Parcours des cases de la colonne.
		if (Sudoku[i][colonne].val == 0)
		{//Si une case de la ligne est vide.
			if (Sudoku[i][colonne].sol[valm] == 1)
			{//Si dans cette case vide, la valeur est possible.
				retour ++;
			}
		}
	}
return (retour == 1);
}

int sol_mul_car(int lig, int col, int valm)
{
	int a, b, retour = 0;
	for (a=0; a<3; a++)
	{//Parcours des lignes du carre de 3*3
		for (b=0; b<3; b++)
		{//Parcours des colonnes du carre de 3*3
			if ((Sudoku[(3*(lig/3))+((lig+a)%3)][(3*(col/3))+((col+b)%3)]).val == 0)
			{//Si la case est vide
				if ((Sudoku[(3*(lig/3))+((lig+a)%3)][(3*(col/3))+((col+b)%3)]).sol[valm] == 1)
				{//La valeur est possible.
					retour ++;
				}
			}
		}
	}
return (retour == 1);
}
		
void voir()
{	ellim_poss();
	int i,j,k;
	printf("Quelle ligne? \t");
	scanf("%i",&i);
	printf("Quelle colonne? \t");
	scanf("%i",&j);
	printf("\n Valeur: %i\t Possibilites:", Sudoku[i-1][j-1].val);
	for (k=0; k<9; k++)
	{
		if (Sudoku[i-1][j-1].sol[k] == 1)
		{
			printf("%i ", k+1);
		}
	}
	printf("\n");
}
A voir également:

1 réponse

eaatmaan
 
up.
0