Visualizzazione dei risultati da 1 a 2 su 2

Discussione: problemi con thread

  1. #1

    problemi con thread

    questo è il codice del progetto che sarebbe una versione semplificata di space invaders con l utilizzo dei thread e dei semafori per la sincronizzazione. il problema(a parte la schermata disturbata) è che non mi visualizza mai tutti i nemici e dunque il gioco funziona male! poi oltretutto i nemici a volte spariscono riappaiono e si muovono in modo strano.

    da compilare con le opzioni -lpthread , -lncurses

    #include <stdio.h>
    #include <curses.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <time.h>
    #include <string.h>
    #include<pthread.h>
    #include<semaphore.h>


    /* Codice dei tasti da utilizzare per il gioco*/
    #define SINISTRA 68
    #define DESTRA 67
    #define SPARA 32

    /* Dimensione dello schermo */
    #define MAXX 80
    #define MAXY 24

    #define DIM_BUFFER 1000000

    #define PASSO 1
    //Numero di nemici da creare
    #define NEMICI 1

    /*Numero massimo di missili che si possono lanciare prima che i precedenti siano scomparsi dallo schermo
    Deve essere multiplo di 2 perché ne vengono sparati 2 per volta*/
    #define MAX_MISSILI 10000

    /* Codice da associare ai vari oggetti da mostrare. Devono essere tutti diversi perché
    * servono a indicare al controllo da chi arrivano i messaggi
    */
    #define TIPO_ASTRONAVE 0
    #define TIPO_NEMICO 1
    #define TIPO_MISSILE 2
    #define TIPO_BOMBA 3



    typedef struct pos{
    int tipo;
    int numero;
    int x;
    int y;
    int passo;
    } posizione;


    void * astronave(void * arg);
    void * missile(void * arg);
    void * nemico(void * arg);
    void * nemico2(void * arg);
    void * nemico3(void * arg);
    void * bomba(void * arg);
    void * controllo(void * arg);

    posizione buffer[DIM_BUFFER]; // buffer condiviso
    int inserisci = 0; // variabile che indica le posizioni occupate nel buffer
    int preleva = 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

    int flag_tr[NEMICI], flag_su[NEMICI], flag_muori[NEMICI];
    int flag_tr2[NEMICI], flag_su2[NEMICI], flag_muori2[NEMICI];
    int flag_tr3[NEMICI], flag_su3[NEMICI], flag_muori3[NEMICI];

    pthread_t astronave_id, nemico_id[NEMICI], controllo_id;

    int main(){

    initscr();
    noecho();
    curs_set(0);

    sem_init(&disponibili, 0, DIM_BUFFER); // inizializzazione semaforo disponibili
    sem_init(&presenti, 0, 0); // inizializzazione semaforo presenti

    int nemici_counter=0, n;
    for(n=0;n<NEMICI;n++){//inizializzazione flag comunicazione controllo
    flag_tr[n]=0;
    flag_su[n]=0;
    flag_muori[n]=0;
    flag_tr2[n]=0;
    flag_su2[n]=0;
    flag_muori2[n]=0;
    flag_tr3[n]=0;
    flag_su3[n]=0;
    flag_muori3[n]=0;
    }


    pthread_create(&astronave_id, NULL, &astronave, NULL);
    while(nemici_counter<NEMICI){
    if (pthread_create(&nemico_id[nemici_counter], NULL, &nemico, &nemici_counter)!=0){
    perror("Errore!");
    }else
    nemici_counter++;
    }

    pthread_create(&controllo_id, NULL, &controllo, NULL);

    pthread_join(controllo_id, NULL);

    getchar();


    endwin();
    return 0;

    }

    void * controllo(void * arg){


    /*Strutture in cui salvare le posizioni degli oggetti da mostrare*/
    posizione valore_letto, astronave;
    posizione nemici[NEMICI];
    posizione bombe[NEMICI];
    posizione missili[MAX_MISSILI];
    pthread_t nemico2_id[NEMICI], nemico3_id[NEMICI];

    /* Array di flag per lo stato dei missili. Il flag corrispondente a un missile vale 1 se ha colpito un nemico */
    int missile_colpito[MAX_MISSILI];

    // cont_nem com_nem; //Struttura per inviare messaggi ai nemici

    char sch_astronave[4][6] = { //Disegno dell'astronave. Dimensione max: 6x6
    {' ', ' ', ' ', 'A', ' ', ' '},
    {' ', ' ', '[', 'O', ']', ' '},
    {' ', '[', 'O', 'O', ']', ' '},
    {'[', 'O', 'O', 'O', 'O', ']'},
    };
    int a_astronave = 4; //Altezza dell'astronave in caratteri
    int l_astronave = 6; //Lunghezza dell'astronave in caratteri


    int livello_nemici[NEMICI]; //Fase di vita dei nemici 0: Morto, 1: Primo livello, 2: Secondo livello
    int nemici_colpiti[NEMICI], nemici1l_colpiti[NEMICI]; //Array di flag che indicano che il nemico n-simo è appena stato colpito da un missile
    int nemici2l_colpiti[NEMICI], nemici3l_colpiti[NEMICI]; //Numero di colpi ricevuti da ciascuna navicella di secondo livello
    int len_nem_1 = 3; //Caratteri occupati dal nemico nella sua prima fase
    int len_nem_2 = 3; //Caratteri occupati dal nemico nella sua seconda fase
    int len_nem_3=3;

    int nemici_distrutti = 0; //Tiene il conto dei nemici distrutti. Quando è uguale a max_nemici il giocatore ha vinto

    int game_over = 0; //0: Gioco in corso, 1: Perso, 2: Vinto

    int i, j, k; //Contatori vari;

    //Inizializzazione delle strutture per memorizzare lo stato del gioco
    for(i = 0; i < NEMICI; i++){
    nemici[i].x = -1;
    nemici[i].y = -1;
    bombe[i].x = -1;
    bombe[i].y = -1;
    livello_nemici[i] = 1;
    nemici_colpiti[i] = 0;
    nemici1l_colpiti[i]=0;
    nemici2l_colpiti[i] = 0;
    nemici3l_colpiti[i]=0;
    }
    for(i = 0; i < MAX_MISSILI; i++){
    missili[i].x = -1;
    missili[i].y = -1;
    missile_colpito[i] = 0;
    }
    astronave.x = -1;
    astronave.y = -1;

    do{


    sem_wait(&presenti);
    pthread_mutex_lock(&mutex);
    valore_letto = buffer[preleva];
    preleva=(preleva+1)%DIM_BUFFER;
    sem_post(&disponibili); // incrementa il semaforo
    pthread_mutex_unlock(&mutex);


    /* CONTROLLO ASTRONAVE */
    if (valore_letto.tipo == TIPO_ASTRONAVE){
    /* Cancellazione dell'astronave nella posizione precedente */
    if (astronave.x >= 0)
    for (i = 0; i < a_astronave; i++)
    for (j = 0; j < l_astronave; j++)
    if(sch_astronave[i][j] != ' ')
    mvaddch(astronave.y + i, astronave.x + j, ' ');
    astronave = valore_letto;
    /* Disegno dell'astronave e controllo di eventuali collisioni con bombe lanciate dai nemici*/
    for (i = 0; i < a_astronave; i++)
    for (j = 0; j < l_astronave; j++)
    if(sch_astronave[i][j] != ' '){
    mvaddch(valore_letto.y + i, valore_letto.x + j, sch_astronave[i][j]);
    for (k = 0; !game_over && k < NEMICI; k++)
    if (bombe[k].y != -1 && valore_letto.y + i == bombe[k].y && valore_letto.x + j == bombe[k].x)
    game_over = 1;
    }
    }
    /* FINE CONTROLLO ASTRONAVE */

    /* CONTROLLO MISSILI */
    if (valore_letto.tipo == TIPO_MISSILE){
    if(missili[valore_letto.numero].x >= 0)
    /* Cancellazione del missile nella posizione precedente */
    mvaddch(missili[valore_letto.numero].y, missili[valore_letto.numero].x, ' ');

    missili[valore_letto.numero] = valore_letto;
    /* Controlla se ha colpito un nemico
    * Se il missile aveva già colpito un nemico, il processo associato è ancora attivo, per cui sta ancora generando
    * le coordinate, ma affinché il comportamento sia realistico ci si aspetta che non oltrepassi il nemico
    * che ha colpito e quindi viene ignorato.
    */
    for (i = 0; !missile_colpito[valore_letto.numero] && i < NEMICI; i++){
    /// Se nemico di primo livello Se nemico di primo livello
    if (livello_nemici[i] == 1 && valore_letto.y == nemici[i].y){
    /* Il missile occupa un carattere, ma il nemico no, quindi si confrontano le coordinate del missile con tutta la lunghezza del nemico */
    //for(j=0;!missile_colpito[valore_letto.numero]&&j<max_nemici;j++){
    if (nemici1l_colpiti[i] < 2){
    /* k rappresenta l'offset per controllare se il missile si trova all'interno della navicella */
    for (k = 0; !missile_colpito[valore_letto.numero] && k < len_nem_1; k++)
    if (valore_letto.x == nemici[i].x + k){
    missile_colpito[valore_letto.numero] = 1;
    nemici1l_colpiti[i]++;
    nemici_colpiti[i] = 1;
    }
    /* Se una navicella è stata colpita dal missile, la cancella */
    if (missile_colpito[valore_letto.numero])
    for(k = 0; k < len_nem_1; k++)
    mvaddch(nemici[i].y, nemici[i].x+ k, ' ');
    }/// fine se minore di due
    }/// Fine if se primo livello

    /// se di secondo livello
    if (livello_nemici[i] == 2 && valore_letto.y == nemici[i].y){
    if (nemici2l_colpiti[i] < 3){
    /* k rappresenta l'offset per controllare se il missile si trova all'interno della navicella */
    for (k = 0; !missile_colpito[valore_letto.numero] && k < len_nem_2; k++)
    if (valore_letto.x == nemici[i].x + k){
    missile_colpito[valore_letto.numero] = 1;
    nemici2l_colpiti[i]++;
    nemici_colpiti[i] = 1;
    }
    /* Se una navicella è stata colpita dal missile, la cancella */
    if (missile_colpito[valore_letto.numero])
    for(k = 0; k < len_nem_1; k++)
    mvaddch(nemici[i].y, nemici[i].x+ k, ' ');
    }/// fine se minore di due
    }/// Fine if se secondo livello


    //}/**
    /** Se il nemico è di terzo livello controlla subito che siano sulla stessa riga */
    if (livello_nemici[i] == 3 && valore_letto.y == nemici[i].y){

    /* Prima controlla che la navicella non sia già stata distrutta */
    if (nemici3l_colpiti[i] < 4){
    /* k rappresenta l'offset per controllare se il missile si trova all'interno della navicella */
    for (k = 0; !missile_colpito[valore_letto.numero] && k < len_nem_3; k++)
    if (valore_letto.x == nemici[i].x + k){
    missile_colpito[valore_letto.numero] = 1;
    nemici3l_colpiti[i]++;
    nemici_colpiti[i] = 1;
    }
    /* Se una navicella è stata colpita dal missile, la cancella */
    if (missile_colpito[valore_letto.numero])
    for(k = 0; k < len_nem_2; k++)
    mvaddch(nemici[i].y, nemici[i].x+ k, ' ');
    }

    }/// fine se livello tre
    }/// fine for (i = 0; !missile_colpito[valore_letto.numero] && i < max_nemici; i++){
    /* Disegno del missile */
    if (!missile_colpito[valore_letto.numero]) //Non lo disegna se ha già colpito un nemico
    mvaddch(valore_letto.y, valore_letto.x, '^');
    else
    if (valore_letto.y <= 0 || valore_letto.x >= MAXX || valore_letto.x <= 0)
    /* A questo punto, il missile che ha colpito un nemico ha finito la sua corsa ideale verso la fine dello schermo.
    * Il suo stato viene ripristinato affinché il prissimo missile con lo stesso numero funzioni.*/
    missile_colpito[valore_letto.numero] = 0;
    }
    /* FINE CONTROLLO MISSILI */

    /* CONTROLLO NEMICI */
    if (valore_letto.tipo == TIPO_NEMICO){
    //cont nem bla bla

    /* Non deve disegnarlo se è morto */
    int disegna = (livello_nemici[valore_letto.numero] != 0);

    if ((livello_nemici[valore_letto.numero] == 1 && nemici_colpiti[valore_letto.numero])){
    if(nemici1l_colpiti[valore_letto.numero]==2){
    flag_muori[valore_letto.numero]=1;
    pthread_create(&nemico2_id[valore_letto.numero], NULL, &nemico2, &valore_letto.numero);
    livello_nemici[valore_letto.numero] = 2; /* Il nemico entra nella seconda fase */
    disegna = 0;
    nemici_colpiti[valore_letto.numero] = 0; /* Reimposta il flag perché serve ad avvertire che almeno una navicella del gruppo è stata colpita */
    }
    }

    if ((livello_nemici[valore_letto.numero] == 2 && nemici_colpiti[valore_letto.numero])){
    if(nemici2l_colpiti[valore_letto.numero]==3){
    flag_muori2[valore_letto.numero]=1;
    pthread_create(&nemico3_id[valore_letto.numero], NULL, &nemico3, &valore_letto.numero);
    livello_nemici[valore_letto.numero] = 3; /* Il nemico entra nella terza fase */
    disegna = 0;
    nemici_colpiti[valore_letto.numero] = 0; /* Reimposta il flag perché serve ad avvertire che almeno una navicella del gruppo è stata colpita */
    }
    }
    /* Controlla se il nemico è stato colpito da un missile. Caso del nemico di terzo livello */
    if ((livello_nemici[valore_letto.numero] == 3 && nemici_colpiti[valore_letto.numero])){
    if(nemici3l_colpiti[valore_letto.numero]==4){
    flag_muori3[valore_letto.numero]=1;
    livello_nemici[valore_letto.numero] = 0; /* Il nemico entra nella terza fase */
    disegna = 0;
    nemici_colpiti[valore_letto.numero] = 0; /* Reimposta il flag perché serve ad avvertire che almeno una navicella del gruppo è stata colpita */
    nemici_distrutti++;
    }
    }/// fineeeee if livello tre

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,472

    Moderazione

    Originariamente inviato da crisponz
    questo è il codice del progetto che sarebbe una versione semplificata di space invaders
    Tralasciando il fatto che non hai specificato il linguaggio nel titolo, come da Regolamento, noi cosa dovremmo farci? Prendere tutto il codice che hai riportato e testarlo? E chi ha scritto quel codice?

    Se hai problemi specifici con un pezzo di codice, tenta di risolverli e, in caso di difficoltà, specifica quali sono questi problemi, dove non riesci a intervenire e perché.

    Leggi il Regolamento e apri un thread in linea con le indicazioni riportate.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

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 © 2025 vBulletin Solutions, Inc. All rights reserved.