날짜 : 190524

주제 : 파일 입출력, 클래스를 활용하여 마리오 게임을 만들어본다.

특징 : 아직 스테이지 구현은 하지 않았다. STL을 아직 쓰지 않고 배열로만 만들었다. 클래스를 사용하다 보니 코드가 분산되어 여기에 직접 올리지 못했다.

 

GitHub : https://github.com/crobbit-kent/CPP_BASIC_PRACTICE/tree/master/Mario

날짜 : 190523

주제 : 텍스트 파일에 미로를 직접 그리고 파일을 불러와서 미로 게임을 만들어 본다.

특징 : 파일 저장과 로딩을 텍스트 파일 또는 바이너리 파일로 할 수 있다.

 

#include <iostream>

using namespace std;

#define NAME_SIZE 32
#define STUDENT_MAX 3

typedef struct _tagStudent
{
	char name[NAME_SIZE];
	int number;
	int kor;
	int eng;
	int math;
	int total;
	int average;
}STUDENT, *PSTUDENT;

int main()
{
	/*
	STUDENT student[STUDENT_MAX] = {};

	for (int i = 0; i < STUDENT_MAX; ++i)
	{
		cin.clear();
		cin.ignore(1024, '\n');
		cout << "이름 : ";
		cin.getline(student[i].name, NAME_SIZE - 1);

		student[i].number = i + 1;

		cout << "국어 : ";
		cin >> student[i].kor;

		cout << "영어 : ";
		cin >> student[i].eng;

		cout << "수학 : ";
		cin >> student[i].math;

		student[i].total = student[i].math + student[i].eng + student[i].kor;
		student[i].average = student[i].total / 3.f;
	}

	// 학생 정보를 파일에 저장
	int studentCount = STUDENT_MAX;

	FILE* file = NULL;

	fopen_s(&file, "Student.std", "wb");

	if (file)
	{
		// 학생 수를 저장
		fwrite(&studentCount, 4, 1, file);

		for (int i = 0; i < studentCount; ++i)
		{
			// 학생 구조체를 통으로 저장
			fwrite(&student[i], sizeof(STUDENT), 1, file);
		}

		fclose(file);
	}
	*/

	STUDENT student[STUDENT_MAX] = {};

	FILE* file = NULL;


	fopen_s(&file, "Student.std", "rb");

	int studentCount = 0;

	if (file)
	{


		// 학생수를 먼저 읽어 온다.
		fread(&studentCount, 4, 1, file);

		for (int i = 0; i < studentCount; ++i)
		{
			fread(&student[i], sizeof(STUDENT), 1, file);
		}

		fclose(file);
	}

	for (int i = 0; i < studentCount; ++i)
	{
		cout << "이름 : " << student[i].name << endl;
		cout << "국어 : " << student[i].kor << endl;
		cout << "영어 : " << student[i].eng << endl;
		cout << "수학 : " << student[i].math << endl;
		cout << "총점 : " << student[i].total << endl;
		cout << "평균 : " << student[i].average << endl << endl;
	}

	system("pause");

	return 0;
}

 

날짜 : 190521

주제 : 더블 링크드 리스트 구현

설명 : 싱글과 다르게 더블은 노드 구조체 안에 앞에 있는 노드와 뒤에 있는 노드를 모두 저장하고 있다. 따라서 노드를 뒤에서부터 순회할 수 있다.

 

#include <iostream>

using namespace std;

#define NAME_SIZE 32

/* 링크드 리스트 : 자료구조의 한 종류. 자료구조란 데이터를 저장하는 방법
링크드 리스트는 데이터 목록을 연결시켜서 접근할 수 있는 구조를 제공

특징 : 선형구조... 즉 배열처럼 특정요소에 바로 접근 불가. 무조건 앞에서부터 차례대로 들어가야한다.
노드를 추가할때 노드를 생성하고 마지막 노드에 연결. 따라서 개수의 제한이 없음.


노드 : 데이터를 저장하기 위한 공간
노드의 특징 : 다음노드에 연결가능(주소를 저장)
*/

/*
정렬 기능 추가... 기준은 학번 또는 평균
*/

enum MAIN_MENU
{
	MM_NONE,
	MM_INSERT,
	MM_DELETE,
	MM_SEARCH,
	MM_PRINT,
	MM_SORT,
	MM_EXIT
};

enum PRINT_MENU
{
	PM_NONE,
	PM_FORWARDS,
	PM_BACKWARDS,
	PM_BACK
};

enum SORT_MENU
{
	SM_NONE,
	SM_NUMBER,
	SM_AVERAGE,
	SM_BACK
};

// 학생 정보 구조체
typedef struct _tagStudent
{
	char	name[NAME_SIZE];
	int		number;
	int		kor;
	int		eng;
	int		math;
	int		total;
	float	average;
}STUDENT, *PSTUDENT;

// 노드 구조체
typedef struct _tagNode
{
	STUDENT studentData;
	_tagNode* nextNode;
	_tagNode* prevNode;
}NODE, *PNODE;

// 리스트 구조체
typedef struct _tagList
{
	PNODE	begin;
	PNODE	end;
	int		currentSize;
	int		studentNumberStandard;
}LIST, *PLIST;

void InitList(PLIST list)
{
	// 포인터 초기화 방식
	list->begin = NULL;
	list->end = NULL;
	list->currentSize = 0;
}

int InputInt()
{
	int input;
	cin >> input;

	if (cin.fail())
	{
		cin.clear();
		cin.ignore(1024, '\n');
		return INT_MAX;
	}

	return input;
}

int PrintMenu()
{
	system("cls");
	cout << "1. 학생 추가" << endl;
	cout << "2. 학생 삭제" << endl;
	cout << "3. 학생 탐색" << endl;
	cout << "4. 학생 출력" << endl;
	cout << "5. 학생 정렬" << endl;
	cout << "6. 종료" << endl << endl;

	cout << "메뉴를 선택하세요 : " << endl;

	int input = InputInt();

	if (input <= MM_NONE || input > MM_EXIT)
	{
		return MM_NONE;
	}

	return input;
}

void InputString(char* string, int size)
{
	cin.clear();
	cin.ignore(1024, '\n');

	cin.getline(string, size - 1);
}

void Insert(PLIST list)
{
	system("cls");
	cout << "========== 1. 학생 추가 ==========" << endl;

	STUDENT student = {};

	cout << "이름 : ";
	InputString(student.name, NAME_SIZE);

	cout << "국어 점수 : ";
	student.kor = InputInt();

	cout << "영어 점수 : ";
	student.eng = InputInt();

	cout << "수학 점수 : ";
	student.math = InputInt();

	student.total = student.kor + student.eng + student.math;
	student.average = student.total / 3.f;

	++list->studentNumberStandard;
	++list->currentSize;
	student.number = list->studentNumberStandard;


	// 추가할 리스트 노드를 생성
	PNODE	node = new NODE;

	// 마지막에 추가되는 노드이기 때문에 그 뒤에 노드는 없음
	node->nextNode = NULL;

	// 입력받은 데이터를 노드에 저장
	node->studentData = student;

	// 헤드노드가 비어있으면 새로 생성된 노드가 헤드노드
	if (list->begin == NULL)
	{
		list->begin = node;
		node->prevNode = NULL;
	}
	else
	{
		node->prevNode = list->end;
		list->end->nextNode = node;
	}

	// 새로 생성된 노드가 마지막 노드
	list->end = node;
}

//void InsertFront(PLIST list)


void ClearList(PLIST list)
{
	PNODE	node = list->begin;

	while (node != NULL)
	{
		// 다음 노드 저장
		PNODE	next = node->nextNode;

		// 현재 노드 삭제
		delete node;

		// 이제 다음 노드로
		node = next;
	}

	// 마지막으로 모두 초기화
	list->begin = NULL;
	list->end = NULL;
	list->currentSize = 0;
}

const void PrintStudentData(const PSTUDENT student)
{
	cout << "이름 : " << student->name << "\t학번 : " << student->number << endl;
	cout << "국어 점수 : " << student->kor << "\t영어 점수 : " << student->eng << endl;
	cout << "수학 점수 : " << student->math << endl;
	cout << "총 점 : " << student->total << "\t평 균 : " << student->average << endl << endl;
}

const void PrintListBackwards(const PLIST list)
{
	PNODE	node = list->end;

	while (node != NULL)
	{
		PrintStudentData(&node->studentData);
		node = node->prevNode;
	}

	cout << "총 학생 수 : " << list->currentSize << endl;
}

const void PrintListForwards(const PLIST list)
{
	PNODE	node = list->begin;

	while (node != NULL)
	{
		PrintStudentData(&node->studentData);
		node = node->nextNode;
	}

	cout << "총 학생 수 : " << list->currentSize << endl;
}

const void PrintList(const PLIST list)
{
	while (true)
	{
		system("cls");
		cout << "========== 4. 학생 정보 출력 ==========" << endl;
		cout << "1. 정방향 출력" << endl;
		cout << "2. 역방향 출력" << endl;
		cout << "3. 뒤로 가기" << endl;
		int menu = InputInt();

		switch (menu)
		{
		case PM_FORWARDS:
			PrintListForwards(list);
			break;
		case PM_BACKWARDS:
			PrintListBackwards(list);
			break;
		case PM_BACK:
			return;
			break;
		}

		system("pause");
	}
	
}

