Sudoku en C ou C++

Fermé
Ciola Messages postés 11 Date d'inscription jeudi 26 février 2009 Statut Membre Dernière intervention 21 septembre 2009 - 21 sept. 2009 à 15:54
Neliel Messages postés 6146 Date d'inscription jeudi 9 juillet 2009 Statut Contributeur Dernière intervention 20 mars 2017 - 27 sept. 2009 à 19:03
Bonjour,

Pour me présenter au BTS, je dois présenter plusieurs application, j'ai choisi d'en faire une sur le Sudoku en C ou C++ donc je dois réaliser un programme capable de générer des grilles aléatoires, de vérifier la solution saisie par l'utilisateur et afficher la solution. Mon problème c'est que je suis vraiement pas douée et je sais même pas par où commencer.

Est ce que quelqu'un pourrait me donner un plan des étapes que je dois suivre ?

Merci beaucoup pour votre aide.
A voir également:

19 réponses

Ciola Messages postés 11 Date d'inscription jeudi 26 février 2009 Statut Membre Dernière intervention 21 septembre 2009 4
21 sept. 2009 à 16:29
Pour information, c'est quand même un projet que je dois présenter lors de l'oral de mon BTS informatique, je suis pas très à l'aise car je me suis mise à l'informatique pour ce BTS qui lui m'a été plus ou moins imposé (et reprendre des cours après 9 ans dans la vie active c'est pas forcément facile) donc je dois respecter certain critère pour l'examen comme faire une appli en C ou C++.

Merci Nabla's et aux autres pour les idées données, je vais regarder et je reviens vers vous en cas de besoin
4
mamiemando Messages postés 33282 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 24 septembre 2024 7 786
22 sept. 2009 à 02:26
messages <3>, <4>, <5>
Je sais pas si c'est l'heure ou si je perds patience, mais ça fait deux fois de suite que je tombe sur un fil de discussion C++ ou les réponses n'ont RIEN à voir avec la question posée. On est pas ici pour raconter sa vie ou discuter du sujet c'est dingue ça !

@dna.factory
Alors NON un sudoku n'est pas compliqué à programmer si on sait écrire des boucles for. D'autant plus qu'il n' y a pas le solveur à programmer. Il suffit juste de réfléchir deux minutes avant de se lancer.

Chaque case peut contenir une valeur de 0 à 9 (son domaine). Ce domaine est restreint par les cases du cadran, de la ligne et de la colonne. Je te donne la méthode en pseudo code pour qu'il te reste un peu de pain sur la planche. Le sudoku usuel contient 3x3 cadrans de 3x3 cases chacuns (n=3).

Pour chaque case (i,j) de la grille
  Si le domaine de la case(i,j) est réduit à un élément : le placer
  Sinon : tirer une valeur v au hasard parmi les valeurs encore dans le domaine
  Pour chaque case de la ligne i : supprimer la valeur v du domaine
  Pour chaque case de la colonne j : supprimer la valeur v du domaine
  Pour chaque case du carré n x n contenant (i,j) : supprimer la valeur v du domaine
Fin pour


