使用叉子的微型游戏
Micro game using forks
我对使用分叉的程序有疑问。
我必须做一个简单的游戏,其中我有 2 艘宇宙飞船,一艘由用户控制(仅上下),另一艘由计算机控制(每次触及边缘时都会反弹)。
每艘宇宙飞船都必须由不同的进程控制。
除了船只之外,还必须可以射击(子弹由另一个进程控制)。
我明白了,唯一的问题是我不明白为什么用户控制的飞船不发射,谁能告诉我我哪里错了?
#include <stdio.h>
#include <curses.h>
#include <stdlib.h>
#include <unistd.h>
#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 -> 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 -> 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("\n\n\nGAME OVER\n\n\n");
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 ='$'; /* Carattere identificativo */
/* Comunico le coordinate iniziali al processo padre */
write(pipeout,&enemy,sizeof(enemy));
while(1){
/* Se supero area Y schermo inverto il movimento */
if(enemy.y + deltay < 1 || enemy.y + deltay > MAXY){
deltay = -deltay;
}
/* Movimento Y */
enemy.y += deltay;
/* Comunico le coordinate correnti al processo padre */
write(pipeout,&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,&apos,sizeof(apos));
/* Lettura dei tasti cursore */
while(1)
{
char c;
c = getch();
if (c==UP && apos.y > 0){
apos.y-=1;
}
if(c==DW && apos.y < 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,&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,&dato_letto,sizeof(dato_letto));
switch((char) dato_letto.c){
case '$': // 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,&proiettile,sizeof(proiettile));
while(1){
/* Se supero area X schermo inverte il movimento */
if(proiettile.x + deltax > MAXX){
//CHIUDI PROCESSO
kill(pidP,1);
}
/* Movimento X */
proiettile.x += deltax;
/* Comunico le coordinate correnti al processo padre */
write(pipeout,&proiettile,sizeof(proiettile));
/* Inserisco una pausa per rallentare il movimento */
usleep(DELAY);
}
}
这看起来非常可疑:
close(pipeout); /* chiusura del descrittore di lettura */
Proiettile(pipeout,apos.x,apos.y); /* invocazione funzione proiettile */
分叉的子进程关闭文件描述符 pipeout
,但随后将其传递给函数 Proiettile()
,该函数尝试通过写入它来与其他进程通信。我不清楚你为什么要关闭 FD,但这种组合显然不适用于进程 运行 Proiettile()
来传达任何信息。
我注意到,如果您正确地检查了系统调用的 return 值,尤其是 write()
调用,那么您的程序可能会告诉您问题本身。此外,这里还有其他问题围绕(缺乏)您的各种进程进行通信的协议,以及被部分写入和读取鱼雷攻击的风险,但这些不是您所问的。
我对使用分叉的程序有疑问。 我必须做一个简单的游戏,其中我有 2 艘宇宙飞船,一艘由用户控制(仅上下),另一艘由计算机控制(每次触及边缘时都会反弹)。 每艘宇宙飞船都必须由不同的进程控制。 除了船只之外,还必须可以射击(子弹由另一个进程控制)。 我明白了,唯一的问题是我不明白为什么用户控制的飞船不发射,谁能告诉我我哪里错了?
#include <stdio.h>
#include <curses.h>
#include <stdlib.h>
#include <unistd.h>
#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 -> 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 -> 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("\n\n\nGAME OVER\n\n\n");
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 ='$'; /* Carattere identificativo */
/* Comunico le coordinate iniziali al processo padre */
write(pipeout,&enemy,sizeof(enemy));
while(1){
/* Se supero area Y schermo inverto il movimento */
if(enemy.y + deltay < 1 || enemy.y + deltay > MAXY){
deltay = -deltay;
}
/* Movimento Y */
enemy.y += deltay;
/* Comunico le coordinate correnti al processo padre */
write(pipeout,&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,&apos,sizeof(apos));
/* Lettura dei tasti cursore */
while(1)
{
char c;
c = getch();
if (c==UP && apos.y > 0){
apos.y-=1;
}
if(c==DW && apos.y < 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,&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,&dato_letto,sizeof(dato_letto));
switch((char) dato_letto.c){
case '$': // 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,&proiettile,sizeof(proiettile));
while(1){
/* Se supero area X schermo inverte il movimento */
if(proiettile.x + deltax > MAXX){
//CHIUDI PROCESSO
kill(pidP,1);
}
/* Movimento X */
proiettile.x += deltax;
/* Comunico le coordinate correnti al processo padre */
write(pipeout,&proiettile,sizeof(proiettile));
/* Inserisco una pausa per rallentare il movimento */
usleep(DELAY);
}
}
这看起来非常可疑:
close(pipeout); /* chiusura del descrittore di lettura */ Proiettile(pipeout,apos.x,apos.y); /* invocazione funzione proiettile */
分叉的子进程关闭文件描述符 pipeout
,但随后将其传递给函数 Proiettile()
,该函数尝试通过写入它来与其他进程通信。我不清楚你为什么要关闭 FD,但这种组合显然不适用于进程 运行 Proiettile()
来传达任何信息。
我注意到,如果您正确地检查了系统调用的 return 值,尤其是 write()
调用,那么您的程序可能会告诉您问题本身。此外,这里还有其他问题围绕(缺乏)您的各种进程进行通信的协议,以及被部分写入和读取鱼雷攻击的风险,但这些不是您所问的。