1. 문제

 

사람과 컴퓨터의 가위바위보 대결

 

사람과 컴퓨터가 가위바위보 게임을 하는 프로그램을 작성하라. 선수 이름은 프로그램 실행 초기에 키 입력받는다. 컴퓨터가 무엇을 낼지는 독자가 마음대로 프로그래밍하면 된다. 저자는 컴퓨터가 랜덤하게 내도록 코딩하였다. 사람이 키보드로부터 입력받고 <Enter> 키를 치면 곧바로 결과가 나온다. 가위, 바위, 보가 아닌 다른 문자를 입력하면 다시 입력받는다.

 

 

2. 결과

 

 

3. 코드

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

class AbstractPlayer {
	string name;
protected:
	string gbb[3];
public:
	AbstractPlayer(string name) {
		this->name = name;
		gbb[0] = "가위"; gbb[1] = "바위"; gbb[2] = "보";
	}
	virtual string turn() = 0;
	string getName() { return name; }
};

class Human : public AbstractPlayer {
public:
	Human(string name) : AbstractPlayer(name) { ; }
	string turn() {
		string gg;
		while (1) {
			cout << getName() << ">>";
			getline(cin, gg);
			if (gg == "가위" || gg == "바위" || gg == "보")
				return gg;
		}
	}
};

class Computer : public AbstractPlayer {
public:
	Computer() : AbstractPlayer("Computer") {
		srand((unsigned)time(0));
	}
	string turn() {
		int num = rand() % 3;
		return gbb[num];
	}
};

int main() {
	string name;

	cout << "***** 컴퓨터와 사람이 가위 바위 보 대결을 펼칩니다. *****" << endl;
	cout << "선수 이름을 입력하세요>>";
	getline(cin, name);

	Human h(name);
	Computer c;

	while (1) {
		string temp = h.turn();
		string com = c.turn();
		cout << c.getName() << ": " << com << endl;
		if (temp == com)
			cout << "the same" << endl;
		else if (temp == "바위") {
			if (com == "가위")
				cout << h.getName() << " is winner." << endl;
			else
				cout << c.getName() << " is winner." << endl;
		}
		else if (temp == "가위") {
			if (com == "보")
				cout << h.getName() << " is winner." << endl;
			else
				cout << c.getName() << " is winner." << endl;
		}
		else if (temp == "보") {
			if (com == "바위")
				cout << h.getName() << " is winner." << endl;
			else
				cout << c.getName() << " is winner." << endl;
		}
	}
}

 

 

4. 설명

 

컴퓨터일 경우 turn함수에서 가위, 바위, 보 중 랜덤한 것을 출력하도록 하였고

 

사람일 경우 값을 입력받아 가위, 바위, 보 중 하나가 아니면 무시하고 다시 한번 더 입력을 받고 이 중 하나라면 그 값을 저장, 컴퓨터와 비교하도록 하였다.

 

1. 문제

 

14. vector<Shape*> v;를 이용하여 간단한 그래픽 편집기를 콘솔 바탕으로 만들어보자. Shape과 Circle, Line, Rect 클래스는 다음과 같다. 생성된 도형 객체를 v에 삽입하고 관리하라. 9장 실습 문제 10번의 힌트를 참고하라.

 

그래픽 편집기의 기능은 "삽입", "삭제", "모두보기", "종료"의 4가지이고, 실행 과정은 다음과 같다.

 

2. 결과

 

 

3. 코드

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

class Shape {
protected:
	virtual void draw() = 0;
public:
	void paint() { draw(); }
};

class Circle : public Shape {
protected:
	virtual void draw() { cout << "Circle" << endl; }
};
class Rect : public Shape {
protected:
	virtual void draw() { cout << "Rectangle" << endl; }
};
class Line : public Shape {
protected:
	virtual void draw() { cout << "Line" << endl; }
};

class UI {
public:
	static int main_memu() {
		int n;
		cout << "삽입:1, 삭제:2, 모두보기:3, 종료:4 >> ";
		cin >> n;
		return n;
	}
	static int one_menu() {
		int n;
		cout << "선:1, 원:2, 사각형:3 >> ";
		cin >> n;
		return n;
	}
	static int two_menu() {
		int n;
		cout << "삭제하고자 하는 도형의 인덱스 >> ";
		cin >> n;
		return n;
	}
};