A mon humble avis, les gens qui disent c'est pas à sa portée s'égarent franchement. La vérification est plutôt plus simple. La seule "difficulté" consiste à associer une case (i,j) avec un cadran (mais bon c'est pas la mort)

#define n 3 // sudoku 3x3 cadrans de 3x3 cases

// Associer chaque case (ligne,colonne) à un index qui identifie un cadran
// (le cadran en haut à geuche a pour 0, celui à sa droite 1 etc...) ce qui donne
// ce mapping pour n = 3 :
// 000111222
// 000111222
// 000111222
// 333444555
// 333444555
// 333444555
// 666777888
// 666777888
// 666777888

// Retourne l'identifiant du cadran contenant la case (ligne, colonne)
unsigned coordonnees2cadran(unsigned ligne,unsigned colonne){
  if (ligne >= n*n) throw;
  if (colonne >= n*n) throw;
  return (ligne/n)*n + colonne/n; // '/' : division euclidienne
}


Pour vérifier une grille :

Vider les domaines associés à chaque ligne
Vider les domaines associés à chaque colonne
Vider les domaines associés à chaque cadran
Pour chaque ligne i
  Pour chaque colonne j
    Ajouter la valeur de la case(i,j) dans le domaine de la ligne(i)
    Ajouter la valeur de la case(i,j) dans le domaine de la colonne(j)
    Ajouter la valeur de la case(i,j) dans le domaine de du cadran contenant (i,j)
  Fin pour
Fin pour

Pour chaque ligne i
  Si le domaine de la ligne(i) ne contient pas les 9 valeurs : retourner faux
Fin pour

Pour chaque colonne j
  Si le domaine de la colonne(j) ne contient pas les 9 valeurs : retourner faux
Fin pour

Pour chaque cadran
  Si le domaine du cadran ne contient pas les 9 valeurs : retourner faux
Fin pour

Retourner vrai


Pour générer une grille à remplir par l'utilisateur tu génères simplement une solution et tu vires des valeurs. Par exemple 5 ou 6 valeurs par cadran. Dans certains cas peut être que la grille aura plusieurs solution mais ça n'a pas d'importance, puisqu'au final la fonction de vérification ne contrôle pas si la grille de départ et la solution proposée concordent, elle regarde juste si la grille proposée est valide.

Maintenant il ne te reste plus qu'à coder tout ça ;-) Si tu es motivée tu peux facilement voir que le pseudo code que je te propose marche pour des sudokus n x n cadrans de n x n éléments (avec n >=1 et pas seulement n = 3).

En terme d'implémentation tu peux par exemple utiliser des structures dans ce genre :

#include <vector>

typedef std::vector<bool> domaine_t;

struct case_t{
  domaine_t domaine; // pour générer la grille ou pour le solveur
  unsigned valeur;
};

typedef std::vector<std::vector<case_t> > grille_t;

Ce qui aurait été dur, ça aurait été :

1) de devoir coder un solveur. Mais en fait ça se fait très facilement avec un modèle CSP (voir cours de recherche opérationnelle pour les amateurs) qui comme la méthode que je viens de proposé est basée sur des réductions de domaines. Il est assez simple de vérifier si la grille a une ou plusieurs solution (avec un arbre de branchement).

