Condividi:        

[C] problemi gioco space invaders SYSTEM V -urgente!!!!

Problemi di HTML? Di PHP, ASP, .NET, JSP, Perl, SQL, JavaScript, Visual Basic..?
Vuoi realizzare programmi in C, C++, Java, Ruby o Smalltalk, e non sai da che parte cominciare?
Entra qui e troverai le risposte!

Moderatori: Anthony47, Triumph Of Steel, archimede

[C] problemi gioco space invaders SYSTEM V -urgente!!!!

Postdi caralu » 16/07/06 22:31

Ciao ragazzi! Ancora una volta alle prese con lo stesso gioco ma con un diverso esercizio...
E' un programmino didattico: sarebbe una emulazione del gioco di space invaders (ma molto grezzo!),con grafica scarna.
Il programma è quasi analogo al classico problema dei "produttori-consumatori": creo dei processi, che accedono ad un buffer condiviso (protetto da semafori), basandomi sulle librerie lpthread e lncurses, utilizzando il sistema comunicazione interprocesso delle System V di linux.
Ho creato un sistema iniziale ma non capisco come mai quando sparo le bombe della navetta con il tasto "spazio" i processi della nave vengono duplicati e non funziona la funzione (scusate la ripetizione!) di collisione delle bombe nave con gli alieni..
Potete darmi una mano per favore? Ecco il codice, Grazie
Codice: Seleziona tutto
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <sys/signal.h>
#include <setjmp.h>
#include <stdlib.h>
#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <curses.h>
#include <time.h>

#define RMODE   0644
#define WMODE   0666
#define NUM_MAX_RIGHE 5
#define SINISTRA 68
#define DESTRA 67
#define N_INIZIALE_ALIENI 10
#define SPAZIO 3
#define SPAZIO_RIGHE 1
#define PASSO_X 2
#define PASSO_Y 1
#define BUFFER_DIM 10
#define MAX_BOMBE_NAVE 5
#define MAX_BOMBE_ALIENO N_INIZIALE_ALIENI * 2

struct pos {
char *c;
int x;
int y;
int index;
int xPrec;
int yPrec;
int pid;
};

int empty, full, mutex, buffer_id, mutexBombeNave, mutexBombeAlieni, livello;
key_t empty_t, full_t, mutex_t, mutex_nave, mutex_alieni;     // le zone di memoria dei due semafori e del semaforo-mutex


void scrittore(struct pos *, struct pos );
void lettore(struct pos *);
void crea_proc(int, int);
void bomba(struct pos, struct pos *, int *);
void creaBomba(struct pos);
void sparaBomba(struct pos);
bool collisione_alieni(int);
bool collisione_nave(int);

// buffer che poi verrà condiviso //
struct BUF {
struct pos *info_elementi[BUFFER_DIM];
struct pos info_alieno[N_INIZIALE_ALIENI];
struct pos info_nave;
struct pos bombe_nave[MAX_BOMBE_NAVE];
struct pos bombe_alieno[MAX_BOMBE_ALIENO];
int vitaAlieni[N_INIZIALE_ALIENI];
int vitaNave;
int vitaBombeNave[MAX_BOMBE_NAVE];
int vitaBombeAlieno[MAX_BOMBE_ALIENO];
int in;
int out;
bool esci;
int posDisponibileAlieno;
int posDisponibileNave;
int nBombeNaveResidue;
int nBombeAlienoResidue;
} * bufferpointer;


union semun {
    int val;
    struct semid_ds *buf;
    unsigned short int *array;
    struct seminfo *__buf;};


/* Function MutexCreate : create a mutex / semaphore */
int MutexCreate ( key_t ipc_key )
{
   const union semun semunion={1}; /* semaphore union structure: mutex must be initialized with 1*/
   int sem_id , ret;
   sem_id = semget ( ipc_key , 1 , IPC_CREAT | WMODE); /* get semaphore ID */
   if ( sem_id == -1) { /* if error return code */
      return sem_id ;
   }
   ret = semctl (sem_id , 0 , SETVAL , semunion ); /* init semaphore */
   if ( ret == -1) {
       return ret;
   }
   return sem_id ;
}



 /* Define sembuf structures to lock and unlock the mutex or to create wait and signal for semaphores */
