C++ Project3

‍우건우·2024년 2월 15일

Jumble Game

#include<iostream>
#include<string>
#include<cstdlib>
#include<ctime>
using namespace std;

int main(void) {

	enum fields {WORD, HINT, NUM_FIELDS};
	const int NUM_WORDS = 5;
	const string WORDS[NUM_WORDS][NUM_FIELDS] = {
		{"wall","Do you feel you're banging your head against something?"},
		{"glasses","These might help you see the answer."},
		{"labored","Going slowly, is it?"},
		{"persistent","keep at it"},
		{"jumble","it's what the game is all about."}
	};

	enum difficulty{EASY, MEDIUM, HARD, NUM_DIFF_LEVELS};
	cout << "There are " << NUM_DIFF_LEVELS << " difficulty levels";

	srand(static_cast<unsigned int>(time(nullptr)));
	int choice = (rand() % NUM_WORDS);
	string theWord = WORDS[choice][WORD]; //정답 변수에 저장
	string theHint = WORDS[choice][HINT]; //힌트 변수에 저장

	string jumble = theWord; //만약 chice가 3이라면 jumble에는 persistent 저장

	int length = jumble.size();

	for (int i = 0; i < length; ++i) {
		int index1 = (rand() % length); //choice가 3이면 length는 10:index1 이 갖을 수 있는 값은 0~9
		int index2 = (rand() % length);
		char temp = jumble[index1]; //철자 교환
		jumble[index1] = jumble[index2];
		jumble[index2] = temp;
	}

	cout << "\t\tWelcome to Word Jumble" << endl << endl;
	cout << "Unscramble the letters to make a word" << endl;
	cout << "Enter 'hint' for a hint" << endl;
	cout << "Enter 'quit' to quit the game" << endl;
	cout << "The Jumble is : " << jumble;

	string guess;
	cout << "\n\nYour guess: ";
	cin >> guess;

	while ((guess != theWord) && guess != "quit") {

		if (guess == "hint")
			cout << theHint;
		else
			cout << "Sorry, that's not it";
		cout << "\n\nYour guess: ";
		cin >> guess;
	}
	if (guess == theWord)
		cout << endl << "That's it! You guessed it" << endl;
	
	cout << endl << "Thanks for playing" << endl;
	
	return 0;
}

표준 템플릿 라이브러리(STL: Standard Template Library)

  • STL에는 크게 세 가지 종류의 클래스 혹은 함수들이 들어 있습니다.
    1. 컨테이너(벡터,리스트,맵,셋 등)
    2. 이터레이터(Iterator)반복자
    3. 알고리즘(Algorithm)

벡터 : 배열과 유사하게 순차적으로 데이터를 저장하는 컨테이너

- 벡터 멤버 함수를 사용하여 시퀀스 요소를 조작
- 반복자를 사용하여 시퀀스 이동
- 알고리즘을 사용하여 요소 그룹 작업
  • 컨테이너를 사용하면 동일한 타입의 값 컬렉션을 저장하고 액세스할 수 있습니다.

  • 컨테이너는 단순하지만 신뢰할 수 있으며 배열보다 더 많은 유연성과 성능을 제공합니다.

  • 알고리즘은 컨테이너들과 함께 작동합니다.

  • 컨테이너 요소들을 분류하거나 검색, 복사, 병합, 삽입, 제거등을 알고리즘을 사용하여 처리할 수 있습니다.

  • 이터레이터는 컨테이너에서 요소를 식별하는 개체이며 요소 간에 이동하도록 조작할 수 있습니다.

배열에 비해 벡터를 사용했을 때 장점:

1. 벡터는 필요에 따라 증가할 수 있지만 배열은 크기를 변경할 수 없습니다.
2. STL 알고리즘은 벡터를 사용할 수 있지만 배열은 사용할 수 없습니다.

배열에 비해 벡터를 사용했을 때 단점:

1.벡터는 오버헤드로 약간의 여부 메모리를 필요로 합니다.
2.벡터의 크기가 커지면 성능 비용이 발생합니다.
3.환경에 따라 사용이 불가능할 수 있습니다.(예: 콘솔 환경)

