본문 바로가기
C, C++/과제창고

[C] YesOrNo 아키네이터

by 야호호코코 2018. 6. 27.
반응형

 예전에 C로 구현한 파일입출력 기반의 Yes or No 아키네이터이다. 컴퓨터가 모르는 부분에 다다르면 직접 사용자가 알려줄 수 있다.



#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct node {
	char *obj_name;		
	char *question;		

	struct node *yes_ptr;
	struct node *no_ptr; 
} Node;

void nodePrint(Node *n);	// 노드의 정보를 출력하며 게임을 진행하는 함수
void treeSave(Node *n);		// 트리의 정보를 텍스트 파일에 저장하는 함수
Node * treeRead(Node *n);	// 텍스트 파일에서 트리의 정보를 읽어 저장하는 함수 (트리 초기화)
Node * insertNode(Node *n, char *NodeObj);	// 노드를 삽입하는 함수 (컴퓨터가 모르는 정보를 알려줄 때)
void deleteTree(Node *n);	// 모든 노드를 free하는 함수
void treePrint(Node *n);	// 1D 부분함수


Node *n;

int main() {

	int loop = 1;

	char answer[100];

	n = treeRead(n);

	while (loop) {
		printf("OK, please think of something.\n");
		nodePrint(n);

		while (1) {	// YES나 NO가 아닐 경우를 대비하여 무한루프로 YES나 NO일 때까지 받음
			printf("Would you like to play again?\n");
			printf(">"); gets(answer);

			if (strcmp(strupr(answer), "YES") == 0) {
				loop = 1;
				break;
			}
			else if (strcmp(strupr(answer), "NO") == 0) {
				loop = 0;
				break;
			}
			else {
				printf("Yes or No로 대답해주세요.\n");
			}
		}
	}


	treeSave(n);

	deleteTree(n);

	return 0;

}

void nodePrint(Node *n) {

	char answer[100];

	char obj[100];

	if (n == NULL) {	// 아무것도 없으면 정답이 뭔지 질문
		printf("Oh. Well you win then -- What were you thinking of?\n");
	}
	else {
		if (n->question != NULL) {	// 질문이 비어있지 않으면 질문출력
			printf("%s\n", n->question);

			while (1) {
				printf(">"); gets(answer);

				if (strcmp(strupr(answer), "YES") == 0) {
					nodePrint(n->yes_ptr);	// YES일 때 yes_ptr로 노드 이동
					break;
				}
				else if (strcmp(strupr(answer), "NO") == 0) {
					nodePrint(n->no_ptr);	// NO일 떄 no_ptr로 노드 이동
					break;
				}
				else {
					printf("Yes or No로 대답해주세요.\n");
				}
			}

		}
		else {						// 질문이 비어있으면 obj가 맞는지 확인
			printf("Is it a %s?\n", n->obj_name);

			while (1) {
				printf(">"); gets(answer);

				if (strcmp(strupr(answer), "YES") == 0) {
					printf("Good. That was soooo easy\n");
					// 컴퓨터가 이김
					break;
				}
				else if (strcmp(strupr(answer), "NO") == 0) {
					insertNode(n, n->obj_name);
					// 플레이어가 이김, 정답에 대한 질문
					printf("Thanks.\n\n");
					break;
				}
				else {
					printf("Yes or No로 대답해주세요.\n");
				}
			}

		}
	}

}

// 1D 부분
void treePrint(Node *n) {

	if (n != NULL) {
		if (n->question != NULL) {
			printf("question: %s\nobject: NOTHING\n", n->question);
		}
		else {
			printf("question: NOTHING\nobject: %s\n", n->obj_name);
		}
		printf("YES: ");
		if (n->yes_ptr->question != NULL) {
			printf("%s\n", n->yes_ptr->question);
		}
		else {
			printf("%s\n", n->yes_ptr->obj_name);
		}

		printf("NO: ");
		if (n->no_ptr->question != NULL) {
			printf("%s\n", n->no_ptr->question);
		}
		else {
			printf("%s\n", n->no_ptr->obj_name);
		}

		treePrint(n->yes_ptr);
		treePrint(n->no_ptr);
	}

}


void treeSave(Node *n) {

	FILE *f;

	f = fopen("test.txt", "w");
	
	fprintf(f, "");	// 텍스트 파일 기존에 있는거 다 지움

	fclose(f);

	f = fopen("test.txt", "a");	

	if (n != NULL) {	// 저장
		if (n->question != NULL) { 
			printf("question: %s\n", n->question);  
			fprintf(f, "question: %s\n", n->question);
		}
		else { 
			printf("object: %s\n", n->obj_name); 
			fprintf(f, "object: %s\n", n->obj_name);
		}

		treeSave(n->yes_ptr);
		treeSave(n->no_ptr);
	}

}