2) de devoir générer des grilles à solution unique (mais une fois le solveur codé, il suffit de virer des valeurs et de n'autoriser leur suppression que si la solution reste unique).

Bonne chance
3
zoleme Messages postés 4 Date d'inscription samedi 26 septembre 2009 Statut Membre Dernière intervention 2 octobre 2009 1
26 sept. 2009 à 22:13
moi je suis daccord avec Niel il faut aussi penser a la capacité du candidat en question
pour ne pas dire trop lui faire peur j'espére que vous comprenez
1
Neliel Messages postés 6146 Date d'inscription jeudi 9 juillet 2009 Statut Contributeur Dernière intervention 20 mars 2017 1 690
21 sept. 2009 à 15:57
Un sudoku est assez complexe à programmer... surtout si tu n'est pas à l'aise avec la programmation...
Tu as choisi ton projet librement où était-il imposé ?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Nabla's Messages postés 18203 Date d'inscription mercredi 4 juin 2008 Statut Contributeur Dernière intervention 28 avril 2014 3 193
21 sept. 2009 à 15:59
poru la création de grilles aléatoires, je ne sais pas.

en revanche, pour l'architecture, deja tu fais une matrice (tableau a 2 dimentions) de la taille d'une grille (peut etre variable si on utilise aussi les lettres).
fais un algo de vérification de chaque ligne, de chaque colone, et de chaque carré, pour voir si chaque chiffre est bien utilisé 1 fois, et seulement une fois

Fais bien attention à ce que les valeurs générées apr le prorgamme ne soit pas modifiables par l'utilisateur sur sa grille
0
Neliel Messages postés 6146 Date d'inscription jeudi 9 juillet 2009 Statut Contributeur Dernière intervention 20 mars 2017 1 690
21 sept. 2009 à 16:15
... c'est un peu soft comme présentation ...

Perso, j'avais choisi "le jeu de la vie", ce n'est pas vraiment un jeu mais plutôt une simulation assez sympas (et simpliste) sur la bioculture. C'est plus complexe à programmer que "trouver le chiffre" mais largement plus simple que le sudoku.
Tapes jeu de la vie dans wikipedia, tu auras le modèle de la simulation... perso, je me suis bien amusé à le faire.
0
dna.factory Messages postés 25243 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 23 septembre 2024 1 612
21 sept. 2009 à 16:23
effectivement le jeu de la vie est pas mal...
y'a aussi la fourmi de langton qu'est pas mal (et facile)
https://fr.wikipedia.org/wiki/Fourmi_de_Langton

(mais de mon temps, y'avait pas besoin de ça, suffissait juste de demander à etre pris...)
0
Neliel Messages postés 6146 Date d'inscription jeudi 9 juillet 2009 Statut Contributeur Dernière intervention 20 mars 2017 1 690
22 sept. 2009 à 08:29
[Mode ironique activé] Oh oui, ça a l'air très simple pour quelqu'un n'ayant pas ou peu eu de cours en C++... [Mode ironique désactivé]

Je ne vois pas en quoi nos réponse sont Hors Sujet, nous lui avons proposé (si possibilité il y a) des projets plus simple pour son niveau. Un Sudoku reste de difficulté assez élevé et tout le monde n'est pas un as de la programmation... faudrait aussi que tu me dise où je raconte ma vie...
Bref, tu peux te garder tes remarques inutiles (début de ton message) et te contenter de l'aider... comme nous.

A+
0
dna.factory Messages postés 25243 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 23 septembre 2024 1 612
22 sept. 2009 à 09:01
pour la vérification de la grille, je suis d'accord, c'est facile, mais ce n'est pas là l'interet du projet

pour la création de la grille, je ne suis pas d'accord par contre, ou alors tu t'es mal exprimé.
ta méthode permet de commencer une grille, mais bien souvent ne permettra pas de la terminer.
car cela revient à résoudre un sudoku en mettant les valeurs au hasard parmi celles disponibles...
ça marche au début, jusqu'a un certain point.
ou alors, ta méthode consiste à essayer de faire des grilles de manière aléatoire jusqu'a avoir la chance d'en trouver une bonne, ce qui peut prendre pas mal de temps...

quant à génerer une grille en virant des valeurs au hasard...
non seulement on risque de génerer des grilles à solutions multiples, mais on risque aussi de génerer des grilles impossibles à résoudre (ou tout du moins, très très difficiles)

je ne suis pas d'accord non plus quand tu dis qu'on ne réponds pas à la question
une partie importante de la question est : "que je suis vraiement pas douée"
j'ai fait un bts informatique de gestion (y'a 10 ans), donc je connais le niveau
j'avoue, en relisant, j'ai mal compris la question, je pensais qu'elle aller entrer en BTS, et non passer l'examen, ce qui explique ma premiere réponse.
effectivement pour un examen final, le 'trouver le nombre' est trop simpliste (je le programmais sur ma calculatrice en seconde) mais, déja pour elle, ça lui permet de se faire une idée de son niveau, si ce qu'on lui propose lui semble facile, alors, effectivement, elle peut essayer de plancher sur autre chose de plus compliqué.
0
mamiemando Messages postés 33282 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 24 septembre 2024 7 786
22 sept. 2009 à 10:37
ou alors, ta méthode consiste à essayer de faire des grilles de manière aléatoire jusqu'a avoir la chance d'en trouver une bonne, ce qui peut prendre pas mal de temps...

Absolument pas. Ce n'est ni long ni faux. On choisit juste une valeur au hasard parmi celle encore disponible pour la case. On restreint l'ensemble des valeurs disponibles pour que les cases contraintes par la valeur qu'on installe reçoivent lors des itérations suivantes une valeur cohérente avec la valeur de la grille.

Par exemple pour un sudoku avec n = 3 j'ai initialement 9 valeurs disponibles pour chaque case. Je tire une valeur entre 0 et 8 (ce qui fait bien 9 valeurs). Supposons que je tire la valeur 6. J'avance 6fois dans {0,1,2,3,4,5,6,7,8,9}, ce qui correspond à la valeur 6 que j'installe dans la case. Du coup je vire dans le domaine des cases du cadran supérieur gauche, de la ligne supérieure, et de la colonne de gauche la valeur 6.

Ensuite je passe à la case immédiatement à droite. Le 6 n'est plus disponible (il reste donc 8 valeurs disponibles). Je tire une valeur entre 0 et 7 (ce qui correspond bien à un échantillon de 8 valeurs). Supposons que je tire la valeur 6. J'avance de 6 crans dans {0,1,2,3,4,5,7,8,9} pour choisir ma valeur, c'est à dire la valeur 7. Puis je retire cette valeur dans les cases du cadran, de la ligne et de la colonne correspondante. Et ainsi de suite.

Conclusion : on parcours une case une et une seule fois, pour chacune d'elle on fait un tirage aléatoire qui donne systématiquement une valeur admissible (et quand le domaine est réduit à un élément, on n'a même pas besoin de faire le tirage aléatoire, on sait que c'est la seule valeur qu'on peut installer dans la case). Bref c'est un algo polynomial, ça dépote...