벡터를 이용한 인벤토리 프로그램

#include<iostream>
#include<string>
#include<vector>

using namespace std;

int main(void) {

	vector<string> inventory;
	vector<int> intVec;
	inventory.push_back("sword"); //생성된 벡터 뒤쪽으로 데이터 추가	
	inventory.push_back("armor");
	inventory.push_back("sheild");

	cout << "You have" << inventory.size() << " items." << endl;

	cout << endl << "Your items: ";
	for (unsigned int i = 0; i < inventory.size(); ++i) {
		cout << inventory[i] << endl;
	}

	cout << endl << "The item name " << inventory[0] << " has";
	cout << inventory[0].size();

	cout << "\n격렬한 전투후 방패가 파괴되었습니다";
	inventory.pop_back();

	cout << endl << "Your items: " << endl;
	for (unsigned int i = 0; i < inventory.size(); ++i)
		cout << inventory[i] << endl;

	cout << "\n당신의 모든 아이템을 도적에게 빼았겼습니다.";
	inventory.clear();

	if (inventory.empty()) {
		cout << "\n당신의 인벤토리에는 아무것도 없습니다." << endl;
	}
	else
		cout << "\n당신은 적어도 하나의 아이템을 소유하고 있습니다." << endl;
}
	return 0;
}

이터레이터(반복자)

컨테이너를 최대한 활용하기 위해서는 이터레이터가 핵심입니다. 
이터레이터를 사용하면 시퀀스 컨테이너를 순회하는 것이 가능합니다.

이터레이터를 이용한 인벤토리 프로그램

#include<iostream>
#include<string>
#include<vector>

using namespace std;

int main(void) {

	std::vector<string> inventory;
	inventory.push_back("sword"); //생성된 벡터 뒤쪽으로 데이터 추가	
	inventory.push_back("armor");
	inventory.push_back("sheild");

	vector<string>::iterator myIterator;
	//문자열을 저장하는 벡터를 순회할 수 있는 반복자 객체생성
	vector<string>::const_iterator iter;
	//const타입의 반복자는 순회중인 대상의 값을 변경할 수 없다는 것이 일반 반복자와의 차이점

	cout << "Your items: "<< endl;
	for (iter = inventory.begin(); iter != inventory.end(); ++iter) {
		cout << *iter << endl;//이터레이터도 일종의 포인터이므로 역참조를 해야함
	}
	cout << "\nYou trade your sword for a battle axe";
	myIterator = inventory.begin();//인벤토리의 첫번째 요소가 들어있는 주소를 가리킴
	*myIterator = "battle axe";
	cout << "Your items: " << endl;

	for (iter = inventory.begin(); iter != inventory.end(); ++iter) {
		cout << *iter << endl;//이터레이터도 일종의 포인터이므로 역참조를 해야함
	}

	return 0;
}

알고리즘 사용

알고리즘은 검색, 무작위 추출, 정렬과 같은 일반적인 작업을 위해 존재합니다. 
알고리즘의 강력한 특징은 동일한 알고리즘은 컨테이너 타입이 다른 요소들과 함께 작동할 
수 있다는 점입니다.(즉, 컨테이너 종류에 상관없이 사용 가능합니다).

고득점 프로그램

#include<iostream>
#include<algorithm>
#include<vector>
#include<random>
#include<iterator>
using namespace std;