void SearchByName(PLIST list)
{
	cout << "탐색할 이름을 입력하세요 : ";
	char searchName[NAME_SIZE] = {};
	InputString(searchName, NAME_SIZE);

	PNODE	node = list->begin;

	while (node != NULL)
	{
		if (strcmp(node->studentData.name, searchName) == 0)
		{
			PrintStudentData(&node->studentData);
			system("pause");

			return;
		}

		node = node->nextNode;
	}

	cout << "ERROR : 일치하는 학생을 찾지 못했습니다." << endl;
	system("pause");
}

void SearchByNumber(PLIST list)
{
	cout << "탐색할 학번을 입력하세요 : ";
	int		searchNumber;
	searchNumber = InputInt();

	PNODE	node = list->begin;

	while (node != NULL)
	{
		if (node->studentData.number == searchNumber)
		{
			PrintStudentData(&node->studentData);
			system("pause");

			return;
		}

		node = node->nextNode;
	}

	cout << "ERROR : 일치하는 학생을 찾지 못했습니다." << endl;
	system("pause");
}

void Search(PLIST list)
{
	while (true)
	{
		system("cls");
		cout << "========== 3. 학생 탐색 ==========" << endl;

		cout << "1. 이름 검색" << endl;
		cout << "2. 학번 검색" << endl;
		cout << "3. 뒤로가기" << endl << endl;

		cout << "메뉴를 선택하세요 : ";

		int menu = InputInt();

		switch (menu)
		{
		case 1:
			SearchByName(list);
			break;
		case 2:
			SearchByNumber(list);
			break;
		case 3:
			break;
		}

		break;
	}
}

void Delete(PLIST list)
{
	system("cls");
	cout << "========== 4. 학생 삭제 ==========" << endl;

	cout << "삭제할 이름을 입력하세요 : ";
	char searchName[NAME_SIZE] = {};
	InputString(searchName, NAME_SIZE);

	PNODE	currNode = list->begin;

	while (currNode != NULL)
	{
		if (strcmp(currNode->studentData.name, searchName) == 0)
		{
			cout << currNode->studentData.name << " 학생이 삭제되었습니다." << endl;
			PNODE	nextNode = currNode->nextNode;
			PNODE	prevNode = currNode->prevNode;

			// 만약 이전 노드가 NULL이라면
			// 즉 시작 노드라면
			if (prevNode == NULL)
			{
				delete currNode;
				list->begin = nextNode;

				// 다음 노드가 헤드 노드가 된다.
				nextNode->prevNode = NULL;

				if (nextNode == NULL)
				{
					list->end = NULL;
				}
			}

			// 만약 이전 노드가 NULL이 아니라면 이전노드의 다음을 다음 노드와 연결
			else
			{
				delete currNode;
				
				// 다음 노드가 존재한다면
				if (nextNode != NULL)
				{
					nextNode->prevNode = prevNode;
					prevNode->nextNode = nextNode;
				}
				else
				{
					list->end = prevNode;
					prevNode->nextNode = NULL;
				}
			}

			--list->currentSize;
			system("pause");
			return;
		}

		// 해당 학생이 아니라면 현재 노드가 이전 노드가 된다.
		currNode = currNode->nextNode;
	}

	cout << "삭제할 학생을 찾을 수 없습니다." << endl;
	system("pause");
}

void Sort(PLIST list)
{
	system("cls");
	cout << "========== 5. 정렬하기 ==========" << endl;
	cout << "1. 학점 기준" << endl;
	cout << "2. 평균 기준" << endl;
	cout << "메뉴를 선택하세요. ";

	int menu = InputInt();

	if (menu <= SM_NONE || menu > SM_AVERAGE)
	{
		cout << "잘못 선택하였습니다." << endl;
		system("pause");
		return;
	}

	
	int i = 0;

	while (i <= list->currentSize)
	{
		PNODE	firstNode = list->begin;
		PNODE	secondNode = firstNode->nextNode;
		while (secondNode != NULL)
		{
			bool	swap = false;

			switch (menu)
			{
			case SM_NUMBER:
				if ((firstNode->studentData.number) > (secondNode->studentData.number))
				{
					swap = true;
				}

				break;
			case SM_AVERAGE:
				if ((firstNode->studentData.average) > (secondNode->studentData.average))
				{
					swap = true;
				}
				break;
			}

			if (swap == true)
			{
				PNODE	firstPrev = firstNode->prevNode;
				PNODE	firstNext = firstNode->nextNode;

				PNODE	secondPrev = secondNode->prevNode;
				PNODE	secondNext = secondNode->nextNode;


				// begin 설정
				if (firstNode == list->begin)
				{
					list->begin = secondNode;
				}

				PNODE	tempNode = firstNode;
				firstNode = secondNode;
				secondNode = tempNode;

				// 앞앞 노드
				if(firstPrev != NULL)
				{
					firstPrev->nextNode = firstNode;
				}

				// 뒤뒤 노드
				if (secondNext != NULL)
				{
					secondNext->prevNode = secondNode;
				}

				// 2번째 노드
				secondNode->nextNode = secondNext;
				secondNode->prevNode = firstNode;			

				// 1번째 노드
				firstNode->prevNode = firstPrev;
				firstNode->nextNode = secondNode;

				// end 설정
				if (firstNext == list->end)
				{
					list->end = secondNode;
				}

				firstNode = secondNode;
				secondNode = firstNode->nextNode;
			}
			else
			{
				firstNode = secondNode;
				secondNode = firstNode->nextNode;
			}
		}
		++i;
	}
	cout << "========= 정렬 되었습니다. =========" << endl;
	PrintListForwards(list);

	system("pause");
}

int main()
{
	LIST	list = {};

	InitList(&list);

	while (true)
	{
		int menu = PrintMenu();

		if (menu == MM_EXIT)
		{
			break;
		}

		switch (menu)
		{
		case MM_INSERT:
			Insert(&list);
			break;
		case MM_DELETE:
			Delete(&list);
			break;
		case MM_SEARCH:
			Search(&list);
			break;
		case MM_PRINT:
			PrintList(&list);
			break;
		case MM_SORT:
			Sort(&list);
			break;
		case MM_EXIT:
			break;
		}
	}

	ClearList(&list);

	return 0;
}

날짜 : 190520

주제 : 싱글 링크드 리스트로 학생관리 프로그램 만들기

설명 : 노드를 구조체로 만들고 그 구조체 안에 다음 구조체의 주소를 저장할 변수를 선언한다. 그 후 노드와 노드를 연결하는 것이 링크드 리스트이다. 장점은 노드의 최대 개수 같은 것들이 정해져 있지 않아서 마음대로 노드를 추가/제거할 수 있다. 따라서 고정크기인 배열의 단점을 보완할 수 있다. 단점은 연속된 메모리 공간이 아니기 때문에 추가하고 지울 경우 '메모리 단편화'가 발생할 수 있다.

 

#include <iostream>

using namespace std;

#define NAME_SIZE 32



/* 링크드 리스트 : 자료구조의 한 종류. 자료구조란 데이터를 저장하는 방법
링크드 리스트는 데이터 목록을 연결시켜서 접근할 수 있는 구조를 제공

특징 : 선형구조... 즉 배열처럼 특정요소에 바로 접근 불가. 무조건 앞에서부터 차례대로 들어가야한다.
노드를 추가할때 노드를 생성하고 마지막 노드에 연결. 따라서 개수의 제한이 없음.


노드 : 데이터를 저장하기 위한 공간
노드의 특징 : 다음노드에 연결가능(주소를 저장)
*/

enum MAIN_MENU
{
	MM_NONE,
	MM_INSERT,
	MM_DELETE,
	MM_SEARCH,
	MM_PRINT,
	MM_EXIT
};

// 학생 정보 구조체
typedef struct _tagStudent
{
	char	name[NAME_SIZE];
	int		number;
	int		kor;
	int		eng;
	int		math;
	int		total;
	float	average;
}STUDENT, *PSTUDENT;

// 노드 구조체
typedef struct _tagNode
{
	STUDENT studentData;
	_tagNode* nextNode;
}NODE, *PNODE;

// 리스트 구조체
typedef struct _tagList
{
	PNODE	begin;
	PNODE	end;
	int		currentSize;
	int		studentNumberStandard;
}LIST, *PLIST;

void InitList(PLIST list)
{
	// 포인터 초기화 방식
	list->begin = NULL;
	list->end = NULL;
	list->currentSize = 0;
}

int InputInt()
{
	int input;
	cin >> input;

	if (cin.fail())
	{
		cin.clear();
		cin.ignore(1024, '\n');
		return INT_MAX;
	}

	return input;
}

int PrintMenu()
{
	system("cls");
	cout << "1. 학생 추가" << endl;
	cout << "2. 학생 삭제" << endl;
	cout << "3. 학생 탐색" << endl;
	cout << "4. 학생 출력" << endl;
	cout << "5. 종료" << endl << endl;

	cout << "메뉴를 선택하세요 : " << endl;

	int input = InputInt();

	if (input <= MM_NONE || input > MM_EXIT)
	{
		return MM_NONE;
	}
	
	return input;
}

void InputString(char* string, int size)
{
	cin.clear();
	cin.ignore(1024, '\n');

	cin.getline(string, size - 1);
}

