So, my PREVIOUS POST was flagged for being off topic, too vague, and asking for opinions and recommendations for useful code. It did those things, so I am re-posting as a question on code I am working on. Thanks to those in the previous post, I was able to piece what I have here from reviewing what you guys said.
The focus here is the Parent/Child relationship and the use of fork() and pipe() to get the desired affect.
The project is a POSIX card game where the parent (dealer) forks into 5 children (players) with their own pipe from the parent. The parent deals cards to the players (at least 5 cards each) until one player has a 3 of a kind(no discard). The winning child transmits the winning hand and EOF (exit(0)) to the parent to declare victory. That triggers the parent to print the winning player and transmit EOF to the remaining children to close them out (exit(1)). The parent then closes. If the parent reaches the end of the deck without a winner, it transmits EOF to the children, waits for them to exit(1)...then closes.
The main question I had is how the child programs read each card individually rather than reading the same value from the pipe over and over. I think I am missing a method to sync the Parent writing to the pipe and the Children reading from the pipe.
I am completely new to this guys, so any help is greatly appreciated. Many thanks.
CODE UPDATED: (compiles with a lot of issues) Complete and compiles but I clearly have trouble with the pipes and relaying data through them. There's alot wrong here from failing to play the game, to failing to read from or write to the pipes, to leaving zombie processes. I'd appreciate any input on my mess. lol
This is my output when I run the program (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.
Current Code:
#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;
}