Salve ragazzi!
Sto implementando 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 con relativi thread, che accedono ad un buffer condiviso (protetto da semafori), basandomi sulle librerie lpthread e lncurses.
Riesco a creare correttamente i processi (e i thread) ma non riesco a fare altrettanto correttamente in fase di visualizzazione,gli alieni vengono sovrapposti su un'unica casella, così da sembrare che ve ne fosse solo uno, e non riesco a capirne il motivo. Per ora cerco di fare stampare solo gli alieni, in seguito implementerò le bombe e la nave del personaggio principale.
Qualcuno può darmi una mano? Vi allego il codice:
codice:
#include <stdio.h>
#include <curses.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define NUM_MAX_RIGHE 5
#define SINISTRA 68
#define DESTRA 67
#define N_INIZIALE_ALIENI 4
#define SPAZIO 1
#define SPAZIO_RIGHE 1
#define PASSO_X 2
#define PASSO_Y 1
#define MAX_BOMBE_NAVE 1
#define DIM_BUFFER N_INIZIALE_ALIENI
struct pos {
char *c;
int x;
int y;
int xPrec;
int yPrec;
int index;
int id;
};
struct pos alieni[N_INIZIALE_ALIENI];
int info_elementi[DIM_BUFFER];
void *alieno(void *);
void *controllo(void *);
pthread_t array_alieni[N_INIZIALE_ALIENI];
pthread_mutex_t semaforo = PTHREAD_MUTEX_INITIALIZER;
sem_t vuoto, pieno;
int dimAlieni, bufferScrittura, bufferLettura, counter;
int main() {
int i = 0, j = 1, k, nAlieniRiga;
pthread_t nave;
pthread_t bombaNave[MAX_BOMBE_NAVE];
pthread_t bombaAlieno[N_INIZIALE_ALIENI];
initscr();
noecho();
curs_set(0);
bufferScrittura = 0;
bufferLettura = 0;
counter = 0;
dimAlieni = 1;
nAlieniRiga = 20 / (dimAlieni + SPAZIO); //20 è inteso come numero COLS (pechè non abbiamo inizializzato le variabili di ncurses
sem_init(&vuoto, 0, DIM_BUFFER);
sem_init(&pieno, 0, 0);
for (k = 0; k < N_INIZIALE_ALIENI; k++){
//struct pos pos_alieno;
i = k % nAlieniRiga;
j = (k / nAlieniRiga) + 1;
alieni[k].x = i * (SPAZIO + 1);
alieni[k].y = j * (SPAZIO_RIGHE + 1);
alieni[k].c = "#";
alieni[k].index = k;
pthread_create(&array_alieni[k], NULL, &alieno, &alieni[k]);
}
controllo(NULL);
getchar();
endwin();
exit(0);
}
void *alieno(void *args)
{
struct pos pos_alieno = *(struct pos*) args;
pos_alieno.id = pthread_self();
int dir = 1, dx, dy;
srand(pos_alieno.id);
while(1)
{
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;
//sleep(rand() % 2); non funziona
sem_wait(&vuoto); //Segnala che è stata scritta un altra posizione nel buffer
pthread_mutex_lock(&semaforo); //equivale ad una wait su valore 1, che poi viene reincrementata dall'unlock che gli ri da valore 1
info_elementi[bufferScrittura] = pos_alieno.index;
bufferScrittura = (bufferScrittura + 1) % DIM_BUFFER;
//printf("Buffer Scrittura %d\n", bufferScrittura); //facevo un po di debug!
alieni[pos_alieno.index] = pos_alieno;
pthread_mutex_unlock(&semaforo);
sem_post(&pieno); //Segnala che c'è una posizione in più da leggere nel buffer
sleep(1);
}
}
void *controllo(void *args)
{
struct pos valore_letto;
int index, i = 0;
do {
//sleep(rand() % 2); non funziona nemmeno così
sem_wait(&pieno); //Segnala che è stata letta una posizione dal buffer
pthread_mutex_lock(&semaforo);
index = info_elementi[bufferLettura];
bufferLettura = (bufferLettura + 1) % DIM_BUFFER;
valore_letto = alieni[index];
pthread_mutex_unlock(&semaforo);
sem_post(&vuoto);
move(valore_letto.yPrec, valore_letto.xPrec);
printw(" "); //printw
move(valore_letto.y, valore_letto.x);
printw("%s",valore_letto.c);
move(index, 0);
//printw("%d",i); tutto questo è debug
//printw("Valore letto x: %d, Valore letto y: %d, Numero alieno %d,\n", valore_letto.x, valore_letto.y, valore_letto.index);
//move(0,15);
//printw("\tlivello %d",livello);
//move(0,27);
//printw("\tvite %d",nave_vita);
refresh();
i++;
}
while (true);
}
P.S. Compilare con le opzioni -lpthread & -lncurses, es:
gcc -o alieni alienThread.c -lncurses -lpthread