void Insert(PLIST list)
{
	system("cls");
	cout << "========== 1. 학생 추가 ==========" << endl;

	STUDENT student = {};

	cout << "이름 : ";
	InputString(student.name, NAME_SIZE);

	cout << "국어 점수 : ";
	student.kor = InputInt();

	cout << "영어 점수 : ";
	student.eng = InputInt();

	cout << "수학 점수 : ";
	student.math = InputInt();

	student.total = student.kor + student.eng + student.math;
	student.average = student.total / 3.f;

	++list->studentNumberStandard;
	++list->currentSize;
	student.number = list->studentNumberStandard;


	// 추가할 리스트 노드를 생성
	PNODE	node = new NODE;

	// 마지막에 추가되는 노드이기 때문에 그 뒤에 노드는 없음
	node->nextNode = NULL;

	// 입력받은 데이터를 노드에 저장
	node->studentData = student;

	// 헤드노드가 비어있으면 새로 생성된 노드가 헤드노드
	if (list->begin == NULL)
	{
		list->begin = node;
	}
	else
	{
		list->end->nextNode = node;
	}

	// 새로 생성된 노드가 마지막 노드
	list->end = node;
}

void ClearList(PLIST list)
{
	PNODE	node = list->begin;

	while (node != NULL)
	{
		// 다음 노드 저장
		PNODE	next = node->nextNode;
		
		// 현재 노드 삭제
		delete node;

		// 이제 다음 노드로
		node = next;
	}

	// 마지막으로 모두 초기화
	list->begin = NULL;
	list->end = NULL;
	list->currentSize = 0;
}

const void PrintStudentData(const PSTUDENT student)
{
	cout << "이름 : " << student->name << "\t학번 : " << student->number << endl;
	cout << "국어 점수 : " << student->kor << "\t영어 점수 : " << student->eng << endl;
	cout << "수학 점수 : " << student->math << endl;
	cout << "총 점 : " << student->total << "\t평 균 : " << student->average << endl << endl;
}

const void PrintList(const PLIST list)
{
	system("cls");
	cout << "========== 4. 학생 정보 출력 ==========" << endl;

	PNODE	node = list->begin;

	while (node != NULL)
	{
		PrintStudentData(&node->studentData);
		node = node->nextNode;
	}

	cout << "총 학생 수 : " << list->currentSize << endl;

	system("pause");
}

void SearchByName(PLIST list)
{
	cout << "탐색할 이름을 입력하세요 : ";
	char searchName[NAME_SIZE] = {};
	InputString(searchName, NAME_SIZE);

	PNODE	node = list->begin;

	while (node != NULL)
	{
		if (strcmp(node->studentData.name, searchName) == 0)
		{
			PrintStudentData(&node->studentData);
			system("pause");

			return;
		}

		node = node->nextNode;
	}

	cout << "ERROR : 일치하는 학생을 찾지 못했습니다." << endl;
	system("pause");
}

void SearchByNumber(PLIST list)
{
	cout << "탐색할 학번을 입력하세요 : ";
	int		searchNumber;
	searchNumber = InputInt();

	PNODE	node = list->begin;

	while (node != NULL)
	{
		if (node->studentData.number == searchNumber)
		{
			PrintStudentData(&node->studentData);
			system("pause");

			return;
		}

		node = node->nextNode;
	}

	cout << "ERROR : 일치하는 학생을 찾지 못했습니다." << endl;
	system("pause");
}

void Search(PLIST list)
{	
	while (true)
	{
		system("cls");
		cout << "========== 3. 학생 탐색 ==========" << endl;

		cout << "1. 이름 검색" << endl;
		cout << "2. 학번 검색" << endl;
		cout << "3. 뒤로가기" << endl << endl;

		cout << "메뉴를 선택하세요 : ";

		int menu = InputInt();

		switch (menu)
		{
		case 1:
			SearchByName(list);
			break;
		case 2:
			SearchByNumber(list);
			break;
		case 3:
			break;
		}

		break;
	}	
}

void Delete(PLIST list)
{
	system("cls");
	cout << "========== 4. 학생 삭제 ==========" << endl;

	cout << "삭제할 이름을 입력하세요 : ";
	char searchName[NAME_SIZE] = {};
	InputString(searchName, NAME_SIZE);

	PNODE	currNode = list->begin;
	PNODE	prevNode = NULL;

	while (currNode != NULL)
	{
		if (strcmp(currNode->studentData.name, searchName) == 0)
		{
			cout << currNode->studentData.name << " 학생이 삭제되었습니다." << endl;
			PNODE	nextNode = currNode->nextNode;

			// 만약 이전 노드가 NULL이라면
			// 즉 시작 노드라면
			if (prevNode == NULL)
			{
				delete currNode;
				list->begin = nextNode;

				if (nextNode == NULL)
				{
					list->end = NULL;
				}
			}

			// 만약 이전 노드가 NULL이 아니라면 이전노드의 다음을 다음 노드와 연결
			else
			{
				cout << currNode->studentData.name << " 학생이 삭제되었습니다." << endl;
				delete currNode;
				prevNode->nextNode = nextNode;

				if (nextNode == NULL)
				{
					list->end = prevNode;
				}
			}

			--list->currentSize;
			system("pause");
			return;
		}

		// 해당 학생이 아니라면 현재 노드가 이전 노드가 된다.
		prevNode = currNode;
		currNode = currNode->nextNode;
	}

	cout << "삭제할 학생을 찾을 수 없습니다." << endl;
	system("pause");
}

int main()
{
	LIST	list = {};

	InitList(&list);

	while (true)
	{
		int menu = PrintMenu();

		if (menu == MM_EXIT)
		{
			break;
		}

		switch (menu)
		{
		case MM_INSERT:
			Insert(&list);
			break;
		case MM_DELETE:
			Delete(&list);
			break;
		case MM_SEARCH:
			Search(&list);
			break;
		case MM_PRINT:
			PrintList(&list);
			break;
		}
	}

	ClearList(&list);

	return 0;
}
/* 숙제 : 더블 링크드 리스트로 학생관리 프로그램 만들기 */

 

 

 

 

날짜 : 190517

주제 : TextRPG (플레이어, 몬스터, 전투, 상점)

특징 : 

1. 강의 20화에서 했던 메뉴 구현을 적용시켜서 턴제 Text RPG를 구현.

2. 상점에서 무기 팔기 기능은 아직 구현하지 않음

3. 지도 easy, normal, hard를 선택함에 따라 나오는 몬스터가 정해져있다.

#include <iostream>
#include "time.h"
#include "stdlib.h"

using namespace std;

enum MAIN_MENU
{
	MM_NONE,
	MM_MAP,
	MM_STORE,
	MM_INVENTORY,
	MM_EXIT
};

enum MAP_TYPE
{
	MT_NONE,
	MT_EASY,
	MT_NORMAL,
	MT_HARD,
	MT_BACK
};

enum CLASS
{
	CLASS_NONE,
	CLASS_KNIGHT,
	CLASS_ARCHER,
	CLASS_WIZARD,
	CLASS_END
};

enum BATTLE
{
	BATTLE_NONE,
	BATTLE_ATTACK,
	BATTLE_BACK
};

enum ITEM_TYPE
{
	IT_NONE,
	IT_WEAPON,
	IT_ARMOR,
	IT_BACK
};

enum STORE_MENU
{
	SM_NONE,
	SM_WEAPON,
	SM_ARMOR,
	SM_BACK
};

enum STORE_MENU_2
{
	SM2_NONE,
	SM2_LIST1,
	SM2_LIST2,
	SM2_LIST3,
	SM2_BACK
};

#define NAME_SIZE			32
#define ITEM_DESC_LENGTH	512
#define INVENTORY_MAX		6
#define STORE_WEAPON_MAX	3
#define STORE_ARMOR_MAX		3

struct _tagItem
{
	char	  name[NAME_SIZE];
	char	  typeName[NAME_SIZE];
	ITEM_TYPE type;
	int		  min;
	int		  max;
	int		  price;
	int		  sell;
	char	  description[ITEM_DESC_LENGTH];
};

struct _tagInventory
{
	_tagItem itemArr[INVENTORY_MAX];
	int		itemCount;
	int		gold;
	_tagItem weapon;
	_tagItem armor;
};

struct _tagPlayer
{
	char	name[NAME_SIZE];
	char	className[NAME_SIZE];
	CLASS	Class;
	int		attackMin;
	int		attackMax;
	int		armorMin;
	int		armorMax;
	int		hp;
	int		hpMax;
	int		mp;
	int		mpMax;
	int		exp;
	int		level;
	_tagInventory inventory;
};


struct _tagMonster
{
	char	name[NAME_SIZE];
	int		attackMin;
	int		attackMax;
	int		armorMin;
	int		armorMax;
	int		hp;
	int		hpMax;
	int		mp;
	int		mpMax;
	int		level;
	int		exp;
	int		goldMin;
	int		goldMax;

};