class GraphicEditor {
	vector<Shape*> v;
	vector<Shape*>::iterator it;

public:
	GraphicEditor() { ; }
	void create(int num) {
		switch (num) {
		case 1:
			v.push_back(new Line());
			break;

		case 2:
			v.push_back(new Circle());
			break;

		case 3:
			v.push_back(new Rect());
			break;
		}
	}
	void indelete(int num) {
		Shape *del;

		if (num < v.size()) {
			it = v.begin();
			for (int i = 0; i< num; i++)
				it++;
			del = *it;
			it = v.erase(it);
			delete del;
		}
		else
			cout << "인덱스를 잘못 입력하셨습니다." << endl;
	}
	void call() {
		bool exit = true;
		cout << "그래픽 에디터입니다." << endl;
		while (exit) {
			switch (UI::main_memu()) {
			case 1:
				create(UI::one_menu());
				break;
			case 2:
				indelete(UI::two_menu());
				break;
			case 3:
				for (int i = 0; i< v.size(); i++) {
					cout << i << ": ";
					v[i]->paint();
				}
				break;
			case 4:
				exit = false;
				break;
			}
		}
	}
};

int main() {
	GraphicEditor* editor = new GraphicEditor;
	editor->call();
	delete editor;
}

 

4. 설명

 

파일은 따로 분리하지 않았습니다.

 

9장 10번과

10장 13번 문제를 이해하셨다면 어려움 없이 풀 수 있는 문제였습니다.

 

1. 문제

 

13. vector를 이용하여 아래 Circle 클래스의 객체를 삽입하고 삭제하는 프로그램을 작성하라. 삭제 시에는 이름이 같은 모든 원을 삭제한다.

 

 

2. 결과

 

 

3. 코드

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

class Circle {
	string name;
	int radius;
public:
	Circle(int radius, string name) {
		this->radius = radius; this->name = name;
	}
	double getArea() { return 3.14*radius*radius; }
	string getName() { return name; }
};

int main() {
	vector<Circle*> v;
	vector<Circle*>::iterator it;

	int num, radius;
	string name;
	bool exit = true;

	cout << "원을 삽입하고 삭제하는 프로그램입니다." << endl;
	while (exit) {
		cout << "삽입:1, 삭제:2, 모두보기:3, 종료:4 >> ";
		cin >> num;
		//fflush(stdin);
		while(getchar() != '\n');
		switch (num) {
		case 1:
			cout << "생성하고자 하는 원의 반지름과 이름은 >> ";
			cin >> radius >> name;
			v.push_back(new Circle(radius, name));
			break;
		case 2:
			cout << "삭제하고자 하는 원의 이름은 >> ";
			getline(cin, name);
			it = v.begin();
			while (it != v.end()) {
				Circle *c = *it;
				if (c->getName() == name) {
					it = v.erase(it);
					delete c;
				}
				else
					it++;
			}
			break;
		case 3:
			for (it = v.begin(); it != v.end(); it++)
				cout << (*it)->getName() << endl;
			cout << endl;
			break;
		case 4:
			exit = false;
			break;
		}
	}

}

 

4. 설명

 

vector<Circle*> v;

 

vector<Circle*>::iterator it;

 

로 2개의 변수를 생성합니다.

 

힌트를 보시면 이해하시는데 큰 어려움은 없으실 겁니다.

 

1. 문제

 

12. Open Challenge를 수정하여 사용자가 어휘를 삽입할 수 있도록 기능을 추가하라.

실행 예는 다음과 같다.

 

 

2. 결과

 

 

3. 코드

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

class Word {
	string en;
	string ko;
public:
	Word() { en = ""; ko = ""; }
	Word(string en, string ko) {
		this->en = en; this->ko = ko;
	}
	void setEnKo(string en, string ko) { this->en = en; this->ko = ko; }
	string getEn() { return en; }
	string getKo() { return ko; }
};

