因为我的先前的帖子被标记为离题、过于模糊并要求意见和推荐有用的代码,所以我将其重新发布为我正在处理的代码问题的问题。感谢前一篇文章中的人们,通过回顾你们说的话,我能够从中拼凑出我现在的代码。
重点是父/子关系及使用fork()和pipe()来实现所需效果。
该项目是一个POSIX纸牌游戏,其中父进程(荷官)分叉成5个子进程(玩家),每个子进程都有自己从父进程读取和写入的管道。直到一个玩家有3张相同的牌(不抛弃),父程序发牌给玩家(每个玩家至少发5张牌)。获胜的孩子发送获胜的手牌和EOF(退出(0))至父进程以表明获胜。这会触发父进程打印获胜的玩家并向剩余的孩子发送EOF以关闭它们(退出(1))。之后,父进程关闭。如果父进程没有赢家到达牌堆底部,则向孩子发送EOF,等待它们退出(1)...然后关闭。
我主要的问题是子进程如何单个读取每张牌,而不是一次又一次地从管道中读取相同的值。我认为我缺少一种方法来同步父进程写入管道和子进程从管道中读取。
我完全是新手,所以任何帮助都非常感谢。非常感谢。
代码已更新:(编译存在许多问题) 完整且编译,但很明显我在管道和通过它们中继数据方面遇到了麻烦。从失败玩游戏,无法从管道读取或写入数据,到留下僵尸进程,这里有很多问题。我很感激任何关于我的混乱的输入。笑一笑。
这是当我运行程序(play.c)时的输出:
os@debian:~/Documents/cpsc351/projects/assn2$ gcc -o play play.c
os@debian:~/Documents/cpsc351/projects/assn2$ ./play
Pipe Success...toChild 1 created.
Pipe Success...toParent 1 created.
Pipe Success...toChild 2 created.
Pipe Success...toParent 2 created.
Pipe Success...toChild 3 created.
Pipe Success...toParent 3 created.
Pipe Success...toChild 4 created.
Pipe Success...toParent 4 created.
Pipe Success...toChild 5 created.
Pipe Success...toParent 5 created.
Parent: All players are at the table. Dealing cards...
30 5C to player 1
51 KS to player 2
9 10H to player 3
25 KD to player 4
6 7H to player 5
18 6D to player 1
45 7S to player 2
29 4C to player 3
37 QC to player 4
12 KH to player 5
7 8H to player 1
19 7D to player 2
20 8D to player 3
49 JS to player 4
35 10C to player 5
15 3D to player 1
5 6H to player 2
36 JC to player 3
0 AH to player 4
22 10D to player 5
48 10S to player 1
27 2C to player 2
42 4S to player 3
16 4D to player 4
32 7C to player 5
4 5H to player 1
14 2D to player 2
41 3S to player 3
39 AS to player 4
1 2H to player 5
26 AC to player 1
46 8S to player 2
34 9C to player 3
11 QH to player 4
24 QD to player 5
17 5D to player 1
31 6C to player 2
44 6S to player 3
40 2S to player 4
3 4H to player 5
21 9D to player 1
50 QS to player 2
13 AD to player 3
33 8C to player 4
23 JD to player 5
43 5S to player 1
2 3H to player 2
28 3C to player 3
47 9S to player 4
38 KC to player 5
10 JH to player 1
8 9H to player 2
Child: Fork Success...Player 4 is sitting at the table.
Child: Player 4 is dealt a KD. Hand Total = 1 cards.
Child: Player 4 is dealt a QC. Hand Total = 2 cards.
Child: Player 4 is dealt a JS. Hand Total = 3 cards.
Child: Player 4 is dealt a AH. Hand Total = 4 cards.
Child: Player 4 is dealt a 4D. Hand Total = 5 cards.
Child: Player 4 is dealt a AS. Hand Total = 6 cards.
Child: Player 4 is dealt a QH. Hand Total = 7 cards.
Child: Player 4 is dealt a 2S. Hand Total = 8 cards.
Child: Player 4 is dealt a 8C. Hand Total = 9 cards.
Child: Player 4 is dealt a 9S. Hand Total = 10 cards.
Child: Fork Success...Player 5 is sitting at the table.
Child: Player 5 is dealt a 7H. Hand Total = 1 cards.
Child: Player 5 is dealt a KH. Hand Total = 2 cards.
Child: Player 5 is dealt a 10C. Hand Total = 3 cards.
Child: Player 5 is dealt a 10D. Hand Total = 4 cards.
Child: Player 5 is dealt a 7C. Hand Total = 5 cards.
Child: Player 5 is dealt a 2H. Hand Total = 6 cards.
Child: Player 5 is dealt a QD. Hand Total = 7 cards.
Child: Player 5 is dealt a 4H. Hand Total = 8 cards.
Child: Player 5 is dealt a JD. Hand Total = 9 cards.
Child: Player 5 is dealt a KC. Hand Total = 10 cards.
Child: Player 5 has left the table.
os@debian:~/Documents/cpsc351/projects/assn2$ Child: Player 4 has left the table.
Child: Fork Success...Player 3 is sitting at the table.
Child: Player 3 is dealt a 10H. Hand Total = 1 cards.
Child: Player 3 is dealt a 4C. Hand Total = 2 cards.
Child: Player 3 is dealt a 8D. Hand Total = 3 cards.
Child: Player 3 is dealt a JC. Hand Total = 4 cards.
Child: Player 3 is dealt a 4S. Hand Total = 5 cards.
Child: Player 3 is dealt a 3S. Hand Total = 6 cards.
Child: Player 3 is dealt a 9C. Hand Total = 7 cards.
Child: Player 3 is dealt a 6S. Hand Total = 8 cards.
Child: Player 3 is dealt a AD. Hand Total = 9 cards.
Child: Player 3 is dealt a 3C. Hand Total = 10 cards.
Child: Player 3 has left the table.
Child: Fork Success...Player 2 is sitting at the table.
Child: Player 2 is dealt a KS. Hand Total = 1 cards.
Child: Player 2 is dealt a 7S. Hand Total = 2 cards.
Child: Player 2 is dealt a 7D. Hand Total = 3 cards.
Child: Player 2 is dealt a 6H. Hand Total = 4 cards.
Child: Player 2 is dealt a 2C. Hand Total = 5 cards.
Child: Player 2 is dealt a 2D. Hand Total = 6 cards.
Child: Player 2 is dealt a 8S. Hand Total = 7 cards.
Child: Player 2 is dealt a 6C. Hand Total = 8 cards.
Child: Player 2 is dealt a QS. Hand Total = 9 cards.
Child: Player 2 is dealt a 3H. Hand Total = 10 cards.
Child: Player 2 is dealt a 9H. Hand Total = 11 cards.
Child: Player 2 has left the table.
Child: Fork Success...Player 1 is sitting at the table.
Child: Player 1 is dealt a 5C. Hand Total = 1 cards.
Child: Player 1 is dealt a 6D. Hand Total = 2 cards.
Child: Player 1 is dealt a 8H. Hand Total = 3 cards.
Child: Player 1 is dealt a 3D. Hand Total = 4 cards.
Child: Player 1 is dealt a 10S. Hand Total = 5 cards.
Child: Player 1 is dealt a 5H. Hand Total = 6 cards.
Child: Player 1 is dealt a AC. Hand Total = 7 cards.
Child: Player 1 is dealt a 5D. Hand Total = 8 cards.
Child: Player 1 has at least "3 of a Kind". Hand Total = 8 cards.
当前代码:
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "cards.h"
#include "cards.c"
#define READ 0
#define WRITE 1
#define PLAYERS 5
int main(int argc, char *argv[])
{
//loop declarations ***Would not let me initialize within a for-loop...c99 error.***
int i;
int j;
pid_t player[PLAYERS];
int toChild_pipe[PLAYERS][2];
int toParent_pipe[PLAYERS][2];
int dealt_card;
int card_count = 1;
int player_count = 0;
int status_forChild;
int status_forParent;
int player_card;
for(i = 0; i < PLAYERS; i++)
{
// Create the pipes
if (pipe(toChild_pipe[i]) < 0)
{
perror("'To-Child' Pipe Error\n");
exit(1);
}
if (pipe(toParent_pipe[i]) < 0)
{
perror("'To-Parent' Pipe Error\n");
exit(1);
}
// Fork the child (new player)
player[i] = fork();
if (player[i] < 0)
{
perror("Fork Error:");
printf(" Player %d cloud not sit at table.\n", i+1);
exit(1);
}
else if (player[i] > 0) //Parent Process
{
// Close unsed pipe ends in Parent
close(toChild_pipe[i][READ]);
close(toParent_pipe[i][WRITE]);
}
else //(player[i] == 0)-- Child Process
{
int player_num = (i+1);
int player_card;
int hand[13] = {0};
int player_card_count = 0;
bool game_over = false;
printf("Child: Fork Success...Player %d is sitting at the table.\n", player_num);
// Close unsed pipe ends in Parent
close(toParent_pipe[i][READ]);
close(toChild_pipe[i][WRITE]);
while(!game_over)
{
if ((status_forChild = read(toChild_pipe[i][READ], &player_card, sizeof(player_card))) == 0)
{
//EOF from parent. Player lost.
game_over = true;
close(toParent_pipe[i][WRITE]);
close(toChild_pipe[i][READ]);
printf("Child: Player %d has left the table.\n", player_num);
exit(1);
}
else if (status_forChild == -1)
{
perror("");
printf("Child %d: ERROR: Could not read from pipe.\n", i+1);
exit(1);
}
else
{
//Players have 5 cards, loop through hand to check for winner. If yes, WIN.
if (player_card_count == 5)
{
for (j = 0; j < 13; j++)
{
if(hand[j] >=3)
{
//WINNER! Close process (status = 0)
printf("Child: Player %d has at least. Hand Total = %d cards.\n"
, player_num, rank(player_card));
close(toParent_pipe[i][WRITE]);
close(toChild_pipe[i][READ]);
exit(0);
}
}
}
//Read the current card value dealt, increment card value in hand array
int card_index = value_index(rank(player_card));
hand[card_index]++;
player_card_count++;
printf("Child: Player %d is dealt a %s%s. Hand Total = %d cards.\n", player_num, rank(player_card),
suit(player_card), player_card_count);
if ((hand[card_index] >= 3)&&(player_card_count > 5)) //at least (3 of a kind) and (> 5 card hand)
{
//WINNER! Close process (status = 0)
printf("Child: Player %d has at least. Hand Total = %d cards.\n", player_num, rank(player_card));
close(toParent_pipe[i][WRITE]);
close(toChild_pipe[i][READ]);
exit(0);
}
}
}
}
}
shuffle();
printf("Parent: All players are at the table. Dealing cards... \n");
while ((dealt_card = deal()) != EOF)
{
//Card is written to the pipe for current player
if ((status_forParent = write(toChild_pipe[i][WRITE], &dealt_card, sizeof(dealt_card))) == -1)
{
perror("");
printf("Parent: ERROR: Could not read from pipe for Child %d.\n", i+1);
exit(1);
}
//If child process exited with status = 0, child had 3 of a kind and wins game.
else if (status_forParent == 0)
{
printf("Parent: Player %d has WON!!!\n", player_count+1, rank(player_card));
break;
}
else
{
printf(" %d %s%s to player %d\n", dealt_card, rank(dealt_card), suit(dealt_card), player_count+1);
if (player_count >= PLAYERS-1)
player_count = 0;
else
player_count++;
}
}
// Close pipe ends
close(toParent_pipe[i][READ]);
close(toChild_pipe[i][WRITE]);
wait(NULL);
return 0;
}
select()
来监控所有子进程可以写入的管道,以确定哪个管道已准备好读取。 - Crowmanselect()
,只需循环并等待read()
即可。 - Crowman