int main()
{
	srand((unsigned int)time(0));

	// 플레이어 정보 설정
	_tagPlayer player = {};

	cout << "이름 : ";
	cin.getline(player.name, NAME_SIZE - 1);

	int selectedClass = CLASS_NONE;
	while (true)
	{
		system("cls");
		cout << "1. 기사" << endl;
		cout << "2. 궁사" << endl;
		cout << "3. 마법사" << endl;
		cout << "클래스를 고르시오 : ";
		cin >> selectedClass;

		if (cin.fail())
		{
			cin.clear();
			cin.ignore(1024, '\n');
			continue;
		}

		else if (selectedClass <= CLASS_NONE || selectedClass >= CLASS_END)
		{
			selectedClass = CLASS_NONE;
			continue;
		}
		
		break;
	}
	
	player.level = 1;
	player.exp = 0;
	player.inventory.gold = 1000000;
	player.Class = (CLASS)selectedClass;

	
	switch (player.Class)
	{
	case CLASS_KNIGHT:
		strcpy_s(player.className, "기사");
		player.attackMin = 5;
		player.attackMax = 10;
		player.armorMin = 15;
		player.armorMax = 20;
		player.hpMax = 500;
		player.hp = 500;
		player.mpMax = 100;
		player.mp = 100;
		break;
	case CLASS_ARCHER:
		strcpy_s(player.className, "궁수");
		player.attackMin = 10;
		player.attackMax = 15;
		player.armorMin = 10;
		player.armorMax = 15;
		player.hpMax = 400;
		player.hp = 400;
		player.mpMax = 200;
		player.mp = 200;
		break;
	case CLASS_WIZARD:
		strcpy_s(player.className, "마법사");
		player.attackMin = 15;
		player.attackMax = 20;
		player.armorMin = 5;
		player.armorMax = 10;
		player.hpMax = 300;
		player.hp = 300;
		player.mpMax = 300;
		player.mp = 300;
		break;
	}

	// 몬스터 생성
	_tagMonster	monsterArr[MT_BACK - 1] = {};

	// 고블린 생성
	strcpy_s(monsterArr[0].name, "고블린");
	monsterArr[0].attackMin = 20;
	monsterArr[0].attackMax = 30;
	monsterArr[0].armorMin = 2;
	monsterArr[0].armorMax = 5;
	monsterArr[0].hpMax = 100;
	monsterArr[0].hp = 100;
	monsterArr[0].mpMax = 10;
	monsterArr[0].mp = 10;
	monsterArr[0].level = 1;
	monsterArr[0].exp = 10;
	monsterArr[0].goldMin = 500;
	monsterArr[0].goldMax = 800;

	// 트롤
	strcpy_s(monsterArr[1].name, "트롤");
	monsterArr[1].attackMin = 80;
	monsterArr[1].attackMax = 130;
	monsterArr[1].armorMin = 60;
	monsterArr[1].armorMax = 90;
	monsterArr[1].hpMax = 2000;
	monsterArr[1].hp = 2000;
	monsterArr[1].mpMax = 100;
	monsterArr[1].mp = 100;
	monsterArr[1].level = 5;
	monsterArr[1].exp = 80;
	monsterArr[1].goldMin = 4000;
	monsterArr[1].goldMax = 7000;

	// 드래곤
	strcpy_s(monsterArr[2].name, "드래곤");
	monsterArr[2].attackMin = 250;
	monsterArr[2].attackMax = 500;
	monsterArr[2].armorMin = 200;
	monsterArr[2].armorMax = 400;
	monsterArr[2].hpMax = 30000;
	monsterArr[2].hp = 30000;
	monsterArr[2].mpMax = 20000;
	monsterArr[2].mp = 20000;
	monsterArr[2].level = 10;
	monsterArr[2].exp = 30000;
	monsterArr[2].goldMin = 30000;
	monsterArr[2].goldMax = 70000;

	// 상점에서 판매할 아에팀 목록을 생성한다.

	// 무기 리스트
	_tagItem	storeWeaponArr[STORE_WEAPON_MAX] = {};
	// 요우무의 단검
	strcpy_s(storeWeaponArr[0].name, "요우무의 단검");
	strcpy_s(storeWeaponArr[0].typeName, "무기");
	storeWeaponArr[0].type = IT_WEAPON;
	storeWeaponArr[0].min = 100;
	storeWeaponArr[0].max = 500;
	storeWeaponArr[0].price = 1000;
	storeWeaponArr[0].sell = storeWeaponArr[0].price * 0.6f;
	strcpy_s(storeWeaponArr[0].description, 
		"요우무라는 장인이 발레리안 스틸로 만든 고급 단검"
	);
	// 슈렐리아의 장검
	strcpy_s(storeWeaponArr[1].name, "슈렐리아의 장검");
	strcpy_s(storeWeaponArr[1].typeName, "무기");
	storeWeaponArr[1].type = IT_WEAPON;
	storeWeaponArr[1].min = 1000;
	storeWeaponArr[1].max = 1500;
	storeWeaponArr[1].price = 20000;
	storeWeaponArr[1].sell = storeWeaponArr[1].price * 0.6f;
	strcpy_s(storeWeaponArr[1].description,
		"슈렐리아라는 나라에서 황실 경비병들이 사용하는 무기"
	);
	// 레이피어
	strcpy_s(storeWeaponArr[2].name, "레이피어");
	strcpy_s(storeWeaponArr[2].typeName, "무기");
	storeWeaponArr[2].type = IT_WEAPON;
	storeWeaponArr[2].min = 2000;
	storeWeaponArr[2].max = 3000;
	storeWeaponArr[2].price = 500000;
	storeWeaponArr[2].sell = storeWeaponArr[2].price * 0.6f;
	strcpy_s(storeWeaponArr[2].description,
		"요정족이 만들었다고 소문으로만 전해지는 전설의 검. 가벼운 것이 특징"
	);

	// 갑옷 리스트
	_tagItem	storeArmorArr[STORE_WEAPON_MAX] = {};
	// 징박힌 갑옷
	strcpy_s(storeArmorArr[0].name, "징박힌 값옷");
	strcpy_s(storeArmorArr[0].typeName, "갑옷");
	storeArmorArr[0].type = IT_ARMOR;
	storeArmorArr[0].min = 105;
	storeArmorArr[0].max = 505;
	storeArmorArr[0].price = 1005;
	storeArmorArr[0].sell = storeWeaponArr[0].price * 0.6f;
	strcpy_s(storeArmorArr[0].description,
		"고급 가죽 갑옷에 징을 박아 방어력을 더함"
	);
	// 판금 갑옷
	strcpy_s(storeArmorArr[1].name, "판금 갑옷");
	strcpy_s(storeArmorArr[1].typeName, "갑옷");
	storeArmorArr[1].type = IT_ARMOR;
	storeArmorArr[1].min = 1005;
	storeArmorArr[1].max = 1505;
	storeArmorArr[1].price = 20005;
	storeArmorArr[1].sell = storeArmorArr[1].price * 0.6f;
	strcpy_s(storeArmorArr[1].description,
		"판금으로 만들어진 갑옷"
	);
	// 드래곤 스케일 갑옷
	strcpy_s(storeArmorArr[2].name, "레이피어");
	strcpy_s(storeArmorArr[2].typeName, "갑옷");
	storeArmorArr[2].type = IT_ARMOR;
	storeArmorArr[2].min = 2005;
	storeArmorArr[2].max = 3005;
	storeArmorArr[2].price = 500005;
	storeArmorArr[2].sell = storeArmorArr[2].price * 0.6f;
	strcpy_s(storeArmorArr[2].description,
		"전설의 용을 잡아 그 가죽으로 만든 갑옷"
	);

	

	// 메인 화면
	while (true)
	{
		system("cls");
		cout << endl << "========== 메인 메뉴 ==========" << endl << endl;
		cout << "1. 지도 " << endl;
		cout << "2. 상점 " << endl;
		cout << "3. 가방 " << endl;
		cout << "4. 종료 " << endl;
		cout << "메뉴를 선택하세요 : ";
		int menu;
		cin >> menu;

		if (cin.fail())
		{
			cin.clear();
			cin.ignore(1024, '\n');
			continue;
		}

		if (menu == MM_EXIT)
		{
			break;
		}

		switch (menu)
		{
		case MM_MAP:
			while (true)
			{
				system("cls");
				cout << endl << "========== 맵 종류 ==========" << endl<< endl;
				cout << "1. 쉬움" << endl;
				cout << "2. 보통" << endl;
				cout << "3. 어려움" << endl;
				cout << "4. 뒤로가기" << endl;
				cout << "맵을 선택하세요 : ";
				cin >> menu;

				if (cin.fail())
				{
					cin.clear();
					cin.ignore(1024, '\n');
					continue;
				}

				if (menu == MT_BACK)
				{
					// 맵 선택 화면에서 빠져나간다
					break;
				}

				// 선택한 메뉴에서 1을 빼주면 몬스터 배열의 인덱스가 된다.
					// 이렇게 해당 맵의 몬스터를 설정
				_tagMonster monster = monsterArr[menu - 1];

				// 전투
				while (true)
				{
					system("cls");
					switch(menu)
					{
					case MT_EASY:
						cout << "********** 쉬움 **********" << endl;
						break;
					case MT_NORMAL:
						cout << "********** 보통 **********" << endl;
						break;
					case MT_HARD:
						cout << "********** 어려움 **********" << endl;
						break;
					}

					// 플레이어 정보를 출력
					cout << "========== 플레이어 ==========" << endl;
					cout << "이름 : " << player.name << "\t직업 : " << player.className << endl;
					cout << "레벨 : " << player.level << "\t경험치 : " << player.exp << endl;
					cout << "공격력 : " << player.attackMin << " ~ " << player.attackMax << endl;
					cout << "방어력 : " << player.armorMin << " ~ " << player.armorMax << endl;
					cout << "체력 : " << player.hp << " / " << player.hpMax << "\t마나 : " << player.mp << " / " << player.mpMax << endl;
					cout << "소지금 : " << player.inventory.gold << endl << endl;

					// 몬스터 정보를 출력
					cout << "========== 몬스터 ==========" << endl;
					cout << "이름 : " << monster.name << "\t레벨 : " << monster.level << endl;
					cout << "공격력 : " << monster.attackMin << " ~ " << monster.attackMax << endl;
					cout << "방어력 : " << monster.armorMin << " ~ " << monster.armorMax << endl;
					cout << "체력 : " << monster.hp << " / " << monster.hpMax << "\t마나 : " << monster.mp << " / " << monster.mpMax << endl;
					cout << "획득 경험치 : " << monster.exp << "\t획득 골드 : " << monster.goldMin << " ~ " << monster.goldMax << endl << endl;

					cout << "========== 행동 ==========" << endl;
					cout << "1. 공격" << endl;
					cout << "2. 도망가기" << endl;
					cout << "행동을 선택하세요." << endl;
					cin >> menu;

					if (cin.fail())
					{
						cin.clear();
						cin.ignore(1024, '\n');
						continue;
					}

					else if (menu == BATTLE_BACK)
					{
						break;
					}

					switch (menu)
					{
					case BATTLE_ATTACK:
						int attack = rand() % (player.attackMax - player.attackMin + 1) + (player.attackMin);
						int armor = rand() % (monster.armorMax - monster.armorMin + 1) + (monster.armorMin);

						int damage = attack - armor;

						// 삼항연산자 : 조건식 ? true일 때 값, : false 일 때 값이 된다.
						// 최소 데미지를 음수가 되지 않고 1로 설정
						damage = damage < 1 ? 1 : damage;

						// 몬스터 HP를 감소시킨다.
						monster.hp -= damage;

						cout << player.name << "가 " << monster.name << "에게 " << damage << "의 피해를 입혔습니다." << endl;

						// 몬스터가 죽음
						if (monster.hp <= 0)
						{
							cout << monster.name << " 몬스터가 사망하였습니다." << endl;

							player.exp += monster.exp;
							int gold = (rand() % monster.goldMax - monster.goldMin + 1) + monster.goldMin;
							player.inventory.gold += gold;

							cout << monster.exp << "의 경험치를 획득하였습니다." << endl;
							cout << gold << "의 골드를 획득하였습니다." << endl;

							// 몬스터 스탯을 초기화
							monster.hp = monster.hpMax;
							monster.mp = monster.mpMax;

							system("pause");
							break;
						}

						// 몬스터가 살아있으면 플레이어를 공격
						attack = rand() % (monster.attackMax - monster.attackMin + 1) + (monster.attackMin);
						armor = rand() % (player.armorMax - player.armorMin + 1) + (player.armorMin);

						damage = attack - armor;

						damage = damage < 1 ? 1 : damage;

						// 플레이어 HP를 감소시킨다.
						player.hp -= damage;

						cout << monster.name << "가 " << player.name << "에게 " << damage << "의 피해를 입혔습니다." << endl;

						// 플레이어가 죽었을 경우
						if (player.hp <= 0)
						{
							cout << "플레이어가 " << monster.name << "에게 사망하였습니다." << endl;

							// 죽으면 경험치와 골드가 10% 깎인다
							cout << (player.exp * 0.1f) << "경험치를 잃었습니다." << endl;
							cout << (player.inventory.gold * 0.1f) << "골드를 잃었습니다." << endl;
							
							player.exp = player.exp - (player.exp * 0.1f);
							player.inventory.gold = player.inventory.gold - (player.inventory.gold * 0.1f);

							// 플레이어 부활
							player.hp = player.hpMax;
							player.mp = player.mpMax;
						}
						system("pause");

						break;
					}
				}
			}
			break;
		case MM_STORE:
			while (true)
			{
				system("cls");

				cout << "========== 상점 ==========" << endl;
				cout << "1. 무기 상점" << endl;
				cout << "2. 방어구 상점" << endl;
				cout << "3. 뒤로 가기" << endl;
				cout << "상점을 선택하세요 : ";
				cin >> menu;

				if (cin.fail())
				{
					cin.clear();
					cin.ignore(1024, '\n');
					continue;
				}

				else if (menu == SM_BACK)
				{
					break;
				}
 					
				else if (menu < SM_NONE || menu > SM_BACK)
				{
					cout << "잘못된 입력입니다. 다시 시도해주세요." << endl;
					system("pause");
					continue;
				}				

				switch (menu)
				{
				case SM_WEAPON:
					while (true)
					{
						system("cls");
						cout << "=========== 무기 상점 ==========" << endl;
						for (int i = 0; i < STORE_WEAPON_MAX; ++i)
						{
							cout << i + 1 << "번 무기 : " << storeWeaponArr[i].name << endl;
							cout << "공격력 : " << storeWeaponArr[i].min << " ~ " << storeWeaponArr[i].max << endl;
							cout << "구매 가격 : " << storeWeaponArr[i].price << " 골드" << endl;
							cout << "판매 가격 : " << storeWeaponArr[i].sell << " 골드" << endl;
							cout << "특징 : " << storeWeaponArr[i].description << endl;
							cout << "-----------------------------------------" << endl;
						}
						cout << "뒤로가기 : 4번을 누르세요." << endl;
						cout << "구매할 아이템을 선택하시오 : ";
						cout << "현재 소지금 : " << player.inventory.gold << endl;
						cout << "가방 남은 자리 : " << int(INVENTORY_MAX - player.inventory.itemCount) << " / " << INVENTORY_MAX << endl; 

						cin >> menu;

						if (cin.fail())
						{
							cin.clear();
							cin.ignore(1024, '\n');
							continue;
						}

						else if (menu < SM2_NONE || menu > SM2_BACK)
						{
							cout << "잘못된 입력입니다. 다시 시도해주세요." << endl;
							system("pause");
							continue;
						}

						switch (menu)
						{							
						case SM2_LIST1:
							if (player.inventory.itemCount >= INVENTORY_MAX)
							{
								cout << "인벤토리가 모두 찼습니다. 상점을 이용할 수 없습니다." << endl;
								system("pause");
								continue;
							}
							if (player.inventory.gold < storeWeaponArr[0].price)
							{
								cout << "소지금이 부족합니다." << endl;
								system("pause");
								continue;
							}
							cout << storeWeaponArr[0].name << "을 구매하셨습니다." << endl;
							player.inventory.gold -= storeWeaponArr[0].price;

							// 무기 바로 장착
							player.attackMin += storeWeaponArr[0].min;
							player.attackMax += storeWeaponArr[0].max;

							// inventory에 아이템 넣기
							player.inventory.itemArr[player.inventory.itemCount++] = storeWeaponArr[0];

							cout << "현재 소지금 : " << player.inventory.gold << endl;
							break;
						case SM2_LIST2:
							if (player.inventory.itemCount >= INVENTORY_MAX)
							{
								cout << "인벤토리가 모두 찼습니다. 상점을 이용할 수 없습니다." << endl;
								system("pause");
								continue;
							}
							if (player.inventory.gold < storeWeaponArr[1].price)
							{
								cout << "소지금이 부족합니다." << endl;
								system("pause");
								continue;
							}
							cout << storeWeaponArr[1].name << "을 구매하셨습니다." << endl;
							player.inventory.gold -= storeWeaponArr[1].price;

							// inventory에 아이템 넣기
							player.inventory.itemArr[player.inventory.itemCount++] = storeWeaponArr[1];

							// 무기 바로 장착
							player.attackMin += storeWeaponArr[1].min;
							player.attackMax += storeWeaponArr[1].max;

							cout << "현재 소지금 : " << player.inventory.gold << endl;
							break;
						case SM2_LIST3:
							if (player.inventory.itemCount >= INVENTORY_MAX )
							{
								cout << "인벤토리가 모두 찼습니다. 상점을 이용할 수 없습니다." << endl;
								system("pause");
								continue;
							}
							if (player.inventory.gold < storeWeaponArr[2].price)
							{
								cout << "소지금이 부족합니다." << endl;
								system("pause");
								continue;
							}
							cout << storeWeaponArr[2].name << "을 구매하셨습니다." << endl;
							player.inventory.gold -= storeWeaponArr[2].price;

							// 무기 바로 장착
							player.attackMin += storeWeaponArr[2].min;
							player.attackMax += storeWeaponArr[2].max;

							// inventory에 아이템 넣기
							player.inventory.itemArr[player.inventory.itemCount++] = storeWeaponArr[2];

							cout << "현재 소지금 : " << player.inventory.gold << endl;
							break;
						case SM2_BACK:	
							break;
						}	
						break;
					}			

					break;
				case SM_ARMOR:					
					while (true)
					{
						system("cls");
						cout << "=========== 갑옷 상점 ==========" << endl;
						for (int i = 0; i < STORE_ARMOR_MAX; ++i)
						{
							cout << i + 1 << "번 무기 : " << storeArmorArr[i].name << endl;
							cout << "공격력 : " << storeArmorArr[i].min << " ~ " << storeWeaponArr[i].max << endl;
							cout << "구매 가격 : " << storeArmorArr[i].price << " 골드" << endl;
							cout << "판매 가격 : " << storeArmorArr[i].sell << " 골드" << endl;
							cout << "특징 : " << storeArmorArr[i].description << endl;
							cout << "-----------------------------------------" << endl;
						}

						cout << "구매할 아이템을 선택하시오 : ";
						cin >> menu;

						if (cin.fail())
						{
							cin.clear();
							cin.ignore(1024, '\n');
							continue;
						}

						else if (menu < SM2_NONE || menu > SM2_BACK)
						{
							cout << "잘못된 입력입니다. 다시 시도해주세요." << endl;
							system("pause");
							continue;
						}

						switch (menu)
						{							
						case SM2_LIST1:
							if (player.inventory.itemCount >= INVENTORY_MAX)
							{
								cout << "인벤토리가 모두 찼습니다. 상점을 이용할 수 없습니다." << endl;
								system("pause");
								continue;
							}
							if (player.inventory.gold < storeArmorArr[0].price)
							{
								cout << "소지금이 부족합니다." << endl;
								system("pause");
								continue;
							}
							cout << storeArmorArr[0].name << "을 구매하셨습니다." << endl;
							player.inventory.gold -= storeArmorArr[0].price;

							// 무기 바로 장착
							player.armorMin += storeArmorArr[0].min;
							player.armorMax += storeArmorArr[0].max;

							// inventory에 아이템 넣기
							player.inventory.itemArr[player.inventory.itemCount++] = storeArmorArr[0];

							cout << "현재 소지금 : " << player.inventory.gold << endl;
							break;
						case SM2_LIST2:
							if (player.inventory.itemCount >= INVENTORY_MAX)
							{
								cout << "인벤토리가 모두 찼습니다. 상점을 이용할 수 없습니다." << endl;
								system("pause");
								continue;
							}
							if (player.inventory.gold < storeArmorArr[1].price)
							{
								cout << "소지금이 부족합니다." << endl;
								system("pause");
								continue;
							}
							cout << storeArmorArr[1].name << "을 구매하셨습니다." << endl;
							player.inventory.gold -= storeArmorArr[1].price;

							// inventory에 아이템 넣기
							player.inventory.itemArr[player.inventory.itemCount++] = storeArmorArr[1];

							// 무기 바로 장착
							player.armorMin += storeArmorArr[1].min;
							player.armorMax += storeArmorArr[1].max;

							cout << "현재 소지금 : " << player.inventory.gold << endl;
							break;
						case SM2_LIST3:
							if (player.inventory.itemCount >= INVENTORY_MAX)
							{
								cout << "인벤토리가 모두 찼습니다. 상점을 이용할 수 없습니다." << endl;
								system("pause");
								continue;
							}
							if (player.inventory.gold < storeArmorArr[2].price)
							{
								cout << "소지금이 부족합니다." << endl;
								system("pause");
								continue;
							}
							cout << storeArmorArr[2].name << "을 구매하셨습니다." << endl;
							player.inventory.gold -= storeArmorArr[2].price;

							// 무기 바로 장착
							player.armorMin += storeArmorArr[2].min;
							player.armorMax += storeArmorArr[2].max;

							// inventory에 아이템 넣기
							player.inventory.itemArr[player.inventory.itemCount++] = storeArmorArr[2];

							cout << "현재 소지금 : " << player.inventory.gold << endl;
							break;
						case SM2_BACK:
							break;
						}
						break;
					}
					break;
				}

				cout << "========== 플레이어 ==========" << endl;
				cout << "이름 : " << player.name << "\t직업 : " << player.className << endl;
				cout << "레벨 : " << player.level << "\t경험치 : " << player.exp << endl;
				cout << "공격력 : " << player.attackMin << " ~ " << player.attackMax << endl;
				cout << "방어력 : " << player.armorMin << " ~ " << player.armorMax << endl;
				cout << "체력 : " << player.hp << " / " << player.hpMax << "\t마나 : " << player.mp << " / " << player.mpMax << endl;
				cout << "소지금 : " << player.inventory.gold << endl << endl;
				cout << "가방 남은 자리 : " << int(INVENTORY_MAX - player.inventory.itemCount) << " / " << INVENTORY_MAX << endl;

				system("pause");
				continue;
			}

			break;
		case MM_INVENTORY:
			system("cls");
			cout << "========== 현재 소지품 목록 ==========" << endl;
			cout << "가방 남은 자리 : " << int(INVENTORY_MAX - player.inventory.itemCount) << " / " << INVENTORY_MAX << endl;
			for (int i = 0; i < player.inventory.itemCount; ++i)
			{
				cout << player.inventory.itemArr[i].name << endl;
			}

			cout << "골드 : " << player.inventory.gold << endl;
			system("pause");
			break;
		}
	}


	return 0;
}

