Микроигра с использованием вилок

#c #process #fork

Вопрос:

У меня проблема с программой, которая использует вилки. Я должен сыграть в простую игру, в которой у меня есть 2 космических корабля, один из которых управляется пользователем (только вверх и вниз), а другой-компьютером (который подпрыгивает каждый раз, когда касается края). Каждый космический корабль должен управляться другим процессом. В дополнение к кораблям должна быть возможность стрелять (пуля управляется другим процессом). Я все понял, единственная проблема в том, что я не понимаю, почему космический корабль, управляемый пользователем, не стреляет, может кто-нибудь сказать мне, где я ошибаюсь?

 #include lt;stdio.hgt; #include lt;curses.hgt; #include lt;stdlib.hgt; #include lt;unistd.hgt;  #define SHOOT 32 /*Sparare */ #define UP 65 /* Cursore sopra */ #define DW 66 /* Cursore sotto */ #define MAXX 80 /* Dimensione dello schermo di output (colonne) */ #define MAXY 20 /* Dimensione dello schermo di output (righe) */ #define DELAY 80000 /* Ritardo nel movimento delle vespe (da adattare) */  /* Prototipi funzioni adoperate */ void Enemy(int pipeout); void Spaceship(int pipeout); void Area(int pipein); void Proiettile(int pipeout, int x, int y);   /* Struttura adoperata per veicolare le coordinate */ struct position {  char c; /* Identificatore dell'entità che invia i dati */  int x; /* Coordinata X */  int y; /* Coordinata Y */ };   /* ----------------------------------------------------------------------  Funzione principale del programma  ---------------------------------------------------------------------- */ int main() { int p[2]; /* Descrittori pipe */ int pidN; /* Pid 'Enemy' */ int pidA; /* Pid 'Spaceship' */  initscr(); /* Inizializza schermo di output */ noecho(); /* Imposta modalità della tastiera */ curs_set(0); /* Nasconde il cursore */ pipe(p); /* Creazione pipe */   /* Creo il primo processo figlio 'Enemy' */  pidN = fork();     /* Se il pid == 0 -gt; si tratta del processo 'Enemy' */  if(pidN==0) {   /* ed eseguo quindi la relativa funzione di gestione */  close(p[0]); /* chiusura del descrittore di lettura */  Enemy(p[1]); /* invocazione funzione nemico */   }   else {   /* Altrimenti sono ancora nel processo padre e creo il processo 'Spaceship' */  pidA=fork();    /* Se il pid == 0 -gt; si tratta del processo 'Spaceship' */  if(pidA==0) {    /* Visualizzo L'Spaceship nella posizione iniziale */  mvprintw(MAXY/2,0,"#");   /* ed eseguo quindi la relativa funzione di gestione */  close(p[0]); /* chiusura del descrittore di lettura */  Spaceship(p[1]); /* invocazione funzione astronave */   }  else {  /* Sono ancora nel processo padre */  close(p[1]); /* chiusura del descrittore di scrittura */  Area(p[0]); /* invocazione funzione area */   }  }   /* Termino i processi Spaceship e Enemy */  kill(pidN,1);   kill(pidA,1);    /* Ripristino la modalità di funzionamento usuale */  endwin();    /* Termino il gioco ed esco dal programma */  printf("nnnGAME OVERnnn");    return 0;  }   /* ----------------------------------------------------------------------  Funzione 'Enemy' ----------------------------------------------------------------------  */ void Enemy(int pipeout) { struct position enemy; //int deltax; /* Spostamento orizzontale */ int deltay=1; /* Spostamento verticale */   enemy.x = MAXX; /* Coordinata X iniziale */  enemy.y = MAXY/2; /* Coordinata Y iniziale */  enemy.c ='


Комментарии:

1. Чтобы было ясно, вы говорите, что космический корабль игрока правильно реагирует на команды вверх / вниз, но не на команды стрельбы, верно?

Ответ №1:

Это выглядит ужасно подозрительно:

 close(pipeout); /* chiusura del descrittore di lettura */  Proiettile(pipeout,apos.x,apos.y); /* invocazione funzione proiettile */  