struct sembuf sem_lock_or_wait ={ /* to lock mutex or wait for semaphore */
    0, /* semaphore number ( only one so 0) */
    -1, /* operation ( -1 to use resource ) */
    SEM_UNDO }; /* flag ( set for undo at exit ) */

struct sembuf sem_ulock_or_signal ={ /* to unlock mutex or post a signal for semaphore */
    0, /* semaphore number ( only one so 0) */
    1, /* operation (1 to release resource ) */
    SEM_UNDO }; /* flag ( in this case 0) */


 /* Function Lock_Wait : to lock a mutex or wait for semaphore */
int Lock_Wait (int sem_id )
 {
    return semop (sem_id , & sem_lock_or_wait , 1);
 }


 /* Function Unlock_Signal : to unlock a mutex or signal for semaphore */
int Unlock_Signal (int sem_id )
 {
    return semop (sem_id , & sem_ulock_or_signal , 1);
 }


 /* Function SemRemove : remove a mutex / semaphore */
int SemRemove (int sem_id )
 {
    return semctl (sem_id , 0 , IPC_RMID );
 }


 
void alieni(int index, int xIniz, int yIniz)
{
int i;

bufferpointer=(struct BUF *) shmat ( buffer_id , NULL , 0) ; // Attachment al buffer condiviso

struct pos pos_alieno, pos_bomba;

int dx, dy;
pos_alieno.x = xIniz * (SPAZIO + 1);
pos_alieno.y = yIniz * (SPAZIO_RIGHE + 1);
pos_alieno.c = "#";
pos_alieno.index = index;
pos_alieno.pid = getpid();
srand(pos_alieno.pid); //inizializziamo il generatore random
int dir = 1;

while(!bufferpointer->esci && bufferpointer->vitaAlieni[index])
   {
   pos_alieno.pid = getpid();
   pos_alieno.yPrec = pos_alieno.y;
   pos_alieno.xPrec = pos_alieno.x;
   dx = PASSO_X * dir;
   dy = 0;
   if (pos_alieno.x + dx >= COLS -1 || pos_alieno.x + dx <= 0)
      {
      if(dir > 0)
         pos_alieno.x = COLS - 1;
      else
         pos_alieno.x = 0;
      dir = -dir;
      dx = PASSO_X * dir;
      dy = PASSO_Y;
      }
   pos_alieno.x += dx;
   pos_alieno.y += dy;
   scrittore(&bufferpointer->info_alieno[pos_alieno.index], pos_alieno);
   double t = clock();
   if((rand() % 100) >= 99 - 1) // 1 qui equivale al livello....da aggiornare!
   {
   Lock_Wait(mutexBombeAlieni);
   if(bufferpointer->nBombeAlienoResidue > 0)
      {
      bufferpointer->nBombeAlienoResidue--;
      bufferpointer->posDisponibileAlieno = (bufferpointer->posDisponibileAlieno + 1) % MAX_BOMBE_ALIENO;
      pos_bomba.index = bufferpointer->posDisponibileAlieno;
      pos_bomba.x = pos_bomba.xPrec = pos_alieno.x;
      pos_bomba.y = pos_alieno.y + 1;
      pos_bomba.c = "!";
      creaBomba(pos_bomba);
      }
   Unlock_Signal(mutexBombeAlieni);
   }
   t = 1000000 - (clock() - t);
   usleep(t);
   }

  shmdt  (bufferpointer); //Detachment del buffer condiviso
  shmctl (buffer_id, IPC_RMID , NULL); //Deallocazione del buffer condiviso
}