/*
숙제
1. 무기상점에서 판매할 아이템 목록 만들기 그리고 출력
2. 출력할 대 앞에 번호를 부여해주고 번호를 입력, 구매
3. 인벤토리기 꽉 차면 구매 불가
4. 가방을 선택하면 가방 안의 아이템을 보여준다.
*/

날짜 : 190516

주제 : 구조체와 문자열 함수를 통해서 학생 관리 시스템을 만든다.

특징 :

cin의 기능과 c의 문자열 함수들을 통해 구조체 문자열에 문자를 입력한다. 

메뉴 기능을 구현한다.

 

#include <iostream>

using namespace std;

#define NAME_SIZE 32
#define ADDRESS_SIZE 128
#define PHONE_SIZE 14 
#define STUDENT_MAX 10

struct _tagStudent
{
	char	name[NAME_SIZE];
	char	address[ADDRESS_SIZE];
	char	phoneNumber[PHONE_SIZE];
	int number;
	int kor;
	int eng;
	int math;
	int total;
	float average;
};

enum MENU
{
	MENU_NONE,
	MENU_INSERT,
	MENU_DELETE,
	MENU_SEARCH,
	MENU_OUTPUT,
	MENU_EXIT
};

int main()
{
	_tagStudent studentArr[STUDENT_MAX] = {};
	int studentCount = 0;
	int studentNum = 1;
	char	searchName[NAME_SIZE] = {};
	char	deleteName[NAME_SIZE] = {};

	while (true)
	{
		system("cls");

		// 메뉴를 출력
		cout << "1. 학생 등록" << endl;
		cout << "2. 학생 삭제" << endl;
		cout << "3. 학생 탐색" << endl;
		cout << "4. 학생 출력" << endl;
		cout << "5. 종료" << endl;
		cout << "메뉴를 선택하세요 : ";
		int menu;
		cin >> menu;

		// cin은 만약 오른쪽에 실수로 문자를 입력할 경우 에러 발생
		// 그렇기 때문에 예외처리를 해준다.
		// 에러가 발생하면 cin 내부의 에러버퍼를 비워주고
		// (입력버퍼 : 입력한 값을 저장해놓고 그 값을 변수에 넣어주는 역할)
		// 이 입력버퍼에 '\n'이 남아있으므로 버퍼를 순회하여 '\n'를 지워준다.
		
		// fail() 입력 에러가 발생했을 경우 true 반환
		if (cin.fail())
		{
			cin.clear(); // 에러버퍼 비우기

			// 입력버퍼에 '/n'이 남아 있으므로 입력버퍼를 검색하여 '\n'를 삭제
			// 첫번째 : 검색하고자 하는 버퍼 크기를 지정. 넉넉히 1024
			// 두번쨰 : 찾고자하는 문자를 넣어준다. 그 문자까지 이동해서 삭제
			cin.ignore(1024, '\n');
			continue;
		}

		if (menu == MENU_EXIT)
			break;

		switch (menu)
		{
		case MENU_INSERT:
			system("cls");
			cout << "========== 학생 추가 ==========" << endl;
			// 학생 수가 모두 찬 경우
			if (studentCount == STUDENT_MAX)
				break;

			// 학생정보를 추가(이름, 주소, 학번, 전화번호)
			// 국어 영어 수학 점수는 입력받는다. 학번, 총점, 평균은 연산된다
			cout << "이름 : ";
			cin >> studentArr[studentCount].name;

			// cin과 cin.getline을 같이 쓸 때 주의해야 한다... 
			// cin이기 때문에 콘솔에서 입력을 하고 엔터를 친 값을 입력한다.
			// 그러면 cin의 eofbit가 unset 상태로 된다.
			// 그리고 cin의 위치는 cin >> studentArr[studentNum].name;의 가장 마지막인
			// 그래서 '\n'을 가르킨다. 이상태에서 getline을 하면 '\n'을 읽으려고 한다.
			// 따라서 '\n'을 찾아서 지워야함.
			// 또는 대신 cin >> std::ws;을 써서 '\n'을 자연스레 넘어가서
			// 다음 오는 getline을 정상적으로 읽는다.
			cin.ignore(1024, '\n');

			cout << "주소 : ";
			// getline()은 뉴라인 문자를 입력스트림에서 버린다.
			cin.getline(studentArr[studentCount].address, ADDRESS_SIZE);

			cout << "전화번호 : " << endl;
			cin.getline(studentArr[studentCount].phoneNumber, PHONE_SIZE);

			cout << "국어 점수 : ";
			cin >> studentArr[studentCount].kor;

			cout << "영어 점수 : ";
			cin >> studentArr[studentCount].eng;

			cout << "수학 점수 : ";
			cin >> studentArr[studentCount].math;

			studentArr[studentCount].total = studentArr[studentCount].kor + studentArr[studentCount].eng + studentArr[studentCount].math;
			studentArr[studentCount].average = studentArr[studentCount].total / 3.f;

			studentArr[studentCount].number = studentNum;

			++studentNum;
			++studentCount;
			break;
		case MENU_DELETE:
			cout << "========== 학생 삭제 ==========" << endl;
			cout << "지울 이름을 입력하세요 : ";
			cin >> std::ws;
			cin.getline(deleteName, NAME_SIZE);

			// 등록되어 있는 학생 수만큼 반복
			for (int i = 0; i < studentCount; ++i)
			{
				// 학생을 찾았을 경우
				if (strcmp(studentArr[i].name, deleteName) == 0)
				{
					for (int j = i; j < studentCount- 1; ++j)
					{
						studentArr[i] = studentArr[i + 1];
					}
					--studentCount;					
					
					cout << "학생 정보가 삭제되었습니다." << endl;
					break;
				}
			}

			break;
		case MENU_SEARCH:
			system("cls");

			cout << "========== 학생 탐색 ==========" << endl;
			
			//cin.ignore(1024, '\n');
			cout << "탐색할 이름을 입력하세요 : ";
			cin >> std::ws;
			
			cin.getline(searchName, NAME_SIZE);

			// 등록되어 있는 학생 수만큼 반복
			for (int i = 0; i < studentCount; ++i)
			{
				// 학생을 찾았을 경우
				if (strcmp(studentArr[i].name, searchName) == 0)
				{
					cout << "이름 : " << studentArr[i].name << endl;
					cout << "전화번호 : " << studentArr[i].phoneNumber << endl;
					cout << "주소 : " << studentArr[i].address << endl;
					cout << "학번 : " << studentArr[i].number << endl;
					cout << "국어 : " << studentArr[i].kor << endl;
					cout << "영어 : " << studentArr[i].eng << endl;
					cout << "수학 : " << studentArr[i].math << endl;
					cout << "총점 : " << studentArr[i].total << endl;
					cout << "평균 : " << studentArr[i].average << endl << endl;
					break;
				}
			}
			break;
		case MENU_OUTPUT:
			system("cls");
			cout << "========== 학생 출력 ==========" << endl;
			// 등록된 학생 수만큼 반복
			for (int i = 0; i < studentCount; ++i)
			{
				cout << "이름 : " << studentArr[i].name << endl;
				cout << "전화번호 : " << studentArr[i].phoneNumber << endl;
				cout << "주소 : " << studentArr[i].address << endl;
				cout << "학번 : " << studentArr[i].number << endl;
				cout << "국어 : " << studentArr[i].kor << endl;
				cout << "영어 : " << studentArr[i].eng << endl;
				cout << "수학 : " << studentArr[i].math << endl;
				cout << "총점 : " << studentArr[i].total << endl;
				cout << "평균 : " << studentArr[i].average << endl << endl;

			}

			break;
		default:
			cout << "메뉴를 잘못 선택했습니다." << endl;
			break;
		}

		system("pause");
	}

	return 0;
}