Разветвленный дочерний элемент закрывает файловый дескриптор pipeout , но затем передает его функции Proiettile() , которая пытается взаимодействовать с другими процессами путем записи в него. Мне непонятно, почему вы закрываете FD, но эта комбинация, очевидно, не будет работать для запущенного процесса Proiettile() , чтобы что-либо сообщить.

Я отмечаю, что если бы вы правильно проверяли возвращаемые значения ваших системных вызовов, особенно ваших write() вызовов, то ваша программа могла бы рассказать вам о самой проблеме. Кроме того, здесь есть и другие проблемы, связанные с (отсутствием) протокола, с помощью которого взаимодействуют ваши различные процессы, и риском торпедирования частичной записью и чтением, но это не то, о чем вы спрашивали.

Комментарии:

1. OMG Большое вам спасибо, я не знаю, как я этого не заметил :/ Что вы имеете в виду под отсутствием протокола?

2. @Zeld, похоже, по каналу передаются сообщения нескольких форматов. Как же тогда получателю узнать, что он получил? Как узнать даже о том, что он получил целое сообщение в первую очередь, а не больше или меньше? Если ваши данные не являются намного более однородными, чем кажутся, вам потребуется структурировать данные, передаваемые по каналу, в соответствии с протоколом, который передает эти данные, а возможно, и другие.