int main() {

	vector<Word> v;
	Word w;
	v.push_back(Word("human", "인간"));
	v.push_back(Word("society", "사회"));
	v.push_back(Word("dall", "인형"));
	v.push_back(Word("emotion", "감정"));
	v.push_back(Word("painting", "그림"));
	v.push_back(Word("trade", "거래"));
	v.push_back(Word("animal", "동물"));
	v.push_back(Word("photo", "사진"));
	v.push_back(Word("bear", "곰"));

	srand((unsigned)time(0));
	int n1; string answer;
	string bogi[4]; for (int i = 0; i<4; i++) bogi[i] = "";
	int number[4]; for (int i = 0; i<4; i++) number[i] = 0;
	int i;
	bool exit = true, exit2 = true;
	int sel;
	string e, k;

	cout << "***** 영어 어휘 테스트를 시작합니다. *****" << endl;

	while (exit2) {
		exit = true;
		cout << "어휘 삽입: 1, 어휘 테스트 : 2, 프로그램 종료:그외키 >> ";
		cin >> sel;
		switch (sel) {
		case 1:
			cout << "영어 단어에 exit을 입력하면 입력 끝" << endl;
			//fflush(stdin);
			while (getchar() != '\n');
			while (1) {
				cout << "영어 >>";  getline(cin, e);
				if (e == "exit") break;
				cout << "한글 >>";  getline(cin, k);
				w.setEnKo(e, k);
				v.push_back(w);
			}
			break;
		case 2:
			cout << "영어 어휘 테스트를 시작합니다. 1~4 외 다른 입력시 종료합니다." << endl;
			while (exit) {
				n1 = rand() % v.size();
				bogi[0] = v.at(n1).getKo();
				answer = bogi[0];
				cout << v.at(n1).getEn() << "?" << endl;

				while (exit) {				// 중복되지 않는 보기 만들기
					for (i = 1; i<4; i++) {
						n1 = rand() % v.size();
						bogi[i] = v.at(n1).getKo();
					}
					if (bogi[0] != bogi[1] && bogi[0] != bogi[2] && bogi[0] != bogi[3] &&
						bogi[1] != bogi[2] && bogi[1] != bogi[3] && bogi[2] != bogi[3])
						exit = false;
				}
				exit = true;

				number[0] = rand() % 4;
				while (exit) {					//보기 순서 섞기
					for (i = 1; i<4; i++) {
						number[i] = rand() % 4;
					}
					if (number[0] != number[1] && number[0] != number[2] && number[0] != number[3] &&
						number[1] != number[2] && number[1] != number[3] && number[2] != number[3])
						exit = false;
				}
				exit = true;
				int result;

				for (i = 1; i<5; i++)
					cout << "(" << i << ") " << bogi[number[i - 1]] << " ";
				cout << ":>";
				cin >> result;

				if (result != 1 && result != 2 && result != 3 && result != 4)	//순서 중요 먼저 1, 2, 3, 4 이외의 값인지 확인해야함
					exit = false;
				else if (answer == bogi[number[result - 1]])
					cout << "Excellent !!" << endl;
				else if (result == 1 || result == 2 || result == 3 || result == 4)
					cout << "No. !!" << endl;
			}
			break;
		default:
			exit2 = false;
			break;
		}
		cout << endl;
	}
}

 

 

4. 설명

 

주의 하실점이라면 퀴즈를 푼 후 어휘를 삽입할려고 할 시 먼저 입력 버퍼를 비워준 후 단어를 입력 받아야 합니다.

 

전글에서 이야기 했듯이 while( getchar() != '\n');을 이용하여서 입력버퍼를 비워 줍니다.

 

대부분 앞의 문제들에서 사용하였던 것이고, 주석으로 무엇을 구현한 것인지 간략히 구분해 놨으므로 이해하시는데는 큰 문제 없으실겁니다.

 

1. 문제

 

11. 책의 년도, 책이름, 저자 이름을 담은 Book 클래스를 만들고, vector<Book> v;로 생성한 벡터를 이용하여 책을 입고하고, 저자와 년도로 검색하는 프로그램을 작성하라.

 

2. 결과

 

 

3. 코드

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

class Book {
	int year;
	string name;
	string writer;
public:
	void setInfo(int ye, string na, string wr) {
		year = ye;
		name = na;
		writer = wr;
	}
	int getYear() { return year; }
	string getWriter() { return writer; }
	void search() { cout << year << "년도, " << name << ", " << writer << endl; }
};