/* 숙제 : 관리 프로그램
도서 대여 프로그램 만들기
1. 책 등록
2. 책 대여
3. 책 반납
4. 책 목록
4. 종료

책 구조체는 책이름, 대여금액, 책번호, 대여여부
책목록을 선택하면 책 정보를 모두 출력
*/

 

 

 

날짜 : 190514

주제 : 빙고게임과 AI 구현

 

특징 :

난이도 쉬움의 AI는 랜덤의 숫자를 넣은 배열을 만들고 0부터 뽑는다.

난이도 어려움의 AI는 평가 변수를 위한 배열을 만든다. 예를 들어, 그 줄에 숫자가 이미 하나 체크가 되면 점수가 1점 오른다. 만약 4개의 숫자가 체크 되어 있으면 4점을 획득한다. 세로인 경우와 대각선의 경우, 점수가 중첩되고 가장 높은  점수를 가진 배열에 있는 숫자를 AI가 체크한다.

 

단점은 이것을 위해 시간복잡도 계산이 되어 있지 않아서 효율적인가에 대해서 문제가 있을 수 있다.

#include <iostream>
#include "time.h"
#include "conio.h"

using namespace std;

/*

혼자 하는 빙고게임 만들기!!!

숫자는 1 ~ 25

5 줄 빙고를 완성하면 게임 끝

0을 입력하면 게임 종료!

*/

