All pastes #10638 Raw Edit

Untitled

public c v1 · immutable
#10638 ·published 2005-04-30 09:57 UTC
rendered paste body
/****************************************************************  Copyright notice**  (c) 2005-2006 Lukas Pitschl (lukas@25haday.com) && Thomas Klaida*  All rights reserved**  This script can be redistributed and/or modified*  under the terms of the GNU General Public License as published by*  the Free Software Foundation; either version 2 of the License, or*  (at your option) any later version.**  The GNU General Public License can be found at*  http://www.gnu.org/copyleft/gpl.html.***  Description: the program is an implementation of master-mind*				in C, using a number instead of colors*				nothing but that, PERIOD!*				*				but..., it's using pipes and two process communicating.*				the child process generates the number to guess.*				the parent reads from stdin, passes the input to*				the child. he processes it and checkes whether the number*				matches the generated one or not. if not the number of*				digits which were on the right place and the right numbers*				are counted and marked as X.*				all digits that are found in the generated number*				are counted and marked as Points.*				*				a message is printed out and the game either*				continues or stops.****************************************************************/#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <limits.h>#include <fcntl.h>#include <time.h>/* including header file containing all * funtion definitions and gloabl vars, * as well as structures, constants, preprocessor * directives... */#include "mastermind.h"int main (int argc, char * argv[]) {    pid_t pid;	char buffer[PIPE_BUF];	int game_finish = 0;		/* contains the id of the process itself */	pid = getpid(); 	#if DEBUG	fprintf(stdout, "The process ID is %d\n", (int)pid);#endif			/* resetting result */	result.x = result.points = result.solved = 0;		fprintf(stdout, "MASTER MIND\n");	fprintf(stdout, "===========\n\n");		/* creating the pipe */	if(pipe(fd) < 0) {		perror("pipe");		exit(EXIT_FAILURE);	}		/* creating second pipe */	if(pipe(fd2) < 0) {		perror("pipe");		exit(EXIT_FAILURE);	}		/* creating a new process */	if((pid = fork()) < 0) {		perror("fork");		exit(EXIT_FAILURE);	}	else if(pid > 0) {		/* here comes all the code belonging to the parent process */		close(fd[0]);		close(fd2[1]);				/* opening pipe where the parent will write in the user input 		 * the child will read this pipe.		 */		if((wpipe = fdopen(fd[1], "w")) == NULL) {			fprintf(stderr, "line number %d\n", __LINE__);			perror("Opening pipe in write mode failed");			exit(EXIT_FAILURE);		}				/* opening pipe to receive child's calculated result */		if((rpipe2 = fdopen(fd2[0], "r")) == NULL) {			fprintf(stderr, "line number %d\n", __LINE__);			perror("Opening pipe in read mode failed");			exit(EXIT_FAILURE);		}				/* loops till right result */		while(!game_finish) {			/* asking for guess */			fprintf(stdout, "Guess my Number: ");			fflush(stdout);						/* reading guess number from stdin */			fgets(buffer, PIPE_BUF, stdin);				/* checking on valid input */			if(!checkUserInput(buffer)) {				fprintf(stdout, "\n");				continue;			}					/* writing input to pipe for child process */			fputs(buffer, wpipe);			fflush(wpipe);						/* reading result from child */			fgets(buffer, PIPE_BUF, rpipe2); 						/* checking on state and according to that,			 * printing the belonging message 			 */			if(!strstr(buffer, "SOLVED")) {				fprintf(stdout, "%s\n", buffer);				fflush(stdout);			}			else {				game_finish = 1;				fprintf(stdout, "%sRight dude!! This was my number%s\n", green, normal);				fflush(stdout);								break;			}		}		/* closing all pipes which are still left open */		fclose(wpipe);		fclose(rpipe2);				/* waiting for child process to die */		if ((waitpid (pid, NULL, 0)) < 0) {			perror ("waitpid() failed for some reason!");			exit (EXIT_FAILURE);		}	}	else {		/* all tasks for the child process come here */		close(fd[1]);		close(fd2[0]);				/* if game_state is not set to NOT_SOLVED a new number is generated */		if(game_state != NOT_SOLVED) {			guess_num = generateNumber();		}#if DEBUG		fprintf(stdout, "Guess it: %s\n", guess_num.rand_num);		fflush(stdout);#endif		/* opening pipe for reading, to get the number input from parent */		if((rpipe = fdopen(fd[0], "r")) == NULL) {			fprintf(stderr, "Couldn't open pipe for reading, %d\n", __LINE__);			perror("fdopen");			exit(EXIT_FAILURE);		}				/* opening pipe for writing, to pass the result over to the parent process */		if((wpipe2 = fdopen(fd2[1], "w")) == NULL) {			fprintf(stderr, "Couldn't open pipe for writing, %d\n", __LINE__);			perror("fdopen");			exit(EXIT_FAILURE);		}				/* reading from pipe */		while(fgets(buffer, PIPE_BUF, rpipe) != NULL) {			/* removing the newline-sequence */			ctrim(buffer);						/* calculating the result */			result = calcGuess(guess_num, buffer);					/* checking if the number was guessed right and telling the			 * parent about it			 */			if(result.solved) 				sprintf(buffer, "SOLVEDX = %d, Points = %d\n", result.x, result.points);			else {				sprintf(buffer, "X = %d, Points = %d\n", result.x, result.points);				game_state = NOT_SOLVED;			}						/* writing result to the pipe the parent is reading,			 * and to assure it's not buffer, flush da bastard :-D			 */ 			fputs(buffer, wpipe2);			fflush(wpipe2);		}		/* if the parent is closing the pipe the child is reading		 * the user input from, the while loop will stop.		 * 		 * so here the child pipe-streams the child is reading from		 * and writing to are closed.		 */		fclose(rpipe);		fclose(wpipe2);	}	exit(EXIT_SUCCESS);}/* implements a conditional trim  * if last char of a string is the new-line-sequence * it's removed and 1 returned, else 0*/int ctrim(char * string) {	if(string[strlen(string)-1] == '\n') {		string[strlen(string)-1] = '\0';	}	return 0;}/* generateNumber() generates the random number * it generates real integers with rand() * and are then converted to a string, else * it'd be really hard to check per number. * * the string is then stored in a struct for easily * backpassing it to the calling function.  */gennum_t generateNumber() {	int rand_num = 0;	gennum_t guess_num;	int i = 0;		srand((unsigned)time(NULL));			for(i = 0; i < MAX_NUMS; i++) {		rand_num = rand()%LETTER_RANGE+1;		guess_num.rand_num[i] = (char)itoa(rand_num);	}		guess_num.rand_num[i+1] = '\0';		return guess_num;}/* calc Guess calculates the X's and Points and * stores them in a struct again.*/result_t calcGuess(gennum_t guess_num, char * string) {	int i = 0;	result_t result;	int rand_code[LETTER_RANGE+1] = {0,0,0,0,0,0,0,0,0,0};	int tmp_i;		/* initialize result var */	result.x = result.points = result.solved = 0;#if DEBUG		fprintf(stdout, "Gen Num %s\n", guess_num.rand_num);#endif	/* first check whether the number from input is equal to	 * the generated num or not. if so, all the calculation	 * is no longer needed, thus dismissed	 */	if(strcmp(guess_num.rand_num, string) == 0) {		result.solved = 1;		return result;	}		/* first calculating how often each number appears	 * in the generated number	 */	for(i = 0; i < (int)strlen(string); i++) {		tmp_i = (int)guess_num.rand_num[i]-48;		rand_code[tmp_i]++;	}		for(i = 0; i < (int)strlen(string); i++) {		tmp_i = (int)string[i]-48;		if(rand_code[tmp_i] > 0) {			if(guess_num.rand_num[i] == string[i]) {				++result.x;				rand_code[tmp_i]--;				string[i] = 'x';			}		}	}		for(i = 0; i < (int)strlen(string); i++) {		tmp_i = (int)string[i]-48;		if(rand_code[tmp_i] > 0) {			if(string[i] == 'x') continue;			else if(inArray(guess_num.rand_num, string[i])) {				++result.points;				rand_code[tmp_i]--;			}		}	}		return result;}/* check whether a char is appearing in an char array */int inArray(char * string, char c) {	int i = 0;	for(i = 0; i < (int)strlen(string); i++) {		if(string[i] == c) return 1;	}		return 0;}/* returns the ASCII value matchin with the given integer */int itoa(int i) {	if(i < LETTER_FROM || i > LETTER_RANGE) return -1;	else return i + 48;}/* check whether the user input is valid. * valid has to comply with the following conditions: *	- must be no less than 4 digits *	- must be no letters */int checkUserInput(char * input) {#if DEBUG		fprintf(stdout, "%d Nr.\n", (int)strlen(input));#endif	/* check if the input is less than 4 digits */ 	if(strlen(input) <= MAX_NUMS) {		fprintf(stdout, "%sYou have to pass me exactly 4! numbers!%s\n", red, normal);		return 0;	}		/* check if there are letters in the input. if so display error message */	if(!checkOnValidInt(input)) {		fprintf(stdout, "%sC'mon, you can't pass me letters, as numbers are required!%s\n", red, normal);		return 0;	}		return 1;}/* checks if there are letters in the input */int checkOnValidInt(char * input) {	int i = 0;		for(i = 0; i < strlen(input); i++) {		if(input[i] == '\n') continue;		if(input[i]-48 < LETTER_FROM || input[i]-48 > LETTER_RANGE) return 0;	}		return 1;}