int main() {

	vector<Book> v;
	Book b;
	int year; string name, writer;

	cout << "입고할 책을 입력하세요. 년도에 -1를 입력하면 입고를 종료합니다." << endl;
	while (1) {
		
		cout << "년도>>"; cin >> year;
		if (year == -1) break;
		//fflush(stdin);
		while (getchar() != '\n');

		cout << "책이름>>"; getline(cin, name);
		cout << "저자>>"; getline(cin, writer);

		b.setInfo(year, name, writer);
		v.push_back(b);
	}
	int num = v.size();
	cout << "총 입고된 책은 " << num << "권입니다." << endl;
	cout << "검색하고자 하는 저자 이름을 입력하세요>>";
	//fflush(stdin);
	while (getchar() != '\n');
	getline(cin, writer);

	for (int i = 0; i< num; i++)
		if (v[i].getWriter() == writer) v[i].search();

	cout << "검색하고자 하는 년도를 입력하세요>>";
	cin >> year;

	for (int i = 0; i< num; i++)
		if (v[i].getYear() == year) v[i].search();
}

 

4. 설명

 

 

fflush(stdin)으로 버퍼를 비워주는 것이 visual studio 2017에서 먹히지 않아서 달리 버퍼를 지워주는 while( getchar() != '\n' ); 을 삽입해 주었습니다.

 

 

아마 2015년 버전 이후부터 보안상으로 막아 논 것 같습니다.

 

1. 문제

 

10. 나라의 수도 맞추기 게임에 vector를 활용해보자. 나라 이름(nation)과 수도(capital) 문자열로 구성된 Nation 클래스를 만들고, vector<Nation> v;로 생성한 벡터를 이용하여 나라 이름과 수도 이름을 삽입할 수도 있고 랜덤하게 퀴즈를 볼 수도 있다. 

 

프로그램 내에서 벡터에 Nation 객체를 여러 개 미리 삽입하여 퀴즈를 보도록 하라. 실행 화면은 다음과 같으며, 저자는 9개 나라의 이름과 수도를 미리 프로그램에서 삽입하였다. 

 

문자열을 string 클래스를 이용하라.

 

2. 결과

 

 

3. 코드

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

class Nation {
	string nation;
	string capital;
public:
	Nation() { ; }
	void setNation(string na, string ca) {
		nation = na;
		capital = ca;
	}
	string getNation() { return nation; }
	string getCapital() { return capital; }
};


int main() {

	vector<Nation> v;
	Nation n;
	n.setNation("한국", "서울");
	v.push_back(n);
	n.setNation("중국", "베이징");
	v.push_back(n);
	n.setNation("일본", "도쿄");
	v.push_back(n);
	n.setNation("베트남", "하노이");
	v.push_back(n);
	n.setNation("인도", "뉴델리");
	v.push_back(n);
	n.setNation("필리핀", "마닐라");
	v.push_back(n);
	n.setNation("타이", "방콕");
	v.push_back(n);
	n.setNation("몰디브", "몰레");
	v.push_back(n);
	n.setNation("미국", "와싱턴");
	v.push_back(n);

	srand((unsigned)time(0));
	int sel;
	bool exit = true;
	string na, ca;
	int num = v.size() + 1;
	int choice = 0;
	int random;

	cout << "***** 나라의 수도 맞추기 게임을 시작합니다. *****" << endl;

	while (exit) {
		cout << "정보 입력: 1, 퀴즈: 2, 종료: 3 >> ";
		cin >> sel;

		switch (sel) {
		case 1:
			cout << "현재 " << v.size() << "개의 나라가 입력되어 있습니다." << endl;
			cout << "나라와 수도를 입력하세요(no no 이면 입력끝)" << endl;
			while (1) {
				cout << num << ">>";
				cin >> na >> ca;

				for (int i = 0; i< num - 1; i++) {
					if (v[i].getNation() == na) {
						cout << "already exists !!" << endl;
						choice = 1;
						break;
					}
				}
				if (na == "no" && ca == "no") break;
				else if (choice == 0) {
					n.setNation(na, ca);
					v.push_back(n);
					num++;
				}
				choice = 0;
			}
			break;
		case 2:
			while (1) {
				random = rand() % v.size();
				cout << v[random].getNation() << "의 수도는?";
				cin >> ca;
				if (ca == "exit") break;
				if (v[random].getCapital() == ca)
					cout << "Correct !!" << endl;
				else
					cout << "NO !!" << endl;
			}
			break;
		case 3:
			exit = false;
			break;
		}
	}
}

 