int main(void) {

	vector<int>::const_iterator iter;
	cout << "Creating a list of scores.";
	vector<int> scores;

	scores.push_back(1500);
	scores.push_back(3500);
	scores.push_back(7500);
	cout << "\nHigh scores: " << endl;
	for (iter = scores.begin(); iter != scores.end(); ++iter) {
		cout << *iter << endl;
	}

	cout << "\nFinging a score: ";
	int score;
	cout << "\nEnter a score to find: ";
	cin >> score;

	iter = find(scores.begin(), scores.end(), score);
	//만약에 iter가 가리키는 주소가 scores.end()의 주소와 같다면 찾는값이 없는 것
	if (iter != scores.end()) {
		cout << "Score fount" << endl;
	}
	else {
		cout << "Scores not found" << endl;
	}

	cout << "\nRandomize scores.";

	random_device rd;
	shuffle(scores.begin(), scores.end(), default_random_engine(rd()));
	
	cout << "\nHigh scores: " << endl;
	for (iter = scores.begin(); iter != scores.end(); ++iter) {
		cout << *iter << endl;
	}

	cout << "\nSorting scores.";
	sort(scores.begin(),scores.end());
	
	cout << "\nHigh scores: " << endl;
	for (iter = scores.begin(); iter != scores.end(); ++iter) {
		cout << *iter << endl;
	}

	return 0;
}

함수 만들기

-기본 인수(Default Parameter) 사용 : 함수의 매개변수가 거의 항상 같은 값을 전달 받는 경우에는 기본인수(호출과정에서 인수가 지정되지 않은 경우에 매개변수에 할당되는 값)를 사용하여 이 값을 지속으로 지정하는 작업을 최소화할 수 있습니다.
예를 들어 그래픽 디스플레이를 설정하는 함수가 있다고 가정해 보겠습니다. 매개변수 중 하나는 게임을 전체 화면으로 표현할지 아니면 창 모드로 표시할지를 함수에 알려주는 bool fullScreen 일 수 있습니다. 함수가 매우 자주 fullScreen에 대해 true로 호출된다고 생각하면 해당 매개변수에 기본 true인수를 부여하여 후출자가 이 디스플레이 설정 함수를 호출할 때마다 fullScreen으로 true를 전달하는 작업을 최소화 할 수 있습니다.
void setDisplay(int width,int height,boolfullScreen=true)

주의사항

파라미터 목록에 기본 인수를 지정하면 나머지 모든파라미터에 대해 기본 인수를 저장해야 함.
즉, 디폴트로 지정한 매개변수의 뒤의 매개변수들은 모두 디폴트로 지정해야함.

Default Parameter 활용

#include<iostream>
#include<string>
using namespace std;

int askNumber(int high, int low = 1); //하한치는 주로 1로 설정. 기본인수로 설정

int main(void) {

	int number = askNumber(5); //하한치는 디폴트값으로 설정되어 있어 호출시 생략가능

	cout << "Thanks for entering: " << number << endl << endl;

	number = askNumber(10, 5);

	cout << "Thanks for entering: " << number << endl << endl;

	return 0;
}

int askNumber(int high, int low) { //함수 정의부에서는 디폴트 값을 설정할 필요가 없습니다.
	int num;
	do {
		cout << "Please enter a number" << " (" << low << " - " << high << "): ";
		cin >> num;
	} while (num > high || num < low); //입력과정에서 입력한 값이 상한치를 넘거나 하한치보다 작으면 다시 입력

	return num;
}

오버로드 함수(Overloading function)

각 함수에 매개변수 목록과 하나의 반환 형식을 지정했습니다.
좀 더 다양한 함수를 표현하기 위해 여러 인수 집합을 사용할 수 있는 함수를 원한다면 어떨까요?
예를 들어, float로 표현되는 정점 집합에 대해 3차원 변환을 수행하는 두함수가 있다고 가정합시다.
이 함수에 대해 int로 표현되는 변환함수를 사용하기 원한다면 두 개의 다른 이름으로 두개의 개별
함수를 작성하는 대신 함수에 서로 다른 매개변수 목록을 처리할 수 있도록 함수 오버로딩을
사용할 수 있습니다. 이렇게 하면 하나의 함수를 호출하여 정점을 float 또는 int로 전달할 수 있습니다.
  • 오버로드된 함수를 만드려면 단순히 이름은 같고 파라미터 목록이 다른 함수를 여러개 작성하기만 하면 됩니다. 이때 함수의 리턴 타입에 대해서는 특별한 제한이 없습니다.

0개의 댓글