Pièce jointe « sudoku.c »
Téléchargement 1 #include "ez-draw.h"
2 #define TAILLE_CASE 36
3 #define HAUT_TITRE 25
4 #define HAUT_LEGENDE 10
5
6 enum {false,true};
7 typedef unsigned char Boolean;
8 // les pavés sont numérotés de 0 à 8 ainsi que les lignes et les colonnes.
9 // Pave[i][j] vrai ssi j est présent dans le pavé n°i.
10 // ligne[i][j] vrai ssi j est présent dans la ligne n° i.
11 // col[i][j] vrai ssi j est présent dans la colonne n° i.
12 Boolean pave[9][10], ligne[9][10], col[9][10];
13
14 // sol indique qu'une solution a été trouvée, on quitte les appels imbriqués de la procédure parcours sans
15 // "défaire" ce qui a été fait lors de la descente. Le tableau grille est ainsi préservé.
16 Boolean sol;
17
18 int enonce[9][9]={
19 {7,9,0,0,4,0,0,0,0},
20 {0,0,4,0,1,0,8,7,0},
21 {0,0,0,0,0,2,0,6,0},
22 {0,5,6,0,0,1,0,0,3},
23 {0,0,0,0,5,0,0,0,0},
24 {3,0,0,8,0,0,7,1,0},
25 {0,8,0,2,0,0,0,0,0},
26 {0,3,5,0,8,0,1,0,0},
27 {0,0,0,0,6,0,0,5,8}
28 };;
29 int grille[9][9];
30
31 enum {MODE_SOL,MODE_JEU};
32 int mode=MODE_JEU;
33
34 // i_clic et j_clic indique les indices ligne et colonne de la case où l'on a cliqué
35 int i_clic=-1, j_clic=-1;
36
37 Window win,win2=None;;
38
39 // possible renvoie vrai ssi on peut placer k dans la case de coordonnées (i,j)
40 Boolean possible (int i,int j,int k)
41 {
42 int p;
43 p=3*(j/3)+i/3;
44 return !pave[p][k]&&!ligne[i][k]&&!col[j][k];
45 }
46
47
48 // L'énoncé est rentré en donnant la suite des valeurs lors de la
49 //déclaration. Cette procédure doit vérifier qu'il n'y a pas de conflit et
50 //mettre à jour les trois tableaux de booléens pour traduire les contraintes.
51 void verifie_enonce()
52 {
53 int i,j,p,k;
54 for (i=0;i<9;i++)
55 for(j=0;j<9;j++)
56 if (enonce[i][j]!=0)
57 {
58 k=enonce[i][j];
59 p=3*(j/3)+i/3;
60 if(possible(i,j,k))
61 {
62 pave[p][k]=true;
63 ligne[i][k]=true;
64 col[j][k]=true;
65 }
66 else
67 {
68 printf("Erreur de remplissage \n");
69 exit(0);
70 }
71 }
72 }
73
74 void initialisations()
75 {
76 int i,j;
77 for (i=0;i<9;i++)
78 for(j=1;j<=9;j++)
79 {
80 pave[i][j]=false;
81 ligne[i][j]=false;
82 col[i][j]=false;
83 grille[i][j-1]=enonce[i][j-1];
84 }
85 verifie_enonce();
86 }
87
88 void dessine_grille(Window win)
89 {
90 int a,b,c,d,i,j,k,p;
91 a=HAUT_TITRE;
92 b=TAILLE_CASE/2;
93 c=TAILLE_CASE;
94 d=HAUT_LEGENDE;
95 /* Affiche le titre */
96 ez_set_color(ez_magenta);
97 ez_set_nfont(3);
98 ez_draw_text(win,EZ_MC,c*5,a-5,"Sudoku");
99
100 /*Dessine la grille*/
101 for(i=0;i<=9;i++)
102 {
103 ez_set_color(i%3==0? ez_blue:ez_grey);
104 ez_draw_line(win,b+i*c,a+b,b+i*c,a+b+9*c);
105 ez_draw_line(win,b,a+b+i*c,b+9*c,a+b+i*c);
106 }
107
108 /* Affiche legende en bas */
109 ez_set_color (ez_black); ez_set_nfont (0);
110 ez_draw_text (win, EZ_BL, b, a+c*10+d-4, "Tapez 'h' pour voir l'aide");
111 ez_draw_text (win, EZ_BR, b+9*c, a+c*10+d-4,
112 mode == MODE_JEU ? "mode jeu" : "mode solution");
113
114 /* Dessine case cliquée */
115 if (i_clic !=-1 && j_clic!=-1)
116 {
117 ez_set_color (ez_magenta);
118 i = i_clic;
119 j = j_clic;
120 ez_draw_rectangle (win, b+j*c+1, a+b+i*c+1, b+j*c+c-1, a+b+i*c+c-1);
121 }
122
123 /*Affiche les chiffres*/
124 for(i=0;i<9;i++)
125 for(j=0;j<9;j++)
126 {
127 ez_set_nfont(3);
128 if (enonce[i][j] != 0)
129 {/* Enonce du jeu */
130 ez_set_color (ez_blue);
131 ez_draw_text (win, EZ_MC, b+j*c+b, a+b+i*c+b, "%d", enonce[i][j]);
132
133 } else if ( grille[i][j] != 0)
134 { /* Cases jouees */
135 if ( i_clic==i && j_clic==j)// case cliquée
136 if( grille[i][j]<0) // un nouveau chiffre vient d'être saisi en (i_clic,j_clic)
137 if(!possible (i_clic,j_clic, -grille[i][j]))
138 { // On ne peut le placer en (i_clic, j_clic)
139 ez_set_color (ez_red);
140 ez_draw_text (win, EZ_MC, b+j*c+b, a+b+i*c+b, "%s","!" );
141 grille[i][j]=0;
142 }
143 else
144 { // on le place en (i_clic,j_clic)
145 grille[i][j]=-grille[i][j];
146 ez_set_color (ez_black);
147 ez_draw_text (win, EZ_MC, b+j*c+b, a+b+i*c+b, "%d", grille[i][j]);
148 p=3*(j/3)+i/3;
149 k=grille[i][j];
150 pave[p][k]=true;
151 ligne[i][k]=true;
152 col[j][k]=true;
153 }
154 else { // on affiche le chiffre qui se trouve dans la case cliquée
155 ez_set_color (ez_black);
156 ez_draw_text (win, EZ_MC, b+j*c+b, a+b+i*c+b, "%d", grille[i][j]);
157 }
158 else {// case non cliquée, on affiche le chiffre
159 ez_set_color (ez_black);
160 ez_draw_text (win, EZ_MC, b+j*c+b, a+b+i*c+b, "%d", grille[i][j]);
161 }
162
163 } else if (i_clic==i && j_clic==j )
164 {/* Possibilités pour cette case */
165 ez_set_nfont (0);
166 ez_set_color (ez_black);
167 for (k = 1 ; k <= 9; k++)
168 if (possible (i_clic,j_clic, k))
169 ez_draw_text (win, EZ_MC,
170 b+j*c+b + ((k-1)%3)*11 - 11,
171 a+b+i*c+b + ((k-1)/3)*11 - 11,
172 "%d", k);
173 }
174 }
175
176 }
177
178
179 void parcours(int prof)
180 {
181 int i,j,k,p;
182 if (prof>80)
183 {
184 sol=true;
185 }
186 else
187 {
188 i=prof % 9;
189 j= prof / 9;
190 p=3*(j/3)+i/3;
191 if (grille[i][j]!=0)
192 parcours(prof+1);
193 else
194 for(k=1;k<=9;k++)
195 if (possible(i,j,k))
196 {
197 grille[i][j]=k;
198 col[j][k]=true;
199 ligne[i][k]=true;
200 pave[p][k]=true;
201 parcours(prof+1);
202 if (sol)return;
203 pave[p][k]=false;
204 ligne[i][k]=false;
205 col[j][k]=false;
206 grille[i][j]=0;
207 }
208 }
209 }
210
211
212 void clic_case (int x, int y)
213 {
214 int a = HAUT_TITRE, b = TAILLE_CASE/2, c = TAILLE_CASE;
215 if (x >= b && x < b+9*c && y >= a+b && y < a+b+9*c)
216 {
217 i_clic = (y-a-b) / c;
218 j_clic = (x-b) / c;
219 }
220 else printf ("Erreur interne dans clic_case\n");
221
222 }
223
224 void win2_event (Ez_event *ev) /* Appelé a chaque evenement sur win2 */
225 {
226 ez_set_nfont(1);
227 switch (ev->type) {
228
229 case Expose :
230 ez_set_color (ez_black);
231 ez_draw_text (ev->win, EZ_TL, 10, 10,
232
233 "Pour modifier une case, cliquer dessus, puis tapez\n"
234 "un chiffre entre 1 et 9\n"
235 "\n"
236 "Vous pouvez utiliser les flèches pour vous déplacer.\n"
237 "\n"
238 "v : Pour vider tout. \n"
239 "Suppr : Pour vider une case. \n"
240 "s : Mode solution, pour faire résoudre.\n"
241 "q : Quitter"
242
243 );
244 break;
245
246 case ButtonPress :
247 case KeyPress :
248 case WindowClose :
249 ez_window_destroy (win2); win2 = None;
250 break;
251 }
252 }
253
254 void affecter_clic (Ez_event *ev, int val)
255 {
256 int p,k;
257 if (i_clic==-1|| j_clic==-1 ) return;
258 k=grille[i_clic][j_clic];
259 if(k!=0)
260 {
261 p=3*(j_clic/3)+i_clic/3;
262 pave[p][k]=false;
263 ligne[i_clic][k]=false;
264 col[j_clic][k]=false;
265 }
266 // La valeur négative indique qu'un nouveau chiffre vient d'être introduit (i_clic,j_clic)
267 grille[i_clic][j_clic] = -val;
268 ez_send_expose (ev->win);
269 }
270
271
272 void win1_onKeyPress (Ez_event *ev)
273 {
274 int k,p;
275 switch (ev->key_sym) {
276
277 case XK_s : mode = MODE_SOL ;
278 i_clic=-1;
279 j_clic=-1;
280 initialisations();
281 sol=false;
282 parcours(0);
283 ez_send_expose (ev->win);
284 break;
285
286 case XK_Up : i_clic=(i_clic-1+9)%9; ez_send_expose (ev->win); break;
287 case XK_Down : i_clic=(i_clic+1+9)%9; ez_send_expose (ev->win); break;
288 case XK_Left : j_clic=(j_clic-1+9)%9; ez_send_expose (ev->win); break;
289 case XK_Right : j_clic=(j_clic+1+9)%9; ez_send_expose (ev->win); break;
290
291 case XK_Delete : if (i_clic==-1|| j_clic==-1 ) return;
292 k=grille[i_clic][j_clic];
293 // si le nombre à supprimer existe, on le supprime
294 if(k!=0)
295 {
296 p=3*(j_clic/3)+i_clic/3;
297 pave[p][k]=false;
298 ligne[i_clic][k]=false;
299 col[j_clic][k]=false;
300 }
301 grille[i_clic][j_clic] = 0;
302 ez_send_expose (ev->win);
303 break;
304
305 case XK_v :
306 initialisations();
307 mode=MODE_JEU;
308 ez_send_expose (ev->win); break;
309
310 case XK_q : ez_quit (); break;
311
312 case XK_h :
313 if (win2 == None)
314 win2 = ez_window_create (500, 300, "Aide", win2_event);
315 else { ez_window_destroy (win2); win2 = None; }
316 break;
317
318 default :
319 if (ev->key_string[0] >= '1' && ev->key_string[0] <= '9')
320 affecter_clic (ev, ev->key_string[0] - '0');
321 }
322 }
323
324 void win_event(Ez_event *ev)
325 {
326 switch (ev->type)
327 {
328 case Expose:
329 dessine_grille(ev->win);
330 break;
331 case ButtonPress:
332 clic_case(ev->mx,ev->my);
333 ez_send_expose(ev->win);
334 break;
335 case MotionNotify:
336 break;
337 case ButtonRelease:
338 break;
339 case KeyPress:
340 win1_onKeyPress(ev);
341 break;
342
343 case WindowClose:
344 ez_quit();
345 break;
346 }
347 }
348
349 int main ()
350 {
351 if(ez_init()<0) exit(1);
352
353 initialisations();
354 win=ez_window_create(TAILLE_CASE*10,TAILLE_CASE*10+HAUT_TITRE+HAUT_LEGENDE,"sudoku",win_event);
355
356 ez_auto_quit(0);
357 ez_main_loop();
358 return 0;
359 }
Fichiers joints
Pour vous référer aux pièces jointes d'une page, utilisez attachment:filename, comme indiqué ci-dessous dans la liste de fichiers. N'utilisez pas l'URL du lien [get], car elle peut changer et donc être facilement cassée.Vous n'êtes pas autorisé à joindre un fichier à cette page.