Ciao a tutti! Io e la mia collega abbiamo bisogno del vostro aiuto!![]()
Dobbiamo fare una versione (molto semplificata) di Space Invaders e usare i thread per la comunicazione tra i processi..Il problema è che durante l'esecuzione, il programma si blocca o a causa della segmentation fault o perchè viene sollevata la floating point exception..Il motivo??boooh!!!Vi posto il codice..è un po' lunghetto, ma ci sono tanti commenti così potete capire cosa abbiamo fatto..Vi prego..aiutateci!!![]()
(continua...)codice:#include <stdio.h> #include <time.h> #include <curses.h> #include <pthread.h> #include <stdlib.h> #include <signal.h> #include <semaphore.h> #include <unistd.h> #define PASSO 1 //entita' dello spostamento del nemico #define SINISTRA 68 // freccia sx #define DESTRA 67 // freccia dx #define SGANCIA 32 // spazio #define MAXX 80 // numero di colonne dello schermo #define MAXY 24 // numero di righe dello schermo #define M 2 // numero di nemici di 1° livello #define G 4 // numero di nemici di 2° livello per gruppo #define BUFFER_DIM 100000 //** Prototipi funzioni **// void * astronave_func(void * arg); void * missile_func(void * arg); void * nemico_func(void * arg); void * nemico2_func(void * arg); void * bomba_func(void * arg); void * controllo_func(void * arg); //**Struttura per la comunicazione fra figli e padre**// typedef struct pos { char c; // soggetto che invia il dato: astronave, nemico, bomba o missile int x; // coordinata x int y; // coordinata y int DIRX; // direzione del nemico di 2° livello int p; // posizione del nemico all'interno del vettore v[] che rappresenta il gruppo di nemici di primo livello int pid; // pid del processo int vita; // 0: il nemico è morto; 1: il nemico è vivo int xi; // coordinata x del primo nemico di secondo livello int xf; // coordinata x dell'ultimo nemico di secondo livello int nem_vivi[G]; // vettore che indica lo stato di vita dei nemici di secondo livello all'interno di ciascun gruppo int g; // rappresenta il numero del gruppo a cui appartiene il nemico di secondo livello int n; // rappresenta il numero assegnato al nemico di 2° livello all'interno del proprio gruppo } pos; typedef struct argomenti // struttura per passare più argomenti ad una funzione thread { int x; // posizione in x (dell'astronave o del nemico) int y; // posizione in y (dell'astronave o del nemico) int i; // indice i } args; //** Inizializzazioni buffer e semafori **// pos buffer[BUFFER_DIM]; // buffer condiviso int IN = 0; // variabile che indica le posizioni occupate nel buffer int OUT = 0; // variabile che indica le posizioni disponibili nel buffer sem_t presenti, disponibili; // variabili che indicano il valore del semaforo, ovvero la presenza o meno di job disponibili pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // mutex per evitare la race condiction main() { initscr(); // inizializzazione dello schermo start_color(); // per l'utilizzazione dei colori noecho(); // i caretteri corrispondenti ai tasti premuti non saranno visualizzati sullo schermo del terminale curs_set(0); // nasconde il cursone sem_init(&disponibili, 0, BUFFER_DIM); // inizializzazione semaforo disponibili sem_init(&presenti, 0, 0); // inizializzazione semaforo presenti //pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // inizializzazione mutex srand(time(NULL)); pthread_t astronave_id, nemico_id[M], controllo_id; int i; //creazione dei thread pthread_create(&astronave_id, NULL, &astronave_func, NULL); for(i=0;i<M;i++) pthread_create(&nemico_id[i], NULL, &nemico_func, &i); //evita che vengano deallocati dati indispensabili ai thread alla terminazione del main //pthread_join(astronave_id, NULL); pthread_create(&controllo_id, NULL, &controllo_func, NULL); pthread_join(controllo_id, NULL); /** Siamo usciti dal controllo e si terminano i procssi figli. Ripristina il normale modo operativo dello schermo **/ endwin(); return(0); } /** Funzione ASTRONAVE **/ void * astronave_func(void * arg) { pos pos_astronave; args pos; pthread_t missile_id[2]; // l'astronave spara contemporaneamente due missili:uno a destra e uno a sinistra int i; pos_astronave.c='#'; pos_astronave.x=MAXX/2; pos_astronave.y=MAXY-1; pos_astronave.pid=pthread_self(); sem_wait(&disponibili); pthread_mutex_lock(&mutex); buffer[IN] = pos_astronave; IN=(IN+1)%BUFFER_DIM; sem_post(&presenti); // incrementa il semaforo pthread_mutex_unlock(&mutex); while(1) { char c; switch(c=getch()) { //gestione movimento o sgancio dei missili da parte dell'astronave case SINISTRA: if(pos_astronave.x>0){ pos_astronave.x-=1; } // fine if(pos_astronave.x>0) break; case DESTRA: if(pos_astronave.x<MAXX-1){ pos_astronave.x+=1; } break; case SGANCIA: for(i=0;i<2;i++){ pos.i=i; pos.x=pos_astronave.x; pos.y=pos_astronave.y; pthread_create(&missile_id[i], NULL, &missile_func, &pos); //pthread_join(missile_id[i], NULL); } break; } // fine switch gestione movimento sem_wait(&disponibili); pthread_mutex_lock(&mutex); buffer[IN] = pos_astronave; IN=(IN+1)%BUFFER_DIM; sem_post(&presenti); // incrementa il semaforo pthread_mutex_unlock(&mutex); } // fine while } // fine Funzione Astronave /** Funzione MISSILE **/ void * missile_func(void * arg) { pos pos_missile; args * pos = (args *)arg; int i = pos->i; pos_missile.c='*'; /*Effettuo il primo assegnamento*/ pos_missile.pid=pthread_self(); pos_missile.p=i; // può essere 0 o 1 e indica quella che sarÃ_ la direzione del missile (dx o sx) if(i%2) // se i è dispari pos_missile.x=pos->x +PASSO; // vÃ_ a sinistra else // altrimenti pos_missile.x=pos->x -PASSO; // vÃ_ a destra pos_missile.y=pos->y-1; sem_wait(&disponibili); pthread_mutex_lock(&mutex); buffer[IN] = pos_missile; IN=(IN+1)%BUFFER_DIM; sem_post(&presenti); // incrementa il semaforo pthread_mutex_unlock(&mutex); if(i%2) //se i=1 il missile vÃ_ a sinistra altrimenti a destra while(1) { pos_missile.x+=PASSO; pos_missile.y-=PASSO; sem_wait(&disponibili); pthread_mutex_lock(&mutex); buffer[IN] = pos_missile; IN=(IN+1)%BUFFER_DIM; sem_post(&presenti); // incrementa il semaforo pthread_mutex_unlock(&mutex); usleep(200000); } else while(1) { pos_missile.x-=PASSO; pos_missile.y-=PASSO; sem_wait(&disponibili); pthread_mutex_lock(&mutex); buffer[IN] = pos_missile; IN=(IN+1)%BUFFER_DIM; sem_post(&presenti); // incrementa il semaforo pthread_mutex_unlock(&mutex); usleep(200000); } } // fine Funzione Missile /** Funzione BOMBA **/ void * bomba_func(void * arg) { pos pos_bomba; args * pos = (args *)arg; pos_bomba.c='o'; //inizializzo: la bomba parte dalla stessa colonna del nemico una posizione in avanti pos_bomba.x=pos->x; pos_bomba.y=pos->y +PASSO; pos_bomba.pid=pthread_self(); sem_wait(&disponibili); pthread_mutex_lock(&mutex); buffer[IN] = pos_bomba; IN=(IN+1)%BUFFER_DIM; sem_post(&presenti); // incrementa il semaforo pthread_mutex_unlock(&mutex); while(1) { pos_bomba.y+=PASSO; sem_wait(&disponibili); pthread_mutex_lock(&mutex); buffer[IN] = pos_bomba; IN=(IN+1)%BUFFER_DIM; sem_post(&presenti); // incrementa il semaforo pthread_mutex_unlock(&mutex); usleep(300000); } }//fine funzione bomba /** Funzione NEMICO **/ void * nemico_func(void * arg) { pos pos_nemico; int i = *((int *)arg); int dx,dy; // spostamenti in x e y; int SOGLIAX; // soglia oltre la quale il nemico non può andare - può essere 1 o MAXX-1 int DIRX; // direzione in x - se dirx=1 vÃ_ a destra, se dirx=-1 va a sinistra int time_giu=0; // contatore per far scendere il nemico int SOGLIA_GIU=10*(0+rand()%4)+i*5; // soglia per far scendere il nemico di una riga int time_bomb=1; // contatore per far sganciare una bomba int SOGLIA_BOMB=30+i*(0+rand()%5); // soglia per far sganciare la bomba args pos; pthread_t bomba_id; pos_nemico.c='$'; pos_nemico.p=i; pos_nemico.pid=pthread_self(); pos_nemico.y=1; // i nemici partono tutti sulla stessa riga pos_nemico.x=9+(i*20); // ma distanziati if(!(i%2)) // se il numero assegnato al nemico è pari { DIRX=1; // vÃ_ a destra SOGLIAX=MAXX-1; // e la soglia max in x è MAXX-1 } else // altrimenti { DIRX=-1; // vÃ_ a sinistra SOGLIAX=1; // e la soglia max in x è 1 } sem_wait(&disponibili); pthread_mutex_lock(&mutex); buffer[IN] = pos_nemico; IN=(IN+1)%BUFFER_DIM; sem_post(&presenti); // incrementa il semaforo pthread_mutex_unlock(&mutex); while(1) { if(pos_nemico.x==SOGLIAX) // se il nemico sbatte contro una parete laterale { DIRX*=-1; // cambio la direzione if(SOGLIAX==MAXX-1) // se la nuova direzione è destra SOGLIAX=1; // la soglia è MAXX-1 else // altrimenti SOGLIAX=MAXX-1; // la soglia è 1 } if(DIRX==1) // se la direzione è destra dx=PASSO; // il suo spostamento sarÃ_ di PASSO else // altrimenti dx=-PASSO; // il suo spostamento sarÃ_ di -PASSO pos_nemico.x+=dx; // scriviamo la posizione in x del nemico if(!(time_giu%SOGLIA_GIU)) // ad intervalli regolari { dy=PASSO; // il nemico avanza di PASSO verso la soglia massima in Y time_giu=1; // riazzero il contatore } else { dy=0; // il nemico non avanza verso la soglia massima in Y time_giu++; // aggiorno il contatore per la discesa del nemico } pos_nemico.y+=dy; // scriviamo la posizione in y del nemico sem_wait(&disponibili); pthread_mutex_lock(&mutex); buffer[IN] = pos_nemico; IN=(IN+1)%BUFFER_DIM; sem_post(&presenti); // incrementa il semaforo pthread_mutex_unlock(&mutex); if(!(time_bomb%SOGLIA_BOMB)){ // ad intervalli regolari pos.x = pos_nemico.x; pos.y = pos_nemico.y; pthread_create(&bomba_id, NULL, &bomba_func, &pos); //pthread_join(bomba_id, NULL); } time_bomb++; // aggiorno il contatore per la bomba usleep(300000); } // fine while; } // fine Funzione Nemico

Rispondi quotando