Bonjour à tous,
voilà je suis comme qui dirait un "newbis" en ce qui concerne le langage C et j'essai en ce moment de comprendre comment fonctionne les threads.
J'avais déjà manipuler un peu les threads en Java mais c'est un peu différents.
Pour m’entraîner j'ai décidé de ressortir un vieux sujet que j'avais eu en cours de Java il y a de cela 1 ou 2 ans.
Voilà, j'essai de faire une sorte de simulateur de robots. Dans une grille il y a des robots, des pièges, des sources d’énergies et des obstacles.
Donc je veux faire des threads pour chacun de ces types. Cependant, j'ai un peu de difficultés concernant la synchronisation des threads avec les mutex et les variables de condition que je n'ai vraiment pas compris.
Voici mon code pour l'instant (je n'ai pas encore fais les threads pour les pièges mais si vous pouviez m'expliquer comment faire la synchronisation entre le thread affichage et les threads source ça serait sympa, je pourrais avancer plus rapidement avec un ou des exemples) :
Le début du fichier
Les structures
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 #ifndef _MAIN_C_ #define _MAIN_C_ #include <stdio.h> #include <stdlib.h> #include <time.h> #include <pthread.h> #include <unistd.h> #include <errno.h> #include <pthread.h> #define NB_LIG 10 #define NB_COL 10 #define NB_ROBOTS 5 #define NB_PIEGES 3 #define NB_SOURCES 4 #define NB_OBS 0
Les variables gloabales
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 typedef struct { int fin; int reqATraiter; int noEtape; pthread_mutex_t mutex; pthread_cond_t termine; pthread_cond_t requete; } Affiche; typedef struct { char* type; //type : "robot", "piege", "obstacle" ou "vide" int idContenant; //idContenant : identifiant du robot, de la source ou du piege } Cellule; typedef struct { Cellule grille [NB_LIG][NB_COL]; } Grille ; typedef struct { int x; int y; } Coords; typedef struct { int strategie; int vitesse; int energie; int maxEnergie; int attaque; int defense; int id; Coords empl; // emplacement du robot pthread_mutex_t mutex; pthread_cond_t cond; } Robot; typedef struct { int vitesse; int attaque; int energie; int id; Coords empl; // emplacement du piege pthread_mutex_t mutex; pthread_cond_t cond; } Piege; typedef struct { int vitesse; int soin; int energie; Coords empl; // emplacement de la source d'energie int id; pthread_mutex_t mutex; pthread_cond_t cond; } Source;
Les fonctions d'initialisations
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 //variable globale contenant ma grille de jeu Grille maGrille; Robot mesRobots [NB_ROBOTS]; Piege mesPieges [NB_PIEGES]; Source mesSources [NB_SOURCES]; int nbRobots; int nbSources; int nbPieges; pthread_t mesThreadsRobots [NB_ROBOTS]; pthread_t mesThreadsPieges [NB_PIEGES]; pthread_t mesThreadsSources [NB_SOURCES]; Affiche monThreadAffiche = {1, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER,PTHREAD_COND_INITIALIZER};
Une fonction pour les robots lol
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168 void* initRobot(int idRobot) { // // Pour la strategie : // 1 : Standard // 2 : Suicidaire // 3 : Peureux // Robot monRobot; int statut; if(idRobot == 0) { maGrille.grille[5][5].type = "robot"; maGrille.grille[5][5].idContenant = idRobot; monRobot.empl.x = 5; monRobot.empl.y = 5; } else if(idRobot == 1) { maGrille.grille[5][6].type = "robot"; maGrille.grille[5][6].idContenant = idRobot; monRobot.empl.x = 5; monRobot.empl.y = 6; } else if(idRobot == 2) { maGrille.grille[6][5].type = "robot"; maGrille.grille[6][5].idContenant = idRobot; monRobot.empl.x = 6; monRobot.empl.y = 5; } else if(idRobot == 3) { maGrille.grille[6][6].type = "robot"; maGrille.grille[6][6].idContenant = idRobot; monRobot.empl.x = 6; monRobot.empl.y = 6; } else if(idRobot == 4) { maGrille.grille[9][9].type = "robot"; maGrille.grille[9][9].idContenant = idRobot; monRobot.empl.x = 9; monRobot.empl.y = 9; } else { printf("WHAT THE FUCK \n"); } monRobot.strategie = (int)(rand()%3); monRobot.vitesse = (int)(rand()%5); monRobot.energie = 30; monRobot.maxEnergie = 30; monRobot.attaque = (int)(rand()%5); monRobot.defense = (int)(rand()%5); monRobot.id = idRobot; statut = pthread_mutex_init(&monRobot.mutex, NULL); statut = pthread_cond_init(&monRobot.cond, NULL); mesRobots[idRobot] = monRobot; return NULL; } void* initSource(int idSource) { Source maSource; int statut; if(idSource == 0) { maGrille.grille[4][4].type = "source"; maGrille.grille[4][4].idContenant = idSource; maSource.empl.x = 4; maSource.empl.y = 4; } else if(idSource == 1) { maGrille.grille[4][8].type = "source"; maGrille.grille[4][8].idContenant = idSource; maSource.empl.x = 4; maSource.empl.y = 7; } else if(idSource == 2) { maGrille.grille[9][6].type = "source"; maGrille.grille[9][6].idContenant = idSource; maSource.empl.x = 9; maSource.empl.y = 6; } else if(idSource == 3) { maGrille.grille[7][1].type = "source"; maGrille.grille[7][1].idContenant = idSource; maSource.empl.x = 7; maSource.empl.y = 1; } else { printf("WHAT THE FUCK \n"); } maSource.vitesse = (int)(rand()%5); maSource.energie = 30; maSource.soin = (int)(rand()%5); maSource.id = idSource; statut = pthread_mutex_init(&maSource.mutex, NULL); statut = pthread_cond_init(&maSource.cond, NULL); mesSources[idSource] = maSource; return NULL; } void* initPiege(int idPiege) { // // Pour la strategie : // 1 : Standard // 2 : Suicidaire // 3 : Peureux // Piege monPiege; int statut; maGrille.grille[7][8].type = "piege"; maGrille.grille[7][8].idContenant = idPiege; monPiege.empl.x = 7; monPiege.empl.y = 8; monPiege.vitesse = (int)(rand()%5); monPiege.energie = 30; monPiege.attaque = (int)(rand()%5); monPiege.id = idPiege; statut = pthread_mutex_init(&monPiege.mutex, NULL); statut = pthread_cond_init(&monPiege.cond, NULL); mesPieges[idPiege] = monPiege; return NULL; } void* initObstacles() { srand(time(NULL)); int i; int aleaI, aleaJ; for(i = 0;i<NB_OBS;i++) { aleaI = (int)(rand()%NB_LIG); aleaJ = (int)(rand()%NB_COL); if(strcmp(maGrille.grille[aleaI][aleaJ].type,"vide")==0) maGrille.grille[aleaI][aleaJ].type = "obstacle"; else i--; } return NULL; }
Des fonctions pour faire des actions autour d'une case
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 void* deplacerRobot(int idRobot, int direction) { int coordX, coordY; coordX = mesRobots[idRobot].empl.x; coordY = mesRobots[idRobot].empl.y; //printf("il sagit du robot : %d avec deplacement = %d\n", mesRobots[idRobot].id, direction); if(direction == 0 && coordX !=0) //haut { if(strcmp(maGrille.grille[coordX-1][coordY].type,"vide")==0) { maGrille.grille[coordX-1][coordY].type = "robot"; maGrille.grille[coordX-1][coordY].idContenant = idRobot; maGrille.grille[coordX][coordY].type = "vide"; mesRobots[idRobot].empl.x--; } } else if(direction == 1 && coordY != (NB_COL-1)) //droite { if(strcmp(maGrille.grille[coordX][coordY+1].type,"vide")==0) { maGrille.grille[coordX][coordY+1].type = "robot"; maGrille.grille[coordX][coordY+1].idContenant = idRobot; maGrille.grille[coordX][coordY].type = "vide"; mesRobots[idRobot].empl.y++; } } else if(direction == 2 && coordX != (NB_LIG-1)) //bas { if(strcmp(maGrille.grille[coordX+1][coordY].type,"vide")==0) { maGrille.grille[coordX+1][coordY].type = "robot"; maGrille.grille[coordX+1][coordY].idContenant = idRobot; maGrille.grille[coordX][coordY].type = "vide"; mesRobots[idRobot].empl.x++; } } else if(direction == 3 && coordY != 0) //gauche { if(strcmp(maGrille.grille[coordX][coordY-1].type,"vide")==0) { maGrille.grille[coordX][coordY-1].type = "robot"; maGrille.grille[coordX][coordY-1].idContenant = idRobot; maGrille.grille[coordX][coordY].type = "vide"; mesRobots[idRobot].empl.y--; } } return NULL; }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274 void* powerUpEnHaut(int x, int y) { printf("ENTRE DANS powerUpEnHaut \n"); mesRobots[maGrille.grille[x-1][y].idContenant].energie++ ; mesSources[maGrille.grille[x][y].idContenant].energie-- ; printf("Nouvelle energie de la source : %d \n", mesSources[maGrille.grille[x][y].idContenant].energie); printf("Nouvelle energie du robot : %d => %d \n", mesRobots[maGrille.grille[x-1][y].idContenant].id, mesRobots[maGrille.grille[x-1][y].idContenant].energie); return NULL; } void* powerUpA_Droite(int x, int y) { printf("ENTRE DANS powerUpA_Droite \n"); mesRobots[maGrille.grille[x][y+1].idContenant].energie++ ; mesSources[maGrille.grille[x][y].idContenant].energie-- ; printf("Nouvelle energie de la source : %d \n", mesSources[maGrille.grille[x][y].idContenant].energie); printf("Nouvelle energie du robot : %d \n", mesRobots[maGrille.grille[x][y+1].idContenant].energie); return NULL; } void* powerUpEnBas(int x, int y) { printf("ENTRE DANS powerUpEnBas \n"); mesRobots[maGrille.grille[x+1][y].idContenant].energie++ ; mesSources[maGrille.grille[x][y].idContenant].energie-- ; printf("Nouvelle energie de la source : %d \n", mesSources[maGrille.grille[x][y].idContenant].energie); printf("Nouvelle energie du robot : %d \n", mesRobots[maGrille.grille[x+1][y].idContenant].energie); return NULL; } void* powerUpA_Gauche(int x, int y) { printf("ENTRE DANS powerUpA_Gauche \n"); mesRobots[maGrille.grille[x][y-1].idContenant].energie++ ; mesSources[maGrille.grille[x][y].idContenant].energie-- ; printf("Nouvelle energie de la source : %d \n", mesSources[maGrille.grille[x][y].idContenant].energie); printf("Nouvelle energie du robot : %d \n", mesRobots[maGrille.grille[x][y-1].idContenant].energie); return NULL; } // Cette fonction retourne 1 s'il y a un robot dans la case du haut. Elle renvoie 0 sinon. int robotEnHaut(int x, int y) { if(x != 0) { if(strcmp(maGrille.grille[x-1][y].type,"robot")==0) { return 1; } } return 0; } // Cette fonction retourne 1 s'il y a un robot dans la case de droite. Elle renvoie 0 sinon. int robotA_Droite(int x, int y) { if(y != (NB_COL-1)) { if(strcmp(maGrille.grille[x][y+1].type,"robot")==0) { return 1; } } return 0; } // Cette fonction retourne 1 s'il y a un robot dans la case du bas. Elle renvoie 0 sinon. int robotEnBas(int x, int y) { if(x != (NB_LIG-1)) { if(strcmp(maGrille.grille[x+1][y].type,"robot")==0) { return 1; } } return 0; } // Cette fonction retourne 1 s'il y a un robot dans la case de gauche. Elle renvoie 0 sinon. int robotA_Gauche(int x, int y) { if(y != 0) { if(strcmp(maGrille.grille[x][y-1].type,"robot")==0) { return 1; } } return 0; } int robotAutour(int x, int y) { if((robotEnHaut(x,y) == 1) || (robotA_Droite(x,y) == 1) || (robotEnBas(x,y) == 1) || (robotA_Gauche(x,y) == 1)) { return 1; } return 0; } // Cette fonction retourne 1 s'il y a un piege dans la case du haut. Elle renvoie 0 sinon. int piegeEnHaut(int idRobot) { int x; int y; x = mesRobots[idRobot].empl.x; y = mesRobots[idRobot].empl.y; if((x-1)>=0) { if(strcmp(maGrille.grille[x-1][y].type,"piege")==0) { return 1; } } return 0; } // Cette fonction retourne 1 s'il y a un piege dans la case de droite. Elle renvoie 0 sinon. int piegeA_Droite(int idRobot) { int x; int y; x = mesRobots[idRobot].empl.x; y = mesRobots[idRobot].empl.y; if((y+1)<=NB_COL) { if(strcmp(maGrille.grille[x][y+1].type,"piege")==0) { return 1; } } return 0; } // Cette fonction retourne 1 s'il y a un piege dans la case du bas. Elle renvoie 0 sinon. int piegeEnBas(int idRobot) { int x; int y; x = mesRobots[idRobot].empl.x; y = mesRobots[idRobot].empl.y; if((x+1)<=NB_LIG) { if(strcmp(maGrille.grille[x+1][y].type,"piege")==0) { return 1; } } return 0; } // Cette fonction retourne 1 s'il y a un piege dans la case de gauche. Elle renvoie 0 sinon. int piegeA_Gauche(int idRobot) { int x; int y; x = mesRobots[idRobot].empl.x; y = mesRobots[idRobot].empl.y; if((y-1)>=0) { if(strcmp(maGrille.grille[x][y-1].type,"piege")==0) { return 1; } } return 0; } int piegeAutour(int idRobot) { if((piegeEnHaut(idRobot) == 1) || (piegeA_Droite(idRobot) == 1) || (piegeEnBas(idRobot) == 1) || (piegeA_Gauche(idRobot) == 1)) { return 1; } return 0; } // Cette fonction retourne 1 s'il y a une source dans la case du haut. Elle renvoie 0 sinon. int sourceEnHaut(int idRobot) { int x; int y; x = mesRobots[idRobot].empl.x; y = mesRobots[idRobot].empl.y; if((x-1)>=0) { if(strcmp(maGrille.grille[x-1][y].type,"source")==0) { return 1; } } return 0; } // Cette fonction retourne 1 s'il y a une source dans la case de droite. Elle renvoie 0 sinon. int sourceA_Droite(int idRobot) { int x; int y; x = mesRobots[idRobot].empl.x; y = mesRobots[idRobot].empl.y; if((y+1)<=NB_COL) { if(strcmp(maGrille.grille[x][y+1].type,"source")==0) { return 1; } } return 0; } // Cette fonction retourne 1 s'il y a une source dans la case du bas. Elle renvoie 0 sinon. int sourceEnBas(int idRobot) { int x; int y; x = mesRobots[idRobot].empl.x; y = mesRobots[idRobot].empl.y; if((x+1)<=NB_LIG) { if(strcmp(maGrille.grille[x+1][y].type,"source")==0) { return 1; } } return 0; } // Cette fonction retourne 1 s'il y a une source dans la case de gauche. Elle renvoie 0 sinon. int sourceA_Gauche(int idRobot) { int x; int y; x = mesRobots[idRobot].empl.x; y = mesRobots[idRobot].empl.y; if((y-1)>=0) { if(strcmp(maGrille.grille[x][y-1].type,"source")==0) { return 1; } } return 0; } int sourceAutour(int idRobot) { if((sourceEnHaut(idRobot) == 1) || (sourceA_Droite(idRobot) == 1) || (sourceEnBas(idRobot) == 1) || (sourceA_Gauche(idRobot) == 1)) { return 1; } return 0; }
mon thread affiche
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 void* afficherGrille() { int i, j; int fin = 0; //printf("DEBUT THREAD AFFICHE ... \n"); while (!fin) { for (i = 0; i < 10; i++) { printf("\n"); } for (i = 0; i < NB_LIG ; i++) { for (j = 0; j < (NB_COL * (NB_LIG/2)) + 1; j++) printf("-"); printf("\n"); for (j = 0; j < NB_COL; j++) { printf("|"); if(strcmp(maGrille.grille[i][j].type,"robot")==0) { printf("|R%d|",maGrille.grille[i][j].idContenant); } else if(strcmp(maGrille.grille[i][j].type,"piege")==0) { printf("|P%d|",maGrille.grille[i][j].idContenant); } else if(strcmp(maGrille.grille[i][j].type,"source")==0) { printf("|S%d|",maGrille.grille[i][j].idContenant); } else if(strcmp(maGrille.grille[i][j].type,"obstacle")==0) { printf("#%d#",maGrille.grille[i][j].idContenant); } else { printf(" "); } printf(" "); } printf("|\n"); } for (i = 0; i < (NB_COL * (NB_LIG/2)) + 1; i++) { printf("-"); } printf("\n"); sleep(1); deplacerRobot(0,0); deplacerRobot(1,1); deplacerRobot(2,2); deplacerRobot(3,3); deplacerRobot(4,2); } return NULL; }
Des fonctions qui vont être utiles pour les threads sources
Ma fonction qui représente les threads sources
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 int sourceNonVide(int idSource) { if(mesSources[idSource].energie > mesSources[idSource].soin) return 0; return 1; } void* annihileSource(int idSource) { int thisX, thisY; thisX = mesSources[idSource].empl.x; thisY = mesSources[idSource].empl.y; maGrille.grille[thisX][thisY].type = "vide"; maGrille.grille[thisX][thisY].idContenant = 0; return 0; }
Le main :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 void* threadSources() { //printf("DEBUT THREAD SOURCE... \n"); int idSource; int thisX, thisY; idSource = nbSources++; initSource(idSource); thisX = mesSources[idSource].empl.x; thisY = mesSources[idSource].empl.y; //sleep(2); // on laisse le temps a l'initialisation... while(mesSources[idSource].energie > 0) { // on regarde s'il y a un robot autour if(robotAutour(thisX,thisY) == 1) // il y a au moins un robot... { //printf(" ROBOT AUTOUR... \n"); if(robotEnHaut(thisX,thisY) == 1) // un robot est en haut { printf("il y a un robot en haut \n"); powerUpEnHaut(thisX,thisY); } if((robotA_Droite(thisX,thisY) == 1) && (sourceNonVide(idSource) == 1)) // un robot est a droite et il reste de lenergie { printf("il y a un robot en droite \n"); powerUpA_Droite(thisX,thisY); } if((robotEnBas(thisX,thisY) == 1) && (sourceNonVide(idSource) == 1)) // un robot est en bas et il reste de lenergie { printf("il y a un robot en bas \n"); powerUpEnBas(thisX,thisY); } if((robotA_Gauche(thisX,thisY) == 1) && (sourceNonVide(idSource) == 1)) // un robot est a gauche et il reste de lenergie { printf("il y a un robot en gauche \n"); powerUpA_Gauche(thisX,thisY); } } } // la source ne peut plus suivre, il faut la faire disparaitre annihileSource(idSource); printf("Une source a ete epuisee \n"); return 0; }
Merci d'avance
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 int main(int argc, char *argv[]) { int i, j; int statut; pthread_t threadAff; nbRobots = 0; nbPieges = 0; nbSources = 0; for(i=0 ; i< NB_LIG; i++) for(j=0 ; j< NB_COL; j++) { maGrille.grille[i][j].type = "vide"; // on initialise toutes les cellules Ã* "vide" } for(i = 0;i<NB_ROBOTS;i++) { initRobot(i); } //initObstacles(); //initPiege(0); statut = pthread_create(&threadAff, NULL, afficherGrille, NULL); for(i=0 ; i<NB_SOURCES ; i++) { statut = pthread_create(&mesThreadsSources[i], NULL, threadSources, NULL); } pthread_join(mesThreadsSources[0], NULL); pthread_join(threadAff, NULL); printf("FIN DU JEU\n"); return 0; } #endif
Partager