void nave()
{
bufferpointer=(struct BUF *) shmat (buffer_id , NULL , 0) ; // Attachment al buffer condiviso
struct pos pos_nave;
struct pos pos_bomba;
pos_nave.c = "^";
pos_nave.x = COLS / 2;
pos_nave.yPrec = pos_nave.y = LINES - 1;
pos_nave.index = 1; //per ora è inutile...
scrittore(&bufferpointer->info_nave, pos_nave);
while(!bufferpointer->esci && bufferpointer->vitaNave)
   {
   char c;
   pos_nave.xPrec = pos_nave.x;
   switch(c = getch())
      {
      case SINISTRA: if(pos_nave.x > 1) pos_nave.x -= 1;
      break;
      case DESTRA: if(pos_nave.x < COLS - 1) pos_nave.x += 1;
      break;
      case 'q': bufferpointer->esci = true;
      break;
      case ' ':
         Lock_Wait(mutexBombeNave);
         if(bufferpointer->nBombeNaveResidue > 0)
            {
            bufferpointer->nBombeNaveResidue--;
            bufferpointer->posDisponibileNave = (bufferpointer->posDisponibileNave + 1) % MAX_BOMBE_NAVE;
            pos_bomba.index = bufferpointer->posDisponibileNave;
            pos_bomba.x = pos_bomba.xPrec = pos_nave.x;
            pos_bomba.y = LINES - 2;
            pos_bomba.c = "o";
            creaBomba(pos_bomba);
            }
         Unlock_Signal(mutexBombeNave);
      }
   if (c == DESTRA || c == SINISTRA)
      {
      scrittore(&bufferpointer->info_nave, pos_nave);
      }
   }

shmdt(bufferpointer); //Detachment
shmctl(buffer_id, IPC_RMID , NULL);//Deallocazione
}

void creaBomba(struct pos pos_bomba)
{
switch(fork()) {
      case -1: printf("Errore fork!");
      break;
      case 0:sparaBomba(pos_bomba);
      break;
      default: return;
      }
}
void sparaBomba(struct pos pos_bomba)
{
pos_bomba.pid = getpid();
struct pos *posizione;
int *posizioneVita;
if(pos_bomba.c == "!") // è un alieno?
   {
   Lock_Wait(mutexBombeAlieni);
   posizione = &bufferpointer->bombe_alieno[bufferpointer->posDisponibileAlieno];
   posizioneVita = &bufferpointer->vitaBombeAlieno[bufferpointer->posDisponibileAlieno];
   *posizioneVita = 1;
   Unlock_Signal(mutexBombeAlieni);
   bomba(pos_bomba, posizione, posizioneVita);
   Lock_Wait(mutexBombeAlieni);
   bufferpointer->nBombeAlienoResidue++;
   Unlock_Signal(mutexBombeAlieni);
   }
   else
      if(pos_bomba.c == "o") //è una nave?
         {
         Lock_Wait(mutexBombeNave);
         posizione = &bufferpointer->bombe_nave[bufferpointer->posDisponibileNave];
         posizioneVita = &bufferpointer->vitaBombeAlieno[bufferpointer->posDisponibileAlieno];
         *posizioneVita = 1;
         Unlock_Signal(mutexBombeNave);
         bomba(pos_bomba, posizione, posizioneVita);
         Lock_Wait(mutexBombeNave);
         bufferpointer->nBombeNaveResidue++;
         Unlock_Signal(mutexBombeNave);
         }
}

void bomba(struct pos pos_bomba, struct pos *posizione, int *posVita)
{
int limite = (pos_bomba.c == "!") ? LINES - 1 : 0;
int dir = (pos_bomba.c == "!") ? 1 : -1;
scrittore(posizione, pos_bomba);
while(pos_bomba.y != limite && *posVita)
   {
   usleep(100000);
   pos_bomba.yPrec = pos_bomba.y;
   pos_bomba.y += dir;
   scrittore(posizione,pos_bomba);
   }
pos_bomba.c = " ";
scrittore(posizione, pos_bomba);
}