Node * treeRead(Node *n) {

	FILE *f;

	char tmp[201];

	int i;

	static int c = 1;	// 몇번쨰 줄을 읽을지 정하는 변수 : c번째 줄을 읽음

	f = fopen("test.txt", "r");

	if (f == NULL) {
		return NULL;
	}
	else {
		n = (Node *)malloc(sizeof(Node));

		for (i = 0; i < c; i++) fgets(tmp, 201, f);

		if ( tmp == NULL ) n = NULL;	// 줄에 아무것도 없으면 빈 노드

		else if (strstr(tmp, "question:")) {	// 질문일 떄
			n->question = (char *)malloc(sizeof(char) * strlen(tmp));
			n->obj_name = NULL;

			strcpy(n->question, tmp + 10);

			n->question[strlen(n->question) - 1] = 0;	// 끝에 개행문자 지움

			c++;
			n->yes_ptr = treeRead(n->yes_ptr);	// yes_ptr로 노드 초기화
			c++;
			n->no_ptr = treeRead(n->no_ptr);	// no_ptr로 노드 초기화
		}
		else {	// 오브젝트일 떄 
			n->question = NULL;
			n->obj_name = (char *)malloc(sizeof(char) * strlen(tmp));
			
			strcpy(n->obj_name, tmp + 8);

			n->obj_name[strlen(n->obj_name) - 1] = 0;	// 끝에 개행문자 지움

			n->yes_ptr = n->no_ptr = NULL;	// 오브젝트만 남으면 이 노드는 제일 끝에 있는 노드이므로 뒤에 노드 없음
		}

	}

	return n;

	fclose(f);

}

Node * insertNode(Node *n, char *NodeObj) {

	char obj[200];
	char tmp[200];
	char question[300];
	char answer[100];

	strcpy(tmp, NodeObj);

	printf("Oh. well you win then -- What were you thinking of?\n");
	printf(">"); gets(obj);

	while (1) {
		printf("Please give me a question about %s, so I can tell the difference between %s and a %s\n", obj, obj, NodeObj);
		printf(">"); gets(question);
		if (strstr(question, "?")) break;
		else printf("물음표 넣어서 대답해주세요.\n");
	}
	while (1) {
		printf("What is the answer for %s?\n", obj);
		printf(">"); gets(answer);

		if (strcmp(strupr(answer), "YES") == 0) { break; }
		else if (strcmp(strupr(answer), "NO") == 0) { break; }
		else printf("Yes or No로 대답해주세요.\n");
	}

	n->question = (char *)malloc(sizeof(char) * (strlen(question) + 1));

	strcpy(n->question, question);

	free(n->obj_name);

	n->obj_name = NULL;

	if (strcmp(strupr(answer), "YES") == 0) {	// 플레이어가 알려준 오브젝트에 대한 정답이 YES일때
		n->yes_ptr = (Node *)malloc(sizeof(Node));

		n->yes_ptr->question = NULL;
		n->yes_ptr->obj_name = (char *)malloc(sizeof(char) * (strlen(obj) + 1));

		strcpy(n->yes_ptr->obj_name, obj);

		n->no_ptr = (Node *)malloc(sizeof(Node));

		n->no_ptr->question = NULL;
		n->no_ptr->obj_name = (char *)malloc(sizeof(char) * (strlen(tmp) + 1));

		strcpy(n->no_ptr->obj_name, tmp);
	}
	else {											// 플레이어가 알려준 오브젝트에 대한 정답이 NO일때
		n->no_ptr = (Node *)malloc(sizeof(Node));

		n->no_ptr->question = NULL;
		n->no_ptr->obj_name = (char *)malloc(sizeof(char) * (strlen(obj) + 1));

		strcpy(n->no_ptr->obj_name, obj);

		n->yes_ptr = (Node *)malloc(sizeof(Node));

		n->yes_ptr->question = NULL;
		n->yes_ptr->obj_name = (char *)malloc(sizeof(char) * (strlen(tmp) + 1));

		strcpy(n->yes_ptr->obj_name, tmp);
	}

	n->yes_ptr->yes_ptr = n->yes_ptr->no_ptr = NULL;
	n->no_ptr->yes_ptr = n->no_ptr->no_ptr = NULL;

	return n;

}

void deleteTree(Node *n) {

	if (n == NULL) return;

	else {
		if (n->obj_name != NULL) free(n->obj_name);
		else free(n->question);

		deleteTree(n->yes_ptr);
		deleteTree(n->no_ptr);
	}

}


반응형