4. 설명

 

 

나라 이름과 수도 이름을 가지고 있는 Nation 클래스를 만든 후 이를 vector의 push_back으로 삽입합니다.

 

1번 입력에서 나올 때는 no no 즉 나라 이름과 수도 이름으로 no가 입력되었을 때 입력을 종료하도록 합니다.

 

2번 퀴즈에서는 exit가 입력되면 퀴즈가 종료되도록 합니다.

 

1. 문제

 

9. STL의 vector 클래스를 이용하는 간단한 프로그램을 작성해보자. vector 객체를 생성하고, 키보드로부터 정수를 입력받을 때마다 정수를 벡터에 삽입하고 지금까지 입력된 수와 평균을 출력하는 프로그램을 작성하라. 0을 입력하면 프로그램이 종료한다.

 

2. 결과

 

 

3. 코드

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

int main() {
	vector<int> v;
	int n;
	double avg;

	while(1) {
		cout << "정수를 입력하세요(0을 입력하면 종료)>>";
		cin >> n;
		v.push_back(n);
		if( n == 0) break;
		
		int sum=0;
		for(int i=0; i<v.size(); i++) {
			cout << v.at(i) << " ";
			sum += v.at(i);
		}
		
		avg = (double)sum / v.size();
		cout << endl << "평균 = " << avg << endl;
	}
}

 

 

4. 설명

 

 

push_back(n)으로 n을 뒤로 push(삽입) 합니다.

 

at(i)로 인덱스 i번 째의 수를 가져옵니다.

 

평균 avg를 구할 때는 소숫점 아래 부분까지 구하므로 (double)형으로 형변환을 해준 후 계산한다.

 

 

 

1. 문제

 

8. 문제 7을 푸는 다른 방법을 소개한다.

bigger() 함수의 다음 라인에서 > 연산자 때문에

 

T에 Circle과 같은 클래스 타입이 대입되면, 구체화가 실패하여 컴파일 오류가 발생한다. 이 문제를 해결하기 위해 다음과 같은 추상 클래스 Comparable을 제안한다.

 

Circle 클래스가 Comparable을 상속받아 순수 가상 함수를 모두 구현하면, 앞의 bigger() 템플릿 함수를 사용하는데 아무 문제가 없다. Circle뿐 아니라, Comparable을 상속받은 모든 클래스를 bigger()에 사용할 수 있다.

Comparable을 상속받은 Circle 클래스를 완성하고 문제 7의 main()을 실행하여 테스트 하라.

 

 

2. 결과

 

 

3. 코드

#include <iostream>
using namespace std;

class Circle;

class Comparable {
public:
	virtual bool operator > (Circle& op2) = 0;
	virtual bool operator < (Circle& op2) = 0;
	virtual bool operator == (Circle& op2) = 0;
};
class Circle : public Comparable {
	int radius;
public:
	Circle(int radius = 1) { this->radius = radius; }
	int getRadius() { return radius; }
	bool operator > (Circle& op2) {
		if (this->radius > op2.radius) return true;
		else return false;
	}
	bool operator < (Circle& op2) {
		if (this->radius < op2.radius) return true;
		else return false;
	}
	bool operator == (Circle& op2) {
		if (this->radius == op2.radius) return true;
		else return false;
	}
};

template <class T>
T bigger(T a, T b) {
	if (a > b) return a;
	else return b;
}

int main() {
	int a = 20, b = 50, c;
	c = bigger(a, b);
	cout << "20과 50중 큰 값은 " << c << endl;
	Circle waffle(10), pizza(20), y;
	y = bigger(waffle, pizza);
	cout << "waffle과 pizza 중 큰 것의 반지름은 " << y.getRadius() << endl;
}

 

4. 설명

 

앞에서 배웠던 연산자 재정의와 순수가상함수를 이용하여 7번에 문제를 해결하는 것을 보여준다.

 

각 연산자에 알맞은 비교방법으로 radius를 비교해주면 올바른 결과를 얻을 수 있다.

 

+ Recent posts