void controllo()
{
struct pos valore_letto;
int nAlieni = N_INIZIALE_ALIENI;
int statoGioco = 0;
int punteggio = 0;
int puntiKiller = 10;
int dimAlieni = 1;
int nAlieniRiga = COLS / (dimAlieni + SPAZIO);

bufferpointer=(struct BUF *) shmat ( buffer_id , NULL , 0) ;          // Attachment al buffer condiviso

livello = 1;
do {
   statoGioco = 1;
do {
   lettore(&valore_letto);
   if(valore_letto.c == "#")
      {
         if(valore_letto.y == bufferpointer->info_nave.y - SPAZIO_RIGHE)
            {
               bufferpointer->vitaNave--;
               bufferpointer->info_nave.xPrec = bufferpointer->info_nave.x;
               bufferpointer->info_nave.x = LINES / 2;
               statoGioco = -1;
            }
      }
   else
      if(valore_letto.c == "o")
      {
         if (collisione_alieni(valore_letto.index))
         {
            punteggio += puntiKiller;
            nAlieni--;
            if(nAlieni == 0) statoGioco = 0;
            valore_letto.c = " ";
         }
      }
      else
         if(valore_letto.c == " ")
         {
            if(collisione_nave(valore_letto.index))
            {   
               bufferpointer->vitaNave--;
               bufferpointer->info_nave.xPrec = bufferpointer->info_nave.x;
               bufferpointer->info_nave.x = LINES / 2;
               statoGioco = -1;
               valore_letto.c = "^";
            }
         }
   move(valore_letto.yPrec, valore_letto.xPrec);
   printw(" ");
   move(valore_letto.y, valore_letto.x);
   printw("%s",valore_letto.c);
   move(0,0); // colloca nelle coordinate 0,0 il punteggio
   printw("Punteggio %d",punteggio);
   move(0,15);
   printw("\tlivello %d",livello);
   move(0,27);
   printw("\tvite %d",bufferpointer->vitaNave);
   move(1,0);
   printw("nAlieni %d",nAlieni);
   refresh();
   }
while (statoGioco > 0 && !bufferpointer->esci);
   if(statoGioco == -1) //vita persa
   {
   move(COLS - 10, 0);
   printw("Vita Persa!!!!");
   refresh();
   usleep(1000000);
   move(COLS - 10, 0);
   deleteln(); //cancella vita persa
   insertln();
   move(bufferpointer->info_nave.y, bufferpointer->info_nave.x);
   printw(" ");
   refresh();
   }
   else if(statoGioco == 0)
   {
      livello++;
      nAlieni = N_INIZIALE_ALIENI;
      crea_proc(0, nAlieniRiga);
   }

}
while(bufferpointer->vitaNave > 0 && !bufferpointer->esci);
  shmdt  (bufferpointer);
  shmctl (buffer_id, IPC_RMID , NULL );

}

bool collisione_alieni(int index)
{
int i;
int status;
for(i=0; i< N_INIZIALE_ALIENI; i++)
   {
   Lock_Wait(mutex);
   if(bufferpointer->bombe_nave[index].x == bufferpointer->info_alieno[i].x && bufferpointer->bombe_nave[index].y == bufferpointer->info_alieno[i].y && bufferpointer->vitaAlieni[i] && bufferpointer->vitaBombeNave[index])
      {
      bufferpointer->vitaAlieni[i] -= 1;
      bufferpointer->vitaBombeNave[index] -= 1;
      if (bufferpointer->vitaAlieni[i] == 0)
         {
         kill(bufferpointer->info_alieno[i].pid, 1);
         }
      if (bufferpointer->vitaBombeNave[index] == 0)
         {
         kill(bufferpointer->bombe_nave[index].pid, 1);
         }
      return true;
      }
   Unlock_Signal(mutex);
   }
return false;
}

bool collisione_nave(int index)
{
return(bufferpointer->bombe_alieno[index].x == bufferpointer->info_nave.x  && bufferpointer->bombe_alieno[index].y == LINES - 1);
}