/*

AI EASY 모드는 랜덤으로 숫자 선택

AI HARD 모드는 각 배열 요소에 점수를 넣어주는 방식.

그리고 점수가 가장 높은 요소를 빙고숫자로 선택

*/


int main()
{
	int arr[25];	// 플레이어의 빙고판
	int arrAI[25];	// AI의 빙고판

	// 빙고판에 숫자 넣기
	for (int i = 0; i < 25; ++i)
	{
		arr[i] = i + 1;
		arrAI[i] = i + 1;
	}

	srand((unsigned int)time(0));

	// 숫자 SHUFFLE
	for (int i = 0; i < 100; ++i)
	{
		// Player
		int idx1 = rand() % 25; // 0 에서 24의 숫자가 랜덤생성
		int idx2 = rand() % 25;
		int temp;

		temp = arr[idx1];
		arr[idx1] = arr[idx2];
		arr[idx2] = temp;

		// AI
		idx1 = rand() % 25; // 0 에서 24의 숫자가 랜덤생성
		idx2 = rand() % 25;

		temp = arrAI[idx1];
		arrAI[idx1] = arrAI[idx2];
		arrAI[idx2] = temp;
	}



	// AI의 픽 설정 <쉬움>
	// 쉬운 AI
	int easyAI;
	int easyAIPicks[25];

	for (int i = 0; i < 25; ++i)
	{
		easyAIPicks[i] = i + 1;
	}

	for (int i = 0; i < 100; ++i)
	{
		int idx1 = rand() % 25;
		int idx2 = rand() % 25;
		int temp;

		temp = easyAIPicks[idx2];
		easyAIPicks[idx2] = easyAIPicks[idx1];
		easyAIPicks[idx1] = temp;
	}	



	enum AI_MODE {
		AI_EASY = 1,
		AI_HARD
	};

	
	int count = 0;	// 진행 횟수	
	int inputDifficulty = 0;	// 난이도
	bool levelIsNotChecked = true;

	int aiPick = 0;
	int aiIndex = 0;	// 쉬운 AI index
	int assessmentArr[25] = {};	// AI 평가점수 배열

	while (true)
	{
		while (levelIsNotChecked == true)
		{
			system("cls");
			cout << " 난이도를 선택 하세요..." << endl;
			cout << " 1 : 쉬움" << endl;
			cout << " 2 : 어려움" << endl;

			cin >> inputDifficulty;

			if (inputDifficulty < AI_EASY || AI_HARD < inputDifficulty)
			{
				continue;
			}
			else
			{
				levelIsNotChecked = false;
			}
		}

		// 빙고판 프린트
		system("cls");
		if (inputDifficulty == AI_EASY) cout << "[ 난 이 도 : EASY ]" << endl;
		if (inputDifficulty == AI_HARD) cout << "[ 난 이 도 : HARD ]" << endl;

		cout << "============= Player =============" << endl;
		for (int i = 0; i < 5; ++i)
		{
			for (int j = 0; j < 5; ++j)
			{
				if (arr[i * 5 + j] == 0)	cout << "■" << "\t";
				else                        cout << arr[i * 5 + j] << "\t";
			}
			cout << endl << endl;
		}

		cout << "============== A  I ==============" << endl;
		for (int i = 0; i < 5; ++i)
		{
			for (int j = 0; j < 5; ++j)
			{
				if (arrAI[i * 5 + j] == 0)	cout << "■" << "\t";
				else                        cout << arrAI[i * 5 + j] << "\t";


			}
			cout << endl << endl;
		}

		// AI의 평가배열 점수판을 출력
		cout << "========== AI DEBUGGING ==========" << endl;
		for (int i = 0; i < 5; ++i)
		{
			for (int j = 0; j < 5; ++j)
			{
				cout << assessmentArr[i * 5 + j] << "\t";
			}
			cout << endl << endl;
		}
		cout << "==================================" << endl;	



		// 빙고 판정
		int bingoCount = 0;
		int bingoCountAI = 0;

		// 가로 판정
		for (int i = 0; i < 5; ++i)
		{
			int sum = arr[i * 5] + arr[i * 5 + 1] + arr[i * 5 + 2] + arr[i * 5 + 3] + arr[i * 5 + 4];
			int sumAI = arrAI[i * 5] + arrAI[i * 5 + 1] + arrAI[i * 5 + 2] + arrAI[i * 5 + 3] + arrAI[i * 5 + 4];

			if (sum == 0)	++bingoCount;
			if (sumAI == 0)	++bingoCountAI;
		}
		// 세로 판정
		for (int i = 0; i < 5; ++i)
		{
			int sum = arr[i] + arr[i + 1 * 5] + arr[i + 2 * 5] + arr[i + 3 * 5] + arr[i + 4 * 5];
			int sumAI = arrAI[i] + arrAI[i + 1 * 5] + arrAI[i + 2 * 5] + arrAI[i + 3 * 5] + arrAI[i + 4 * 5];

			if (sum == 0)	++bingoCount;
			if (sumAI == 0)	++bingoCountAI;
		}

		// 대각선 판정 1
		int sum = arr[0] + arr[6] + arr[12] + arr[18] + arr[24];
		int sumAI = arrAI[0] + arrAI[6] + arrAI[12] + arrAI[18] + arrAI[24];

		if (sum == 0)	++bingoCount;
		if (sumAI == 0)	++bingoCountAI;

		// 대각선 판정 2
		sum = arr[4] + arr[8] + arr[12] + arr[16] + arr[20];
		sumAI = arrAI[4] + arrAI[8] + arrAI[12] + arrAI[16] + arrAI[20];

		if (sum == 0)	++bingoCount;
		if (sumAI == 0)	++bingoCountAI;

		// bingo 수 체크
		if (bingoCount >= 5 && bingoCountAI >= 5)
		{
			cout << "와우 비기셨습니다." << endl;
			break;
		}
		if (bingoCount >= 5 && bingoCountAI < 5)
		{
			cout << "Player : 5 빙고 승리!@@!!@!@" << endl;
			break;
		}
		if (bingoCountAI >= 5 && bingoCount < 5)
		{
			cout << "A I : 5 빙고 승리...... ㅠㅠ" << endl;
			break;
		}



		// UI Text
		cout << count << " 회차"
			<< "\t플레이어 빙고 : " << bingoCount << "개 VS "
			<< "A I 빙고 : " << bingoCountAI << " 개" << endl << endl;
		cout << "AI의 PICK : " << aiPick << endl << endl;
		for (int i = 0; i < 25; ++i)
		{
			cout << easyAIPicks[i] << " ";
		}
		cout << endl << endl;
		cout << "1~25 사이의 숫자를 입력하시오(0 : 종료)" << endl;



		// 플레이어 입력
		int player;
		cin >> player;

		if (player != 0)
		{
			for (int i = 0; i < 25; ++i)
			{
				if (player == arr[i])
				{
					arr[i] = 0;
					break;
				}
			}
		}
		else
		{
			break;
		}

		// 쉬운 AI
		if (inputDifficulty == AI_EASY)
		{
			for (int i = 0; i < 25; ++i)
			{
				if (player == arrAI[i])
				{
					arrAI[i] = 0;
					break;
				}
			}

			// 픽 pool에 동기화
			for (int i = 0; i < 25; ++i)
			{
				if (player == easyAIPicks[i])
				{
					easyAIPicks[i] = 0;					
				}
			}

			while (easyAIPicks[aiIndex] == 0) // 이미 player가 체크한 숫자 지우기
			{
				++aiIndex;
			}

			aiPick = easyAI = easyAIPicks[aiIndex]; // easyAIPicks에서 하나씩 사용

			// 플레이어 빙고판에 AI의 숫자 체크
			for (int i = 0; i < 25; ++i)
			{
				if (easyAI == arrAI[i])
				{
					arrAI[i] = 0;
				}
				if (easyAI == arr[i])
				{
					arr[i] = 0;
					++count;
				}
			}

			++aiIndex;
		}

		// 어려운 AI
		else if (inputDifficulty == AI_HARD)
		{		
			// 어려운 AI 초기화
			for (int i = 0; i < 0; ++i)
			{
				assessmentArr[i] = 0;
			}
			
			// 동기화
			for (int i = 0; i < 25; ++i)
			{
				if (player == arrAI[i])
				{
					arrAI[i] = 0;
					break;
				}
			}

			int hardAI;

			// 가로 평가
			for (int i = 0; i < 5; ++i)
			{
				int checkCount = 0; // 빙고체크한 횟수
				for (int j = 0; j < 5; ++j)
				{					
					if (arrAI[i * 5 + j] == 0)	checkCount++;
				}
				// 그 줄 모두가 점수를 획득
				assessmentArr[i * 5] = assessmentArr[i * 5 + 1] = assessmentArr[i * 5 + 2] = assessmentArr[i * 5 + 3] = assessmentArr[i * 5 + 4] = checkCount;
			}

			// 세로 평가
			for (int i = 0; i < 5; ++i)
			{
				int checkCount = 0;
				for (int j = 0; j < 5; ++j)
				{
					if (arrAI[i + j * 5] == 0)	++checkCount;
				}
				// 그 줄 모두가 점수를 획득
				assessmentArr[i] += checkCount;
				assessmentArr[i + 1 * 5] += checkCount;
				assessmentArr[i + 2 * 5] += checkCount;
				assessmentArr[i + 3 * 5] += checkCount;
				assessmentArr[i + 4 * 5] += checkCount;
			}

			// 대각선 평가(왼쪽에서 오른)			
			int checkCount = 0;

			for (int i = 0; i < 5; ++i)
			{				
				if (arrAI[i * 6] == 0)	++checkCount;
			}

			// 그 줄 모두가 점수를 획득
			for (int i = 0; i < 5; ++i)
			{
				assessmentArr[i * 6] += checkCount;
			}

			// 대각선 평가(오른쪽에서 왼)
			checkCount = 0;
			for (int i = 0; i < 5; ++i)
			{
				if (arrAI[4 + i * 4] == 0)	++checkCount;
			}

			// 그 줄 모두가 점수를 획득
			for (int i = 0; i < 5; ++i)
			{
				assessmentArr[4 + i * 4] += checkCount;
			}

			hardAI = 0; // AI가 선택할 빙고판의 INDEX
			int hardAINum = 0; // 평가 점수 변수
			for (int i = 0; i < 25; ++i)
			{
				// 가장 점수가 높지만 이미 체크가 된 숫자가 아닌 숫자를 찾기!
				if (assessmentArr[i] > hardAINum && arrAI[i] != 0)
				{
					hardAINum = assessmentArr[i]; // 점수 저장
					hardAI = i;					  // index 저장
				}
			}
			
			// 가장 큰 점수를 가진 index를 bingo check
			aiPick = arrAI[hardAI];

			// 플레이어 빙고판에 AI의 숫자 체크
			for (int i = 0; i < 25; ++i)
			{
				if (aiPick == arrAI[i])
				{
					arrAI[i] = 0;
				}
				if (aiPick == arr[i])
				{
					arr[i] = 0;
					++count;
				}
			}
		}
	}

	cout << "게임이 종료되었습니다." << endl;

	system("pause");

	return 0;
}

