Visualizzazione dei risultati da 1 a 2 su 2

Discussione: [C] SystemV e semafori

  1. #1

    [C] SystemV e semafori

    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!
    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
    (continua)
    Mau

  2. #2
    codice:
    /** Funzione CONTROLLO **/
    void controllo()
    {
    pos astronave, missile[2], bomba, nemico[M], nem2[M], valore_letto;
    int GAME_OVER=0; // se game_over=-1 l'astronave č stata uccisa, se game_over=1 l'astronave ha vinto, se game_over=0 il gioco prosegue
    int NEM_VIVI=M+M*G; // segna quanti nemici vivi ci sono
    int vita[M]; // vettore che indica lo stato di vita dei nemici di primo livello
    int vite[M][G]; // vettore che indica lo stato di vita dei singoli nemici di secondo livello
    int vita_gruppo[M]; // vettore che indica lo stato di vita del gruppo iesimo
    int i,j;
    pthread_t nemico2_id[M];
    
    
    init_pair(1,COLOR_GREEN,COLOR_BLACK);
    init_pair(2,COLOR_CYAN,COLOR_BLACK);
    init_pair(3,COLOR_YELLOW,COLOR_BLACK);
    init_pair(4,COLOR_RED,COLOR_BLACK);
    init_pair(5,COLOR_BLUE,COLOR_BLACK);
    init_pair(6,COLOR_MAGENTA,COLOR_BLACK);
    
    astronave.x=-1; // all'inizio l'astronave si trova fuori scena
    
    for(i=0;i<2;i++)
        missile[i].x=-1; // all'inizio il missile si trova fuori scena
    
    for(i=0;i<M;i++)
       {
          nemico[i].x=-1; // all'inizio il nemico di primo livello si trova fuori scena
          nem2[i].xf=-1; // all'inizio il nemico di secondo livello si trova fuori scena
    
          vita[i]=1; // il nemico di primo livello ha una vita
          vita_gruppo[i]=4; // il gruppo di nemici di secondo livello viene annientato quando i 4 nemici che lo compongono muoiono
        }
    
    for(i=0;i<M;i++)
       for(j=0;j<G;j++)
          vite[i][j]=2; // i nemici di secondo livello hanno 2 vite
    
    do
    {
     wait_sem(1);
     valore_letto = *pos_mem;
     post_sem(0);
    
    switch(valore_letto.c) {
               
             case '#': /** CASO ASTRONAVE **/
    	
             if(astronave.x>=0) // se l'astronave č giā entrata in scena
                {
                  // cancello la "vecchia" posizione dell'astronave
                  mvaddch(astronave.y,astronave.x,' ');
                }
             astronave=valore_letto; // aggiorno la sua nuova posizione
    	 attron(COLOR_PAIR(5));
             mvaddch(astronave.y,astronave.x,astronave.c); // e la visualizzo
    	break;
                        
    
    	case '$': /** CASO NEMICO **/
    
    	if(nemico[valore_letto.p].x>=0) // se il nemico č giā entrato in scena
               mvaddch(nemico[valore_letto.p].y,nemico[valore_letto.p].x,' ');  // cancello la "vecchia" posizione del nemico
                                
            nemico[valore_letto.p]=valore_letto; // aggiorno la posizione del nemico
    	attron(COLOR_PAIR(1));
            mvaddch(nemico[valore_letto.p].y,nemico[valore_letto.p].x,nemico[valore_letto.p].c); // e lo visualizzo
    	
    	break;
    
    	} // fine switch                         
    
           
    
    if(!NEM_VIVI) // se NEM_VIVI č uguale a 0
       GAME_OVER=1; // l'astronave ha vinto
       
    
    curs_set(0);
    refresh();
    } // fine do
    while(!GAME_OVER);
    
    if(GAME_OVER>0)
      {
        mvaddstr(MAXY/2, MAXX/2-3,"HAI VINTO!");
        refresh();
        fflush(stdin);
        getchar();
      }
    else
      {
        mvaddstr(MAXY/2, MAXX/2-3,"HAI PERSO!");
        refresh();
        fflush(stdin);
        getchar();
      }
    
    } // fine Funzione Controllo
    Mau

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.