void crea_proc(int n, int nAlieniRiga)
{
int i,j;
i = n % nAlieniRiga;
j = (n / nAlieniRiga) + 1;
switch(fork())
   {
   case -1: printf("Errore nell'esecuzione della fork");
   case 0: alieni(n, i, j);
      break;
   default:if (n < N_INIZIALE_ALIENI - 1)
         crea_proc(n + 1, nAlieniRiga);
   }
}

void scrittore(struct pos *posizione, struct pos item)
{
Lock_Wait(empty);
Lock_Wait(mutex);
bufferpointer->info_elementi[bufferpointer->in] = posizione;
*posizione = item;
bufferpointer->in = (bufferpointer->in + 1) % BUFFER_DIM;
Unlock_Signal(mutex);
Unlock_Signal(full);
}

void lettore(struct pos *item)
{
Lock_Wait(full); //Segnala che è stata letta una posizione dal buffer
Lock_Wait(mutex);
*item = *bufferpointer->info_elementi[bufferpointer->out];
bufferpointer->out = (bufferpointer->out + 1) % BUFFER_DIM;
Unlock_Signal(mutex);
Unlock_Signal(empty);
}

int dimAlieni = 1;

int main()
{
union semun arg1, arg2;   // argomento per semctl per indicare il valore del semaforo
int i;
initscr();
noecho();
curs_set(0);
// creazione semaforo empty //
if ((empty = semget(empty_t, 1, IPC_CREAT | IPC_EXCL | WMODE)) == (-1))
   printf("Errore semaforo empty\n");

// inizializzazione del semaforo empty con la dimensione del buffer //
arg1.val = BUFFER_DIM;
semctl (empty, 0, SETVAL, arg1);
   
   
// creazione semaforo full //
if ((full = semget(full_t, 1, IPC_CREAT | IPC_EXCL | WMODE)) == (-1))
   printf("Errore semaforo full\n");
 
// inizializzazione del semaforo full a zero //
arg2.val = 0;
semctl (full, 0, SETVAL, arg2);

// creazione del mutex //
mutex=MutexCreate(mutex_t);         
mutexBombeNave = MutexCreate(mutex_nave);
mutexBombeAlieni = MutexCreate(mutex_alieni);
// creazione della memoria condivisa per il buffer //
buffer_id = shmget ( IPC_PRIVATE , sizeof(struct BUF) , IPC_CREAT | IPC_EXCL | WMODE );  /* Ottiene l'ID della Shared memory */

bufferpointer=(struct BUF *) shmat ( buffer_id , NULL , 0) ;         // Attachment al buffer condiviso
Lock_Wait(mutex);
bufferpointer->in = 0;
bufferpointer->out = 0;
bufferpointer->vitaNave = 3;
for(i = 0;i < N_INIZIALE_ALIENI; i++)
bufferpointer->vitaAlieni[i] = 1;
bufferpointer->posDisponibileAlieno = 0;
bufferpointer->posDisponibileNave = 0;
bufferpointer->nBombeNaveResidue = MAX_BOMBE_NAVE;
bufferpointer->nBombeAlienoResidue = MAX_BOMBE_ALIENO;
Unlock_Signal(mutex);
shmdt(bufferpointer);
int nAlieniRiga = COLS / (dimAlieni + SPAZIO);
pid_t pid;
int status; // conterra' lo stato
crea_proc(0, nAlieniRiga);
switch(fork()){
      case 0:nave();
      break;
      default:controllo();
      break;
      }
SemRemove(empty);
SemRemove(full);
SemRemove(mutex);
SemRemove(mutexBombeNave);
SemRemove(mutexBombeAlieni);

clear();
endwin();
wait(&status);
exit(0);
}
Linux Slackware 10.2 - Kernel 2.16
caralu
Newbie
 
Post: 8
Iscritto il: 07/07/06 17:05

Sponsor
 

Torna a Programmazione


Topic correlati a "[C] problemi gioco space invaders SYSTEM V -urgente!!!!":


Chi c’è in linea

Visitano il forum: Nessuno e 24 ospiti