ciao a tutti!Io e la mia collega abbiamo un nuovo problema da risolvere. Dobbiamo fare una versione di Space Invaders utilizzando la SystemV con i semafori. Il problema č che i nemici non si muovono in modo fluido, vanno a scatti e non capiamo dove stiamo sbagliando..potete aiutarci? grazie anticipatamente!
(continua)codice:#include <stdio.h> #include <stdlib.h> #include <time.h> #include <sys/shm.h> #include <sys/sem.h> #include <curses.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 3 // numero di nemici di 1° livello #define G 4 // numero di nemici di 2° livello per gruppo /* chiavi per l'identificazione dei segmenti di memoria da creare */ key_t mem_key; // chiave memoria key_t sem_key; // chiave set di semafori /* identificatori per i segmenti di memoria allocati */ int seg_mem; // identificatore segmento di memoria int semid; // identificatore set di semafori /* Struttura union semun */ union semun { int val; // per SETVAL struct semid_ds *buf; // per IPC_STAT e IPC_SET unsigned short *array; // per GETALL e SETALL struct seminfo * __buf ; /* buffer for IPC_INFO */ }; /* 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 xi; // coordinata x del primo nemico di secondo livello int xf; // coordinata x dell'ultimo nemico di secondo livello 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 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; /* Puntatori alla memoria condivisa */ pos* pos_mem; /* Prototipi funzioni */ void astronave (); void missile (int i, int x1, int y1); void nemico(int i); void nemico2(int i,int x, int y); void bomba(int x1, int y1); void sem_iniz(int semaforino); void wait_sem(int semaforino); void post_sem(int semaforino); void controllo(); void gestione_mem(); void libera_mem(); 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 int pid_astronave, pid_nemico, i; /* Chiamate per l'inizializzazione della memoria condivisa e dei semafori */ gestione_mem(); sem_iniz(0); /* Creazione processi */ switch(pid_astronave=fork()) { case -1: perror("Errore nell'esecuzione della fork astronave"); exit(1); case 0: astronave(); } for(i=0;i<M;i++) { switch(pid_nemico=fork()) { case -1: perror("Errore nell'esecuzione della fork nemico"); exit(1); case 0: nemico(i); } } controllo(); libera_mem(); /** Siamo usciti dal controllo e si terminano i procssi figli. Ripristina il normale modo operativo dello schermo **/ endwin(); return(0); } /**Funzione GESTIONE_MEM - per la gestione della memoria **/ void gestione_mem() { int i; /* creazione delle chiavi per i segmenti di memoria e per il set di semafori */ if((mem_key = ftok(".",0)) == -1) { perror ("\nErrore ftok memoria!"); exit (1); } if((sem_key = ftok(".",1)) == -1) { perror ("\nErrore ftok set di semafori!"); exit (1); } /* Allocazione dei segmenti di memoria condivisa e del set di semafori */ if((seg_mem = shmget(mem_key,sizeof(pos),IPC_CREAT | 0666)) < 0) { perror ("Errore shmget memoria!"); exit (1); } if((semid = semget(sem_key,1,IPC_CREAT | 0600)) < 0) { perror ("Errore semget set di semafori!"); exit (1); } /* Attachment dei segmenti di memoria */ if((int) (pos_mem = shmat(seg_mem, NULL, SHM_RND)) == -1) { perror ("Errore shmat memoria!"); exit (1); } } // fine funzione GESTIONE_MEM /** Funzione SEM_INIZ - per l'inizializzazione dei semaforini **/ void sem_iniz(int semaforino) { union semun arg; unsigned short values[2]; values[0] = 1; values[1] = 0; arg.array = values; if(semctl(semid,semaforino,SETALL,arg) == -1) { perror ("Errore semctl semaforino!"); exit (1); } } // fine funzione SEM_INIZ /** Funzione WAIT_SEM **/ void wait_sem(int semaforino) { struct sembuf op[1]; op[0].sem_num = semaforino; op[0].sem_op = -1; op[0].sem_flg = SEM_UNDO; semop(semid,op,1); } // fine funzione WAIT_SEM /** Funzione POST_SEM **/ void post_sem(int semaforino) { struct sembuf op[1]; op[0].sem_num = semaforino; op[0].sem_op = 1; op[0].sem_flg = SEM_UNDO; semop(semid,op,1); } // fine funzione POST_SEM /** Funzione LIBERA_MEM - per il detachment e la deallocazione dei segmenti di memoria **/ void libera_mem() { /* Detachment dei segmenti di memoria*/ if(shmdt(pos_mem) == -1) { perror ("Errore shmdt memoria!"); exit (1); } /* Deallocazione dei segmenti di memoria e del semaforo */ if(shmctl(seg_mem,IPC_RMID,0) == -1) { perror ("Errore deallocazione nemico di primo livello!"); exit (1); } if(semctl(semid,1,IPC_RMID) == -1) { perror ("Errore deallocazione semaforo!"); exit (1); } } // fine funzione LIBERA_MEM /** Funzione ASTRONAVE **/ void astronave () { pos pos_astronave; int pid_missile[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=getpid(); wait_sem(0); *pos_mem = pos_astronave; post_sem(1); 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; break; case DESTRA: if(pos_astronave.x<MAXX-1) pos_astronave.x+=1; break;/* case SGANCIA: for(i=0;i<2;i++) switch(pid_missile[i]=fork()) { case -1: perror("Errore nell'esecuzione della fork"); exit(1); case 0: missile(pipeout,i,pos_astronave.x,pos_astronave.y); } break;*/ } // fine switch gestione movimento wait_sem(0); *pos_mem = pos_astronave; post_sem(1); } } // fine Funzione Astronave /** Funzione NEMICO **/ void nemico(int i) { pos pos_nemico; 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 int pid_bomba; pos_nemico.c='$'; pos_nemico.p=i; pos_nemico.pid=getpid(); 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 } wait_sem(0); *pos_mem = pos_nemico; post_sem(1); 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 // aggiorniamo la posizione del nemico e la comunichiamo al controllo wait_sem(0); *pos_mem = pos_nemico; post_sem(1); /* if(!(time_bomb%SOGLIA_BOMB)) // ad intervalli regolari switch(pid_bomba=fork()) { // il nemico sgancia la bomba case -1: perror("Errore nella creazione del processo bomba"); exit(1); case 0: bomba(pipeout,pos_nemico.x,pos_nemico.y); } time_bomb++; // aggiorno il contatore per la bomba */ usleep(300000); } // fine while; } // fine Funzione Nemico

Rispondi quotando