날짜 : 190512

주제 : 숫자퍼즐게임

GitHub :

main2.cpp 파일입니다.

https://github.com/crobbit-kent/CPP_BASIC_PRACTICE/tree/master/baseball/baseball 

 

 

#include <iostream> 
#include "time.h" 
#include "conio.h" // 콘솔창에서 입출력하는 기능들을 제공해주는 헤더파일 

using namespace std; 

int main() 
{ 
// 강의 15화 : 숫자퍼즐게임 
srand((unsigned int)time(0)); 

int iNumbers[25] = {}; 

for (int i = 0; i < 24; ++i) 
{ 
iNumbers[i] = i + 1; // 1~24 
} 

// 가장 마지막 칸은 공백으로 비워둔다. 공백을 의미하는 값으로 특수한 값을 사용할 예정 
// INT_MAX라는 값은 int의 최대값 
iNumbers[24] = INT_MAX; // 값을 보기 위해서는 클릭한 후 f12를 클릭해본다. 

// 별이 있는 위치를 저장할 변수를 만든다. 
int iStarIndex = 24; 
int iIndex; 

// 인덱스 : 0 ~ 23 
int iTemp, idx1, idx2; 

for (int i = 0; i < 100; ++i) 
{ 
idx1 = rand() % 24; 
idx2 = rand() % 24; 

//iTemp = iNumbers[idx1]; 
//iNumbers[idx1] = iNumbers[idx2]; 
//iNumbers[idx2] = iTemp; 
} 
  
while(true) 
{ 
system("cls"); 
for (int i = 0; i < 5; ++i) 
{ 
for (int j = 0; j < 5; ++j) 
{ 
if (iNumbers[5 * i + j] == INT_MAX) 
{ 
cout << "*\t"; 
} 
else 
cout << iNumbers[5 * i + j] << "\t"; 
} 

cout << endl; 
} 

bool bWin = true; 

// 퍼즐을 맞추었는지 체크 
for (int i = 0; i < 24; ++i) 
{ 
if (iNumbers[i] != i + 1) 
{ 
bWin = false; 
break; 
} 
} 

if (bWin == true) 
{ 
cout << "축하합니다. 숫자를 모두 맞췄습니다!" << endl; 
break; 
} 

cout << "----------------------------------------------" << endl; 
cout << "W : 위, S : 아래, A : 왼쪽, D : 오른쪽, Q : 종료" << endl;  

// Enter를 치지 않더라도 문자를 누르는 순간 바로 그 문자를 반환하고 종료 
char cInput = _getch();  

if (cInput == 'q' || cInput == 'Q') 
break; 

// 이게 if보다 편하다 
switch (cInput) 
{ 
// 별을 '찾아서' 위로 이동시킨다. 
case 'w': 
case 'W': 
// 별이 가장 윗줄일 경우... 아무것도 작동하지 않는다. 
if (iStarIndex > 4) 
{ 
iNumbers[iStarIndex] = iNumbers[iStarIndex - 5]; 
iNumbers[iStarIndex - 5] = INT_MAX; 
iStarIndex -= 5; 
} 
break; 

case 's': 
case 'S': 
if (iStarIndex < 20) 
{ 
iNumbers[iStarIndex] = iNumbers[iStarIndex + 5]; 
iNumbers[iStarIndex + 5] = INT_MAX; 
iStarIndex += 5; 
} 
break; 

case 'a': 
case 'A': 
if ((iStarIndex % 5) != 0) 
{ 
iNumbers[iStarIndex] = iNumbers[iStarIndex - 1]; 
iNumbers[iStarIndex - 1] = INT_MAX; 
--iStarIndex; 
} 

break; 
case 'd': 
case 'D': 
if ((iStarIndex % 5) != 4) 
{ 
iNumbers[iStarIndex] = iNumbers[iStarIndex + 1]; 
iNumbers[iStarIndex + 1] = INT_MAX; 
++iStarIndex; 
} 

break; 
} 
} 

cout << endl << "게임을 종료합니다." << endl; 

system("pause"); 

return 0; 
} 

/* 
숙제 : 숫자빙고게임을 만들어보자... 

1~25까지의 숫자가 있고 이 숫자를 골고루 섞어서 5X5로 출력 
플레이어는 숫자를 입력받는다. 1~25 사이 
0을 입력하면 게임을 종료 

숫자를 입력받았으면 숫자목록 중 입력받은 숫자를 찾아서 *로 만들어준다 
숫자를 *로 만든 후에 빙고 줄 수를 체크한다. 5X5이기 때문에 가로 5 줄 세로 5 줄 대각선 2줄이 나올 수 있따. 
빙고줄이 몇줄인지 체크해서 화면에 보여준다. 
5줄 이상 빙고한 경우 게임을 종료. 
*/

+ Recent posts