; /* Carattere identificativo */ /* Comunico le coordinate iniziali al processo padre */ write(pipeout,amp;enemy,sizeof(enemy)); while(1){ /* Se supero area Y schermo inverto il movimento */ if(enemy.y deltay lt; 1 || enemy.y deltay gt; MAXY){ deltay = -deltay; } /* Movimento Y */ enemy.y = deltay; /* Comunico le coordinate correnti al processo padre */ write(pipeout,amp;enemy,sizeof(enemy)); /* Inserisco una pausa per rallentare il movimento */ usleep(DELAY); } } /* ---------------------------------------------------------------------- Funzione 'Spaceship' - Movimento tramite i tasti cursore ---------------------------------------------------------------------- */ void Spaceship(int pipeout) { struct position apos; int p[2]; apos.x = 0; /* Coordinata X iniziale */ apos.y = MAXY/2; /* Coordinata Y iniziale */ apos.c='#'; /* Carattere identificativo astronave*/ int pidP; /* Comunico al processo padre le coordinate iniziali dell'astronave */ write(pipeout,amp;apos,sizeof(apos)); /* Lettura dei tasti cursore */ while(1) { char c; c = getch(); if (c==UP amp;amp; apos.y gt; 0){ apos.y-=1; } if(c==DW amp;amp; apos.y lt; MAXY - 1){ apos.y =1; } if(c==SHOOT) { pidP = fork(); if(pidP==0) { flash(); mvprintw(apos.y 1,apos.x,"-"); refresh(); /* ed eseguo quindi la relativa funzione di gestione */ close(pipeout); /* chiusura del descrittore di lettura */ Proiettile(pipeout,apos.x,apos.y); /* invocazione funzione proiettile */ } } /* Comunico al processo padre le coordinate dell'astronave */ write(pipeout,amp;apos,sizeof(apos)); } kill(pidP,1); } /* ---------------------------------------------------------------------- Funzione relativa al processo di visualizzazione e controllo ---------------------------------------------------------------------- */ void Area(int pipein) { struct position enemy, spaceship, dato_letto, proiettile; int collision=0; do { // Leggo dalla pipe / read(pipein,amp;dato_letto,sizeof(dato_letto)); switch((char) dato_letto.c){ case '

Комментарии:

1. Чтобы было ясно, вы говорите, что космический корабль игрока правильно реагирует на команды вверх / вниз, но не на команды стрельбы, верно?

Ответ №1:

Это выглядит ужасно подозрительно:


Разветвленный дочерний элемент закрывает файловый дескриптор pipeout , но затем передает его функции Proiettile() , которая пытается взаимодействовать с другими процессами путем записи в него. Мне непонятно, почему вы закрываете FD, но эта комбинация, очевидно, не будет работать для запущенного процесса Proiettile() , чтобы что-либо сообщить.

Я отмечаю, что если бы вы правильно проверяли возвращаемые значения ваших системных вызовов, особенно ваших write() вызовов, то ваша программа могла бы рассказать вам о самой проблеме. Кроме того, здесь есть и другие проблемы, связанные с (отсутствием) протокола, с помощью которого взаимодействуют ваши различные процессы, и риском торпедирования частичной записью и чтением, но это не то, о чем вы спрашивали.

Комментарии:

1. OMG Большое вам спасибо, я не знаю, как я этого не заметил :/ Что вы имеете в виду под отсутствием протокола?

2. @Zeld, похоже, по каналу передаются сообщения нескольких форматов. Как же тогда получателю узнать, что он получил? Как узнать даже о том, что он получил целое сообщение в первую очередь, а не больше или меньше? Если ваши данные не являются намного более однородными, чем кажутся, вам потребуется структурировать данные, передаваемые по каналу, в соответствии с протоколом, который передает эти данные, а возможно, и другие.

: // Enemy / // Cancello il precedente carattere visualizzato / mvaddch(enemy.y,enemy.x,' '); // Aggiorno le coordinate relative alla nuova posizione / enemy=dato_letto; break; case '#' : // Spaceship / // Cancello il precedente carattere visualizzato / mvaddch(spaceship.y,spaceship.x,' '); // Aggiorno le coordinate relative alla nuova posizione / spaceship=dato_letto; break; case '-' : // Proiettile/ // Cancello il precedente carattere visualizzato / mvaddch(proiettile.y,proiettile.x,' '); // Aggiorno le coordinate relative alla nuova posizione / proiettile=dato_letto; break; } //if(enemy.x != 1 || enemy.y !=0 ) mvaddch(dato_letto.y,dato_letto.x,dato_letto.c); refresh(); /* Il ciclo si ripete finchè le vite del contadino terminano */ } while(!collision); } void Proiettile(int pipeout,int x, int y) { struct position proiettile; int pidP=getpid(); int deltax=1; proiettile.x = x; /* Coordinata X iniziale */ proiettile.y = y; /* Coordinata Y iniziale */ proiettile.c='-'; write(pipeout,amp;proiettile,sizeof(proiettile)); while(1){ /* Se supero area X schermo inverte il movimento */ if(proiettile.x deltax gt; MAXX){ //CHIUDI PROCESSO kill(pidP,1); } /* Movimento X */ proiettile.x = deltax; /* Comunico le coordinate correnti al processo padre */ write(pipeout,amp;proiettile,sizeof(proiettile)); /* Inserisco una pausa per rallentare il movimento */ usleep(DELAY); } }

Комментарии:

1. Чтобы было ясно, вы говорите, что космический корабль игрока правильно реагирует на команды вверх / вниз, но не на команды стрельбы, верно?

Ответ №1:

Это выглядит ужасно подозрительно:


Разветвленный дочерний элемент закрывает файловый дескриптор pipeout , но затем передает его функции Proiettile() , которая пытается взаимодействовать с другими процессами путем записи в него. Мне непонятно, почему вы закрываете FD, но эта комбинация, очевидно, не будет работать для запущенного процесса Proiettile() , чтобы что-либо сообщить.

Я отмечаю, что если бы вы правильно проверяли возвращаемые значения ваших системных вызовов, особенно ваших write() вызовов, то ваша программа могла бы рассказать вам о самой проблеме. Кроме того, здесь есть и другие проблемы, связанные с (отсутствием) протокола, с помощью которого взаимодействуют ваши различные процессы, и риском торпедирования частичной записью и чтением, но это не то, о чем вы спрашивали.

Комментарии:

1. OMG Большое вам спасибо, я не знаю, как я этого не заметил :/ Что вы имеете в виду под отсутствием протокола?

2. @Zeld, похоже, по каналу передаются сообщения нескольких форматов. Как же тогда получателю узнать, что он получил? Как узнать даже о том, что он получил целое сообщение в первую очередь, а не больше или меньше? Если ваши данные не являются намного более однородными, чем кажутся, вам потребуется структурировать данные, передаваемые по каналу, в соответствии с протоколом, который передает эти данные, а возможно, и другие.