quant à génerer une grille en virant des valeurs au hasard...
non seulement on risque de génerer des grilles à solutions multiples, mais on risque aussi de génerer des grilles impossibles à résoudre (ou tout du moins, très très difficiles)


Non puisque tu pars d'une solution admissible et tu vires certaines cases. Il y a donc au moins cette solution. Quand à avoir des solutions multiples j'ai déjà expliqué comment faire pour éviter d'avoir des solutions multiples, mais si tu ne vires pas trop de valeurs, la grille sera suffisamment contrainte pour n'admettre qu'une (ou peu) de solution. De toute façon même s'il y a plusieurs solution ça n'a aucune importance puisque la méthode de vérification ne compare pas la solution qui a permis de générer la grille avec la solution proposée par le joueur.

je ne suis pas d'accord non plus quand tu dis [...]

Ben là le programme tient en 100 lignes et j'ai déjà donné la structure du code. Comme tu le vois c'est juste quelques boucle for, ce qui doit être l'une des premières choses qu'on apprend en algorithmique. La seule difficulté du problème, c'était réfléchir à l'algo et là on lui a donné. Et tu as bien vu qu'il n'y avait rien de miraculeux.

De plus si on lui dit le sujet c'est générer un sudoku, donc pourquoi s'égarer à parler d'autres jeux ? Le but du forum, c'est de répondre à un problème, pas de contester l'énoncé, non ?

Bonne continuation
0
dna.factory Messages postés 25243 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 23 septembre 2024 1 612
22 sept. 2009 à 12:56
sois je n'ai rien compris à ton algo, soit je persiste, IL NE MARCHE PAS.
exemple

ligne 1, case 1 : le 1 est choisi, retiré des possibilités
ligne 1, case 2 : le 2 est choisi, retiré des possibilités
ligne 1, case 3 : le 3 est choisi, retiré des possibilités
[...]
ligne 1, case 9 : le 9 est chois (oui, c'est un coup de chance, mais c'est pour l'exemple)

la ligne 1 est donc la suivante : [1|2|3][4|5|6][7|8|9]
jusque là, on est d'accord sur le fonctionnement ?

on passe à la ligne 2, premier triplet :
case 1 : le 1, le 2 et le 3 sont indisponible, le 4 est choisi
case 2 : le 1, le 2, le 3 et le 4 sont indisponible, le 5 est choisi
case 3 : les chiffres de 1 à 5 sont indispo le 6 est choisi

ligne 2, deuxième triplet :
case 4 : le 4, 5 et 6 sont indispo, le 1 est choisi
case 5 : le 1, 4, 5 et 6 sont indispo, le 2 est choisi
case 6 : le 1, 2, 4, 5 et 6 sont indispo, le 3 est choisi

on a donc jusque là :
[1|2|3][4|5|6][7|8|9]
[4|5|6][1|2|3]

j'ai bien suivi ton algo simple ?
mes tirages ne sont pas aléatoire, c'est vrai, mais ça ne change rien, c'est juste pour que ce soit plus visible, des tirages aléatoires peuvent donner le même genre de résultat

ligne 2, troisième triplet
première case, le 1, le 2, le 3, le 4, le 5, le 6, le 7, le 8 et le 9 sont indispo...
boucle infinie ?
0
mamiemando Messages postés 33282 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 24 septembre 2024 7 786 > dna.factory Messages postés 25243 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 23 septembre 2024
25 sept. 2009 à 00:57
Effectivement tu n'as pas tout compris mais ce n'est pas grave, j'ai pas dû être assez précise

Je la refais.

Exemple :
Itération 1 : Toutes les valeurs sont disponibles. J'en tire une au hasard parmi {1...9} mettons que ce soit 8. Je réduis les domaines en conséquence (dans le cadran, sur la colonne, et sur la ligne). En outre 8 est viré du domaine de la case immédiatement à droite, que je vais traiter à l'itération 2. La grille contient :
8xx|xxx|xxx

Itération 2 : Toutes les valeurs sont disponibles sauf 8. J'en dire une au hasard (par exemple 5). Ma grille contient alors 85x|xxx|xxx

Etc...

Alors maintenant comment faire pour tirer immédiatement une valeur aléatoire du premier coup. Supposons que mon domaine soit {2,4,6,7}, soit 4 valeurs. Je tire une valeur entre 0 et 3 (3 étant la taille du domaine - 1). Si j'ai tiré la valeur :
- 0 je prends la valeur 2 car elle en position 0/3
- 1 je prends la valeur 4 car elle en position 1/3
- 2 je prends la valeur 6 car elle en position 2/3
- 3 je prends la valeur 6 car elle en position 3/3

Il n'y a donc qu'un seul tirage aléatoire (pas de risque de lenteur dû à une succession de tirages aléatoires malheureux). Ca se code par exemple comme ca :

#include <set>

typedef std::set<unsigned> domaine_t;

unsigned extract_random_value(domaine_t & d)
{
  unsigned i, rnd, r;

  // Si le domaine est réduit à 0 élément c'est qu'il y a un bug dans le générateur de grille

  if (d.size() == 0) throw;
  
  // Si le domaine est réduit à 1 élément, on peut optimiser avec cette instruction
  
  if (d.size() == 1) return *d.begin();

  // Le domaine à plusieurs éléments
  // randint(i,j) étant une fonction que tu codes
  // qui tire une valeur aléatoire entre i et j

  rnd = randint(0,d.size()-1);
  domaine_t::const_iterator
    sit (d.begin()),
    send(d.end());
  for(i=0;sit!=send && i <rnd;++sit, ++i);
  r = *sit;

  // Je vire cette valeur du domaine et je la retourne.
  // Il faut ensuite que je vire la valeur r des cases situés
  // sur la même ligne/colonne ou dans le même cadran
  // que la case dont le domaine est d.

  d.erase(sit);
  return r;
}

Comme tu le vois la grille est vraiment aléatoire et il n'y a pas de boucle infinie.

Est-ce que tu es convaincu ?
0
dna.factory Messages postés 25243 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 23 septembre 2024 1 612 > mamiemando Messages postés 33282 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 24 septembre 2024
25 sept. 2009 à 08:35
toujours pas...
manifestement, l'un de nous refuse de comprendre l'autre....
et dans la mesure ou j'estime m'y connaitre en prog (BTS info gestion développeur, +10 ans expérience dans l'informatique), même si c'est moi qui ne te comprends pas, c'est pas grave, car ça veut dire que contrairement à ce que tu prétends, ce que tu dis n'est pas clair, et donc pas accessible à un débutant.
ce n'est pas un générateur que tu code là, c'est la première partie du solveur. (résolution quand une case est possible)
si tu veux te rendre compte du fonctionnement de ton programme, prends une grille de sudoku au hasard, niveau moyen au moins (t'en as maintenant dans tous les journeaux)
tu regarde la premiere case vide dans le sens de la lecture, tu regardes les valeurs dispo, et tu affectes une valeur au hasard parmi les cases dispo, et tu continue
je peux te parier qu'a 90% tu seras bloquée avant la fin.
alors effectivement, ton 'throw' te permettra d'éviter la boucle infinie, mais c'est pas pour ça que le programme marchera...

0
Neliel Messages postés 6146 Date d'inscription jeudi 9 juillet 2009 Statut Contributeur Dernière intervention 20 mars 2017 1 690 > dna.factory Messages postés 25243 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 23 septembre 2024
25 sept. 2009 à 08:42
Tout comme dna.factory, je n'ai pas compris ton code et pourtant j'ai deux ans de BTS Electronique (où j'ai commencé à apprendre le C), deux ans de BTS IRIS (deux ans de programmations en C et C++), plus une année de licence en génie logiciel (Java)...
Donc, comme le dis dna.factory, un débutant n'a aucune chance de comprendre ton source... d'autant qu'il ne fonctionne pas (du moins pas à tous les coups).
0
dna.factory Messages postés 25243 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 23 septembre 2024 1 612 > Neliel Messages postés 6146 Date d'inscription jeudi 9 juillet 2009 Statut Contributeur Dernière intervention 20 mars 2017
25 sept. 2009 à 08:51
au passage, quand tu donnes un code, je te conseille de donner l'algo, c'est compréhensible par tout le monde, et généralement plus clair.
0
Neliel Messages postés 6146 Date d'inscription jeudi 9 juillet 2009 Statut Contributeur Dernière intervention 20 mars 2017 1 690
22 sept. 2009 à 10:52
Rien n'indique que le sujet était imposé: elle dit bien "... j'ai choisi ...". L'idéal est quand même de prendre un sujet compatible avec ses capacités... Il est quand même préférable qu'à la fin lors de la soutenance, le programme fonctionne. Je dit ça dans son intérêt et à aucun moment je n'étais hors sujet...
J'ai vu trop de personne lors de mes études qui ont choisis un projet trop complexe pour eux et qui se sont rétamés à la soutenance!
Le Sudoku te semble peut-être facile à réaliser mais ce n'est certainement pas le cas de tout le monde! Si elle n'est pas sur d'elle, autant, comme le dit dna.factory qu'elle expériente ce qu'elle sait faire sur un projet plus simple...
0
Nabla's Messages postés 18203 Date d'inscription mercredi 4 juin 2008 Statut Contributeur Dernière intervention 28 avril 2014 3 193
22 sept. 2009 à 11:00
un forum de développeurs de sudoku: http://www.setbb.com/phpbb/?mforum=sudoku
0
Perso ce fut l'un de mes projet de première année : Programmer un résolveur de sudoku en C en deux jours.

C'est pas "si" compliqué, il faut bien savoir jouer au sudoku de base en fait pour que ton programme ai de bon algos ...

Perso je me promenais avec un tableau avec 3dimensions pour stocket toutes mes valeurs
0
Nabla's Messages postés 18203 Date d'inscription mercredi 4 juin 2008 Statut Contributeur Dernière intervention 28 avril 2014 3 193
24 sept. 2009 à 16:41
le solutioonneur de sudoku est pas trop dur à coder, et en effet, un tableau tridimentionnel s'ympose, (la 3° dimention pour stoquer les valeurs non éliminés je pense?)
mais la création de la grille est ce qui me semble le plus dur dans la création de son programme
0
Romrom44 > Nabla's Messages postés 18203 Date d'inscription mercredi 4 juin 2008 Statut Contributeur Dernière intervention 28 avril 2014
24 sept. 2009 à 16:46
Exactement pour le tridimensionnel.

C'est vrai que j'avais pas forcement réfléchis à la partie "générateur" de sudoku.

Au pire tu peux partir dans une optique ou tu prend un fichier contenant plusieurs grilles déja résolue, tu sélectionne une grille au hasard, puis dans cette grille tu révèle certaines cases aléatoirement et hop tu envoi cette grille en partie dévoilée :p

M'enfin c'est un peu tricher
0
Nabla's Messages postés 18203 Date d'inscription mercredi 4 juin 2008 Statut Contributeur Dernière intervention 28 avril 2014 3 193 > Romrom44
24 sept. 2009 à 16:53
c'est tricheur, et tu sais pas si tu vas livrer une grille qui sera résolvable, si ca se trouve il y aura plusieurs possibilitées correctes, et tu connaitra pas le niveau de la grille non plus. Il faut faire un algo de controle
0
Romrom44 > Nabla's Messages postés 18203 Date d'inscription mercredi 4 juin 2008 Statut Contributeur Dernière intervention 28 avril 2014
24 sept. 2009 à 16:55
Hum, pas faux non plus

J'y avais pas pensé

Moui un générateur de sudoku ça à l'air assez périlleux en fait ^^
0
mamiemando Messages postés 33282 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 24 septembre 2024 7 786
25 sept. 2009 à 22:22
Alors voici l'issue de la bataille...
#include <iostream>
#include <vector>
#include <set>
#include <cstdlib>
#include <cassert>

#define N     3
#define N2    N*N

typedef std::set<unsigned> domaine_t;

unsigned randint(unsigned max){
 return (unsigned) (((double) rand()*(max+1))/RAND_MAX);
}

struct case_t{
	domaine_t domaine;
	unsigned  valeur;

	case_t():
		valeur(0)
	{
		for(unsigned i=1;i<N2+1;++i) domaine.insert(i);
	}

	void supprimer(unsigned val){
		domaine_t::iterator fit = domaine.find(val);
		if(fit != domaine.end()) domaine.erase(fit);
	}
};

struct grille_t{
	std::vector<std::vector<case_t> > data;

	grille_t(){
		for(unsigned i=0;i<N2;++i){
			data.push_back(std::vector<case_t>(N2,case_t()));
		}
	}

	void corriger(unsigned i,unsigned j,unsigned val){
		assert(i < N2);
		assert(j < N2);

		// Virer val de la ligne i et de la colonne j
		for(unsigned k=0;k<N2;++k){
			data[i][k].supprimer(val);
			data[k][j].supprimer(val);
		}

		// Virer val du cadran dont la case supérieure gauche
		// est (i0,j0)
		unsigned i0 = i / N2;
		unsigned j0 = j / N2;
		for(unsigned i1=0; i1<N; ++i1){
			for(unsigned j1=0; j1<N; ++j1){
				data[i0+i1][j0+j1].supprimer(val);
			}
		}
	}

	void generer(){
		unsigned val, k, rnd;
		for(unsigned i=0;i<N2;++i){
			for(unsigned j=0;j<N2;++j){
				const domaine_t & d = data[i][j].domaine;
				rnd = randint(d.size()-1);
				
				// Tirer la valeur de la case (i,j)
				// (la rnd-ième valeur du domaine)
				domaine_t::const_iterator
					sit (d.begin()),
					send(d.end());
				for(k=0;sit!=send && k < rnd;++sit, ++k);
				val = *sit;
				data[i][j].valeur = val;
				
				// Corriger les domaines
				corriger(i,j,val);
			}
		}
	}
};

std::ostream & operator << (std::ostream & out,const grille_t & g){
	for(unsigned i = 0; i < N2; ++i){
		if(i%N == 0){
			for(unsigned j = 0; j < N2 + N; ++j) out << '-';
			out << std::endl;
		}
		for(unsigned j = 0; j < N2; ++j){
			if (j%N == 0) out << '|';
			out << g.data[i][j].valeur;
		}
		out << std::endl;
	}
	return out;
}

int main(){
//	for(unsigned k=0;k<20;++k) std::cout << randint(9) << std::endl;
	grille_t grille;
	grille.generer();
	std::cout << grille << std::endl;
	return 0;
}

Comme vous pouvez le constater j'ai fait exactement l'algo que je vous avais annoncé. Vous allez être contents, il y a effectivement un cas auquel je n'avais pas pensé. Mais comme nous avons plein de pros de l'informatique et que le plus gros est fait, je suis sûr que vous apporterez le path qui va bien (bon j'ai pas initialisé la graine du générateur aléatoire je sais).

Voici ce que ça donne :
------------
|847|691|352
|536|478|910
|192|350|476
------------
|283|765|194
|674|932|580
|951|840|237
------------
|725|183|649
|419|207|803
|368|509|721

Les 0 correspondent à des cases qui n'ont pas pu être remplie, typiquement la dernière de la deuxième ligne. En fait c'est dû au fait qu'au moment de remplir les cases du dernier cadran, il n'y a que deux valeurs admissibles (9 et 1) parmi les trois qu'il faudrait mettre (i.e. {1, 5, 9}. N'étant pas mauvaise perdante je reconnais donc humblement m'être craquée sur ce point.

Comment résoudre le problème : il faut maintenir le domaine associé à chaque cadran et s'assurer qu'au moment ou l'on insère une valeur dans la grille on ne tombe pas en pénurie de valeur pour les cases restantes ce qui, je l'admets, n'est pas forcément ultra trivial. Et ce qui tombe plutôt bien car sinon il aurait suffit de copier ce source pour faire le projet à sa place. J'avoue que j'ai pas le mental d'y réfléchir trop ce soir plus avant, mais c'est déjà une piste.

Par rapport à l'histoire "ce que tu évoques est un solveur" : oui ça ressemble et on n'a pas vraiment le choix, mais si tu trouves une autre méthode, n'hésite pas à nous en faire part.

Par rapport à "écris le pseudo code" c'était déjà fait dans mon premier message.

Par rapport à vos messages : je suis contente de voir l'enthousiasme que vous mettez à défendre votre point de vue et votre franchise. Vraiment. Maintenant je pense que le but c'est de faire avancer la résolution du problème, et j'attends de votre part des messages plus constructifs et qui font avancer la résolution du problème (ça ne sert à rien de flooder un fil de discussion sur un débat, les messages privés sont faits pour ça). En ce qui me concerne c'est ce que j'ai essayé de faire, j'attends votre contribution, surtout que de ce que j'ai cru comprendre vous êtes fort en info. Bref, impressionnez-moi ;-)

Bonne continuation.
0
dna.factory Messages postés 25243 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 23 septembre 2024 1 612
26 sept. 2009 à 09:19
nanananère...
comment ça, pas constructif ?
pour ma part quand je pense sudoku je pense au tableaux croisés dynamiques d'excel
en gros faut pas chercher à remplir case par case, faut définir chaque case en fonction de toute les autres
et non, je n'ai pas la moindre idée d'approcher cet algo pour le moment, et pas vraiment le temps (je n'ai plus de temps de transport en commun pour me concentrer à ces bêtises, et le boulot est assez intense, même si j'ai 5 minutes de temps en temps pour trainer ici)
le fait est qu'on est en dehors du niveau du BTS, et donc qu'on répond bien à la question, laisse tomber (car même si on lui fourni un code, si elle ne comprends pas la démarche, elle se fera allumer par les examinateurs)
0
Neliel Messages postés 6146 Date d'inscription jeudi 9 juillet 2009 Statut Contributeur Dernière intervention 20 mars 2017 1 690
25 sept. 2009 à 22:34
J'avais tenté d'en faire un il y a quelques temps (dans ma période "folie") et je me suis bien cassé les dents dessus bref je ne retenterai pas (rien que d'y penser, j'ai mal au crâne)...
Le truc du "O" est justement le défaut que dna.factory avait détecté... maintenant tu cerne plus la difficulté de réaliser un tel programme.
0
mamiemando Messages postés 33282 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 24 septembre 2024 7 786
26 sept. 2009 à 20:18
1) Ce n'est absolument pas ce qu'avait annoncé dna.factory, il n'avait même pas compris que l'algo générait bien une grille aléatoire. Je te renvoie à ses messages. A aucun moment il n'a soulevé le problème de l'algo que j'ai proposé. En plus si tu as suivi la discussion tu verras que tout n'est pas à jeter dans ce que j'ai proposé. Au contraire je lui ai même montré qu'effectivement, pour générer une grille, on avait presque l'équivalent d'un solveur.

2) Il n'a pas proposé la moindre approche constructive pour l'aider à résoudre son problème. Il a juste fait son papa avec des "t'y arriveras pas, moi de toute façon je suis le plus mouhaha". J'attends toujours devoir le pro en action (et je dis ça sincèrement, parce que les tableaux croisés dynamique d'excel dans un programme c/c++ ça me fait doucement rigoler).

3) Je n'ai rien à prouver, ni à rougir de quoi que ce soit. Je reconnais que le sujet est plus difficile que ce que j'avais soupçonné au départ (voir message précédent). Ca ne me pose aucun problème de reconnaître que je me suis trompée. Au moins j'ai tenté de répondre à la question au lieu de faire mon papa et d'alimenter la discussion de message qui ne servent à rien. C'est au final la seule chose que je lui ai reproché. Honnêtement qu'il ait son BTS en informatique qui en a quelque chose à taper ? S'il veut raconter sa vie il y a des forums sur CCM pour ça.

Plutôt que de polluer ce fil en discussion puériles et inintéressantes, je vous invite si vous le souhaiter à continuer le débat en messages privés, je serai enchantée d'y répondre.

Sur ce, cordialement, bonne soirée.
0
mamiemando Messages postés 33282 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 24 septembre 2024 7 786
27 sept. 2009 à 18:37
J'ai bien compris :-)
0
Neliel Messages postés 6146 Date d'inscription jeudi 9 juillet 2009 Statut Contributeur Dernière intervention 20 mars 2017 1 690
27 sept. 2009 à 19:03
Cool alors, on est sur la même longueur d'onde... peu importe que tu trouve ça facile ou pas, l'important si c'est faisable pour elle.
0
dna.factory Messages postés 25243 Date d'inscription mercredi 18 avril 2007 Statut Modérateur Dernière intervention 23 septembre 2024 1 612
21 sept. 2009 à 16:11
je vais faire le briseur de reves...
laisse tomber le sudoku, t'as pas le niveau...
c'est plus du niveau de l'examen de fin de bts.

si tu veux faire un programme de jeu, commence déja par 'trouver le chiffre auquel je pense' (avec plus grand, moins grand)
c'est vraiment la base de la programmation, mais ça te permet au moins d'avancer doucement.
-1