[C++ 소스] 최종 프로그램 실습(학교, 도서관, 강의실, 학생 등)
실습 시나리오
시나리오
프로그램은 콘솔 기반의 응용 프로그램이다. 프로그램을 시작하면 이 에이치 나라를 생성한다. 이 에이치 나라는 초기화, 사용자 명령에 따른 동작, 종료화 과정을 거친다.
이 에이치 나라의 초기화에서는 학생 공장이 만들어지고 주거지와 다운타운, 학교가 만들어진다.
이 에이치 나라의 사용자 명령에 따른 동작에서는 종료 메뉴를 선택하기 전까지 선택한 메뉴를 수행하는 것을 반복한다. 이 에이치 나라의 메뉴는 학생 생성, 초점 이동, 학생 이동, 전체 보기, 종료 메뉴가 있다.
이 에이치 나라의 학생 생성 메뉴에서는 생성할 학생 종류를 선택하고 학생 이름을 입력받은 후에 학생 공장에 주문하여 생성한다. 학생 종류에는 마법 학생, 학사 학생, 운동 학생이 있다. 학생의 생성과 소멸은 학생 공장에서만 가능하다.
이 에이치 나라의 초점 이동 메뉴에서는 주거지, 다운타운, 학교 중에 한 장소를 선택하면 해당 장소로 초점을 이동한다. 각 장소로 이동하면 해당 장소의 종료 메뉴를 선택하기 전까지 선택한 메뉴를 수행하는 것을 반복한다. 종료 메뉴를 선택하면 초점은 다시 이 에이치 나라로 이동한다.
이 에이치 나라의 학생 이동 메뉴에서는 이동할 학생을 선택하고 주거지, 다운타운, 학교 중에 한 장소를 선택하여 유닛을 선택한 장소로 이동한다. 만약 이동한 장소가 학교일 때는 처음 학교를 방문한 것인지 확인하여 학번을 부여한다.
이 에이치 나라의 전체 보기에서는 이 에이치 나라에 있는 학생 정보와 각 장소의 정보를 보여준다.
주거지 메뉴에는 거실 생활, 소등, 이 에이치 나라로 학생 복귀하기, 초점 종료가 있다. 거실 생활에서는 학생을 선택하여 선택한 학생을 휴식 시킨다. 선택한 학생이 마법 학생이면 마법 여행도 간다. 소등 기능에서는 전체 학생이 잠을 잔다.
다운타운 메뉴에는 파티, 노래방, 이 에이치 나라로 학생 복귀하기, 초점 종료가 있다. 파티 기능에서는 전체 학생은 음료를 마신다. 노래방 기능에서는 학생을 선택하며 선택한 학생이 노래한다. 만약 선택한 학생이 운동 학생이면 춤도 춘다.
학교 메뉴에는 강의 시작, 도서관 가기, 이 에이치 나라로 학생 복귀하기, 초점 종료가 있다. 강의 시작 기능에서는 전체 학생은 강의를 받는다. 도서관 가기에서는 학생을 선택하며 선택한 학생이 공부힌다. 만약 선택한 학생이 학사 학생이면 독서도 한다.
모든 장소에서 이 에이치 나라로 유닛 복귀하기에서는 이동할 학생을 선택하여 선택한 학생을 에이치 나라로 복귀시킨다.
모든 장소에서 종료 메뉴를 선택하면 해당 장소의 초점이 종료하고 이 에이치의 상호 작용을 계속 수행한다.
주의 사항
각 장소에서는 학생의 기능 중에 약속한 행위외에 다른 기능에 접근할 수 없다.
학생의 생성과 소멸은 학생 공장에서만 가능하다.
학생에 관한 세부 사항은 상속과 다형성에서의 시나리오와 같습니다.
1. 학생
멤버 필드로 이름, 주민번호, 체력, 지력, 스트레스가 있음
주민번호: 순차적 부여
이름: 생성 시 전달
지력:100(최소 0, 최대 200)
체력: 100 (최소 0, 최대 200)
스트레스: 0 (최소 0, 최대 100)
연속으로 공부한 횟수: 0 (0,5), 공부를 하면 1 증가, 그 외의 행위를 하면 0으로 리셋, scnt로 부름
2. 학사 학생
멤버 필드로 더미 뇌가 있음
더미 뇌는 생성 시 0 이며 공부한 회수가 5의 배수가 될 때마다 1씩 증가
공부하다.
체력 5소모, 지력: scnt+더미 뇌 증가, 스트레스: 2감소
강의를 받다.
체력 3소모, 지력: scnt 증가, 스트레스: scnt증가
잠자다.
체력 10회복, 스트레스: 5감소 *scnt는 연속 공부한 회수
휴식하다.
체력 3회복, 스트레스: 25감소
음료 섭취
체력 5회복, 지력: 10감소 , 스트레스: 2증가
노래하다.
체력 10 소모, 지력: 5-scnt감소, 스트레스: 5-scnt증가
독서하다.
더미 뇌 1증가, 스트레스: 5감소
3. 마법 학생
마법 학생은 내부적으로 지팡이가 있다.
지팡이는 생성 시 0이며 마법 여행 시 1씩 증가
공부하다.
체력 3소모, 지력: scnt 증가, 스트레스: 3증가
강의를 받다.
체력 2소모, 지력: scnt 증가, 스트레스: 5증가
잠자다.
체력 10회복, 스트레스: 5감소
휴식하다.
체력 3회복, 스트레스: 25감소
음료 섭취
체력 5+지팡이 회복, 지력: 10-지팡이 감소, 스트레스: 2감소
노래하다.
체력 10-지팡이 소모, 지력: 5감소, 스트레스: 5감소
마법 여행을 가다.
지팡이 1증가
4. 운동 학생
운동 학생은 내부적으로 air가 있다.
air는 생성 시 0 이며 춤을 추면 1 증가
공부하다.
체력 2소모, 지력: scnt/2 증가,
air 3 감소, air*3만큼 스트레스 감소
강의를 받다.
체력 1소모, 지력: scnt/2 증가,
air :5 감소, air*3만큼 스트레스 감소
잠자다.
체력 10회복, 스트레스: 5감소
휴식하다.
체력 8회복, 스트레스: 25감소
음료 섭취
체력 5 회복, 지력: 3 감소, 스트레스: 2감소
노래하다.
체력 5소모, 지력: 2증가, 스트레스: 5감소
춤을 추다.
체력 5소모, 지력: 3증가, air 1증가
//ehglobal.h
#pragma once
enum keydata //기능 키에 사용할 상수 열거
{
NO_DEFINED,F1,F2,F3,F4,F5,F6,F7,F8, ESC
};
class ehglobal
{
public:
static void clrscr(); //콘솔 화면 클리어
static keydata getkey(); //기능 키 입력
static void waitkey(); //아무 키나 누를 때까지 대기
private:
ehglobal(void)
{
}
~ehglobal(void)
{
}
};
//ehglobal.cpp
#include "ehglobal.h"
#pragma warning(disable:4996)
#include <conio.h>
#include <windows.h>
void ehglobal::clrscr()
{
system("cls");
}
keydata ehglobal::getkey()
{
int key = getch();
if(key == 27)//key가 27이면 ESC를 누른 것입니다.
{
return ESC;
}
if(key == 0) //key가 0이면 기능 키를 누른 것입니다.
{
key = getch();//다시 한 번 getkey를 호출해야 합니다.
switch(key)//key의 값에 따라 기능 키를 정의한 열거형의 상수를 반환합니다.
{
case 59: return F1; case 60: return F2;
case 61: return F3; case 62: return F4;
case 63: return F5; case 64: return F6;
case 65: return F7; case 66: return F8;
}
}
return NO_DEFINED;
}
void ehglobal::waitkey()
{
getkey();
}
//SeqArray.h
#pragma once
template <typename data>
class SeqArray
{
data *base; //저장소
size_t capacity; //저장소 크기
size_t size; //보관 개수
public:
SeqArray()
{
base = 0;
capacity = 0;
size = 0;
}
~SeqArray(void)
{
if(base)//저장소가 있을 때
{
delete[] base;//저장소 해제
}
}
void PushBack(data value)//순차 보관
{
if(IsFull())//꽉차면
{
if(capacity)//저장소의 개수가 참일 때
{
Reserve(capacity *2);//두 배로 확장
}
else//아닐 때(0일 때)
{
Reserve(1);//1로 확장
}
}
base[size] = value;//보관
size++;//보관 개수 1 증가
}
void RemoveAt(size_t index)//특정 인덱스 요소 삭제
{
if(IsAvailIndex(index)==false)//인덱스가 유효하지 않을 때
{
return;
}
size--;//보관 개수 1 감소
for( ;index<size;index++)
{
base[index] = base[index+1];//한 칸씩 앞으로 이동
}
}
template <typename find_if>
int FindIf(find_if fun)//특정 알고리즘이 처음으로 참인 위치 찾기
{
for(size_t i = 0; i<size; ++i)
{
if(fun(base[i]))//알고리즘에 적용하였을 때 참이면
{
return i; //인덱스 반환
}
}
return -1;//-1 반환
}
data &operator[](size_t index)//인덱서
{
if(IsAvailIndex(index)==false)//유효하지 않은 인덱스일 때
{
throw "유효하지 않은 인덱스를 사용하였습니다.";//예외 던짐
}
return base[index];//인덱스의 원소 반환
}
bool IsAvailIndex(size_t index)const//유효한 인덱스인지 판별
{
return (index>=0)&&(index<size);
}
size_t GetSize()const
{
return size;
}
private:
bool IsFull()const//꽉 찼는지 판별
{
return size == capacity;
}
void Reserve(int ncapacity)//저장소 확장
{
data *tbuf = base;//저장소 위치를 tbuf로 설정
base = new data[ncapacity];//저장소 동적 할당
capacity = ncapacity;//저장소 크기 설정
if(tbuf)//이전 저장소가 참이면
{
for(size_t i=0; i<size;++i)
{
base[i] = tbuf[i];//이전 저장소에 보관한 값을 새로운 저장소로 이동
}
delete[] tbuf;//이전 저장소 메모리 해제
}
}
};
//IPlay.h
#pragma once
#ifndef interface
#define interface struct
#endif
interface IPlay
{
virtual void Drink()=0;
virtual void Sing()=0;
};
//IRelax.h
#pragma once
#ifndef interface
#define interface struct
#endif
interface IRelax
{
virtual void Sleep()=0;
virtual void Relax()=0;
};
//IStudy.h
#pragma once
#ifndef interface
#define interface struct
#endif
interface IStudy
{
virtual void ListenLecture()=0;
virtual void Study()=0;
};
//Man.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Man
{
static int last_pn;
const int pn;
string name;
int snum;//학번
public:
Man(string name);
int GetPN()const;
string GetName()const;
int GetSNum()const;//학번 접근자
void SetSNum(int snum); //학번 설정자
virtual void View()const=0;//정보보기
};
//Man.cpp
#include "Man.h"
int Man::last_pn;
Man::Man(string name):pn(++last_pn)
{
this->name = name;
snum = 0;
}
int Man::GetPN()const
{
return pn;
}
string Man::GetName()const
{
return name;
}
int Man::GetSNum()const//학번 접근자
{
return snum;
}
void Man::SetSNum(int snum) //학번 설정자
{
this->snum = snum;
}
//IComeBack.h
#pragma once
#ifndef interface
#define interface struct
#endif
#include "Man.h"
interface IComeBack
{
virtual void ComeBack(Man *man)=0;
};
//StuConst.h
#pragma once
class StuConst
{
public:
static const int def_iq;
static const int max_iq;
static const int min_iq;
static const int def_hp;
static const int max_hp;
static const int min_hp;
static const int def_stress;
static const int max_stress;
static const int min_stress;
static const int def_scnt;
static const int max_scnt;
static const int min_scnt;
private://개체를 생성할 수 없게 함
StuConst(void);
};
//StuConst.cpp
#include "StuConst.h"
const int StuConst::def_iq = 100;
const int StuConst::max_iq=200;
const int StuConst::min_iq=0;
const int StuConst::def_hp=100;
const int StuConst::max_hp=200;
const int StuConst::min_hp=0;
const int StuConst::def_stress=0;
const int StuConst::max_stress=100;
const int StuConst::min_stress=0;
const int StuConst::def_scnt=0;
const int StuConst::max_scnt=5;
const int StuConst::min_scnt=0;
StuConst::StuConst(void)
{
}
//Student.h
#pragma once
#include "Man.h"
#include "IPlay.h"
#include "IRelax.h"
#include "IStudy.h"
#include "StuConst.h"
using namespace std;
class Student:public Man, public IStudy, public IRelax, public IPlay
{
int iq;
int hp;
int stress;
int scnt;
public:
friend class StuFactory;
virtual void Study();
virtual void ListenLecture();
virtual void Sleep();
virtual void Relax();
virtual void Drink();
virtual void Sing();
virtual void View()const;
int GetIQ()const;
int GetHP()const;
int GetStress()const;
int GetSCnt()const;
protected:
Student(string name);
void SetIQ(int iq);
void SetHP(int hp);
void SetStress(int stress);
void SetSCnt(int scnt);
};
//Student.cpp
#include "Student.h"
#define SC StuConst //간략하게 사용할 수 있게 매크로 정의
Student::Student(string name):Man(name)
{
SetIQ(SC::def_iq);
SetHP(SC::def_hp);
SetStress(SC::def_stress);
SetSCnt(SC::def_scnt);
}
void Student::View()const
{
cout<<"주민 번호:"<<GetPN()<<" 이름:"<<GetName()<<endl;
cout<<" IQ:"<<iq<<" HP:"<<hp<<" Stress:"<<stress<<endl;
cout<<" 연속으로 공부한 횟수:"<<scnt<<endl;
}
int Student::GetIQ()const
{
return iq;
}
int Student::GetHP()const
{
return hp;
}
int Student::GetStress()const
{
return stress;
}
int Student::GetSCnt()const
{
return scnt;
}
void Student::SetIQ(int iq)
{
if(iq>SC::max_iq)
{
iq = SC::max_iq;
}
if(iq<SC::min_iq)
{
iq = SC::min_iq;
}
this->iq = iq;
}
void Student::SetHP(int hp)
{
if(hp>SC::max_hp)
{
hp = SC::max_hp;
}
if(hp<SC::min_hp)
{
hp = SC::min_hp;
}
this->hp = hp;
}
void Student::SetStress(int stress)
{
if(stress>SC::max_stress)
{
stress = SC::max_stress;
}
if(stress<SC::min_stress)
{
stress = SC::min_stress;
}
this->stress = stress;
}
void Student::SetSCnt(int scnt)
{
if(scnt>SC::max_scnt)
{
scnt = SC::max_scnt;
}
if(scnt<SC::min_scnt)
{
scnt = SC::min_scnt;
}
this->scnt = scnt;
}
void Student::ListenLecture()
{
cout<<GetName()<<" 강의받다."<<endl;
}
void Student::Study()
{
cout<<GetName()<<" 공부하다."<<endl;
}
void Student::Sleep()
{
cout<<GetName()<<" 잠을 자다."<<endl;
}
void Student::Relax()
{
cout<<GetName()<<" 휴식하다."<<endl;
}
void Student::Drink()
{
cout<<GetName()<<" 음료를 마시다."<<endl;
}
void Student::Sing()
{
cout<<GetName()<<" 노래하다."<<endl;
}
//MStudent.h
#pragma once
#include "Student.h"
class MStudent :
public Student
{
int stick;
public:
friend class StuFactory;
virtual void Study();
virtual void ListenLecture();
virtual void Sleep();
virtual void Relax();
virtual void Drink();
virtual void Sing();
virtual void View()const;
void Travel();
private:
MStudent(string name);
};
//MStudent.cpp
#include "MStudent.h"
MStudent::MStudent(string name):Student(name)
{
stick=0;//지팡이는 생성 시 0
}
void MStudent::Study()
{
Student::Study();
Student::ListenLecture();
SetHP(GetHP()-3);//체력 3소모
SetIQ(GetIQ()+GetSCnt());//지력: scnt 증가
SetStress(GetStress()+3);//스트레스: 3증가
SetSCnt(GetSCnt()+1);
}
void MStudent::ListenLecture()
{
SetHP(GetHP()-2); //체력 2소모
SetIQ(GetIQ()+GetSCnt());//지력: scnt 증가
SetStress(GetStress()+5);// 스트레스: 5증가
SetSCnt(0);
}
void MStudent::Sleep()
{
Student::Sleep();
SetHP(GetHP()+10); //체력 10회복
SetStress(GetStress()-5); //스트레스: 5감소
SetSCnt(0);
}
void MStudent::Relax()
{
Student::Relax();
SetHP(GetHP()+3); //체력 3회복
SetStress(GetStress()-25); //스트레스: 25감소
SetSCnt(0);
}
void MStudent::Drink()
{
Student::Drink();
SetHP(GetHP()+5+stick); //체력 5+지팡이 회복
SetIQ(GetIQ()-(10-stick));//지력: 10-지팡이 감소
SetStress(GetStress()-2);//스트레스: 2감소
SetSCnt(0);
}
void MStudent::Sing()
{
Student::Sing();
SetHP(GetHP()-(10-stick)); //체력 10-지팡이 소모
SetIQ(GetIQ()-5);//지력: 5감소
SetStress(GetStress()-5);//스트레스: 5감소
SetSCnt(0);
}
void MStudent::View()const
{
cout<<"마법 학생";
Student::View();
cout<<" 지팡이:"<<stick<<endl;
}
void MStudent::Travel()
{
cout<<GetName()<<" 여행하다."<<endl;
stick++;//지팡이 1증가
}
//PStudent.h
#pragma once
#include "Student.h"
class PStudent :
public Student
{
int air;
public:
friend class StuFactory;
virtual void Study();
virtual void ListenLecture();
virtual void Sleep();
virtual void Relax();
virtual void Drink();
virtual void Sing();
virtual void View()const;
void Dance();
private:
PStudent(string name);
};
//PStudent..cpp
#include "PStudent.h"
PStudent::PStudent(string name):Student(name)
{
air=0;//air는 생성 시 0
}
void PStudent::Study()
{
Student::Study();
SetHP(GetHP()-2);//체력 2소모
SetIQ(GetIQ()+GetSCnt()/2);//지력: scnt/2 증가
air-=3;
SetStress(GetStress()-air*3);//스트레스: air*3감소
SetSCnt(GetSCnt()+1);
}
void PStudent::ListenLecture()
{
Student::ListenLecture();
SetHP(GetHP()-1); //체력 1소모
SetIQ(GetIQ()+GetSCnt()/2);//지력: scnt/2 증가
air-=5;
SetStress(GetStress()-air*3);// 스트레스: air*3 감소
SetSCnt(0);
}
void PStudent::Sleep()
{
Student::Sleep();
SetHP(GetHP()+10); //체력 10회복
SetStress(GetStress()-5); //스트레스: 5감소
SetSCnt(0);
}
void PStudent::Relax()
{
Student::Relax();
SetHP(GetHP()+8); //체력 8회복
SetStress(GetStress()-25); //스트레스: 25감소
SetSCnt(0);
}
void PStudent::Drink()
{
Student::Drink();
SetHP(GetHP()+5); //체력 5 회복
SetIQ(GetIQ()-3);//지력: 3 감소
SetStress(GetStress()-2);//스트레스: 2감소
SetSCnt(0);
}
void PStudent::Sing()
{
Student::Sing();
SetHP(GetHP()-5); //체력 5 소모
SetIQ(GetIQ()+2);//지력: 5증가
SetStress(GetStress()-5);//스트레스: 5감소
SetSCnt(0);
}
void PStudent::View()const
{
cout<<"운동 학생";
Student::View();
cout<<" air:"<<air<<endl;
}
void PStudent::Dance()
{
cout<<GetName()<<" 춤을 추다."<<endl;
SetHP(GetHP()-5); //체력 5 소모
SetIQ(GetIQ()+3);//지력: 3증가
air++;//air 1증가
}
//SStudent.h
#pragma once
#include "Student.h"
class SStudent :
public Student
{
int dummy;
int total_scnt;
public:
friend class StuFactory;
virtual void Study();
virtual void ListenLecture();
virtual void Sleep();
virtual void Relax();
virtual void Drink();
virtual void Sing();
virtual void View()const;
void Reading();
private:
SStudent(string name);
};
//SStudent..cpp
#include "SStudent.h"
SStudent::SStudent(string name):Student(name)
{
dummy = 0;//더미 뇌는 생성 시 0
total_scnt = 0;
}
void SStudent::Study()
{
Student::Study();
SetHP(GetHP()-5);//체력 5소모
SetIQ(GetIQ()+GetSCnt()+dummy);//지력: scnt+더미 뇌 증가
SetStress(GetStress()-2);//스트레스: 2감소
SetSCnt(GetSCnt()+1);
total_scnt++;
if(total_scnt%5 == 0)//더미 뇌는 공부한 회수가 5의 배수가 될 때마다 1씩 증가
{
dummy++;
}
}
void SStudent::ListenLecture()
{
Student::ListenLecture();
SetHP(GetHP()-3); //체력 3소모
SetIQ(GetIQ()+GetSCnt());//지력: scnt 증가
SetStress(GetStress()+GetSCnt());// 스트레스: scnt증가
SetSCnt(0);
}
void SStudent::Sleep()
{
Student::Sleep();
SetHP(GetHP()+10); //체력 10회복
SetStress(GetStress()-5); //스트레스: 5감소
SetSCnt(0);
}
void SStudent::Relax()
{
Student::Relax();
SetHP(GetHP()+3); //체력 3회복
SetStress(GetStress()-25); //스트레스: 25감소
SetSCnt(0);
}
void SStudent::Drink()
{
Student::Drink();
SetHP(GetHP()+5); //체력 5회복
SetIQ(GetIQ()-10);//지력: 10감소
SetStress(GetStress()+2);//스트레스: 2증가
SetSCnt(0);
}
void SStudent::Sing()
{
Student::Sing();
SetHP(GetHP()-10); //체력 10 소모
SetIQ(GetIQ()-(5-GetSCnt()));//지력: 5-scnt감소
SetStress(GetStress()+(5-GetSCnt()));//스트레스: 5-scnt증가
SetSCnt(0);
}
void SStudent::View()const
{
cout<<"학사 학생";
Student::View();
cout<<" 더미 뇌:"<<dummy<<"연속으로 공부한 횟수:"<<total_scnt<<endl;
}
void SStudent::Reading()
{
cout<<GetName()<<" 독서하다."<<endl;
dummy++;//더미 뇌 1증가
SetStress(GetStress()-5);//스트레스: 5감소
}
//StuFactory.h
#pragma once
#include "SeqArray.h"
#include "Student.h"
class StuFactory
{
SeqArray<Student *> base;
public:
StuFactory(void);
~StuFactory(void);
Student *MakeStudent(int stype,string name);//학생 생성
};
//StuFactory.cpp
#include "StuFactory.h"
#include "SStudent.h"
#include "MStudent.h"
#include "PStudent.h"
StuFactory::StuFactory(void)
{
}
StuFactory::~StuFactory(void)
{
//보관 개수를 얻어온다.
size_t size = base.GetSize();
for(size_t i = 0; i<size; ++i)//i를 0~size-1까지 증가
{
delete base[i];//학생 개체 소멸
}
}
Student *StuFactory::MakeStudent(int stype,string name)//학생 생성
{
Student *stu = 0;
//stype에 따라 적절한 학생 개체 생성
switch(stype)
{
case 1: stu = new SStudent(name); break;
case 2: stu = new MStudent(name); break;
case 3: stu = new PStudent(name); break;
default: throw "학생 타입 범위를 벗어났습니다.";
}
base.PushBack(stu);//생성한 학생 개체를 컬렉션에 보관
return stu;//생성한 학생 개체 반환
}
//Place.h
#pragma once
#include "IComeBack.h"
#include "Man.h"
#include "SeqArray.h"
#include "ehglobal.h"
class Place
{
IComeBack ⁣
SeqArray<Man *> base;
public:
Place(IComeBack &ic);
~Place(void);
void Run();
virtual void InStudent(Man *man);//유닛 이동
virtual void View();//장소 정보 출력
protected:
int SelectMenu();
virtual void ViewMenu()const;
void ComeBackStu();//학생 복귀
virtual void DoItByKey(int key)=0;//키에 따라 기능 수행
Man *SelectMan();//학생 선택
size_t GetCount()const;//학생 수
Man *GetAt(size_t index);//index 위치 학생 반환
private:
void EraseMan(Man *man);//학생 제거
};
//Place.cpp
#include "Place.h"
Place::Place(IComeBack &ic):ic(ic)
{
}
Place::~Place(void)
{
}
void Place::Run()
{
int key = 0;
while((key = SelectMenu())!=ESC)
{
if(key == F1)
{
ComeBackStu();//학생 복귀
}
else
{
DoItByKey(key);//키에 따라 기능 수행
}
cout<<"아무 키나 누르세요."<<endl;
ehglobal::getkey();
}
}
int Place::SelectMenu()
{
ehglobal::clrscr();
ViewMenu();
return ehglobal::getkey();
}
void Place::ViewMenu()const
{
cout<<"ESC:초점 종료"<<endl;
cout<<"F1: 이에이치 나라로 학생 복귀"<<endl;
}
void Place::ComeBackStu()//유닛 복귀
{
Man *man = SelectMan();//이동할 유닛 선택
if(man == 0)
{
cout<<"잘못 선택하였습니다."<<endl;
return;
}
EraseMan(man);//유닛 제거
ic.ComeBack(man);//학생 복귀
}
Man *Place::SelectMan()//유닛 선택
{
cout<<"선택할 학생의 주민번호:";
int pn=0;
cin>>pn;
size_t size = base.GetSize();//보관한 학생 수 구하기
for(size_t i=0;i<size;++i)
{
if(base[i]->GetPN() == pn)//학생 주민번호와 입력한 주민번호가 같을 때
{
return base[i];
}
}
return 0;
}
void Place::EraseMan(Man *man)//유닛 제거
{
size_t size = base.GetSize();//보관한 학생 수 구하기
for(size_t i=0;i<size;++i)
{
if(base[i]==man)//보관한 학생과 입력 인자로 받은 학생이 같을 때
{
base.RemoveAt(i);//해당 인덱스에 보관한 개체 지우기
return;
}
}
}
void Place::InStudent(Man *man)//유닛 이동
{
base.PushBack(man);
}
void Place::View()//장소 정보 출력
{
size_t size = base.GetSize();//보관 개수를 얻어온다.
for(size_t i = 0; i<size; ++i)//i를 0~size-1까지 증가
{
base[i]->View();//학생 정보 출력
}
}
size_t Place::GetCount()const//학생 수
{
return base.GetSize();
}
Man *Place::GetAt(size_t index)//index 위치 학생 반환
{
return base[index];
}
//Downtown.h
#pragma once
#include "Place.h"
#include "PStudent.h"
#include "IPlay.h"
class Downtown:
public Place
{
public:
Downtown(IComeBack &ic);
~Downtown(void);
virtual void View();//장소 정보 출력
private:
virtual void ViewMenu()const; //메뉴 출력
virtual void DoItByKey(int key);//키에 따라 기능 수행
void Party();//파티
void GoToSing();//노래방으로 가기
};
//Downtown.cpp
#include "Downtown.h"
Downtown::Downtown(IComeBack &ic):Place(ic)
{
}
Downtown::~Downtown(void)
{
}
void Downtown::ViewMenu()const //메뉴 출력
{
Place::ViewMenu();
cout<<"F2: 파티"<<endl;
cout<<"F3: 노래방으로 가기"<<endl;
}
void Downtown::DoItByKey(int key)//키에 따라 기능 수행
{
switch(key)
{
case F2: Party(); break; //파티
case F3: GoToSing(); break; //노래방으로 가기
default: cout<<"잘못 선택하였습니다."<<endl;
}
}
void Downtown::Party()//파티
{
cout<<"파티"<<endl;
size_t max = GetCount();//학생 수 구하기
for(size_t index = 0; index<max; ++index)
{
IPlay *iplay = dynamic_cast<IPlay *>(GetAt(index));
if(iplay)
{
iplay->Drink();
}
else
{
throw "장소에 있는 개체가 IPlay 형식으로 하향 캐스팅을 할 수 없습니다.";
}
}
}
void Downtown::GoToSing()//노래방으로 가기
{
cout<<"노래방으로 가기"<<endl;
Man *man = SelectMan();
if(man==0)
{
cout<<"잘못 선택하였습니다."<<endl;
return;
}
IPlay *iplay = dynamic_cast<IPlay *>(man);
if(iplay)
{
iplay->Sing();
PStudent *pstu = dynamic_cast<PStudent *>(iplay);
if(pstu)
{
pstu->Dance();
}
}
else
{
throw "IPlay 형식으로 하향 캐스팅을 하지 못하였습니다.";
}
}
void Downtown::View()//장소 정보 출력
{
cout<<"다운타운 "<<endl;
Place::View();
}
//School.h
#pragma once
#include "Place.h"
#include "IStudy.h"
#include "SStudent.h"
class School :
public Place
{
int last_snum;//가장 최근에 부여한 학생 번호
public:
School(IComeBack &ic);
~School(void);
virtual void InStudent(Man *man);//유닛 이동
virtual void View();//장소 정보 출력
private:
virtual void ViewMenu()const; //메뉴 출력
virtual void DoItByKey(int key);//키에 따라 기능 수행
void StartLecture();//강의 시작
void GoToLibrary();//도서관으로 가기
};
//School.cpp
#include "School.h"
School::School(IComeBack &ic):Place(ic)
{
last_snum = 0;
}
School::~School(void)
{
}
void School::ViewMenu()const //메뉴 출력
{
Place::ViewMenu();
cout<<"F2: 강의 시작"<<endl;
cout<<"F3: 도서관으로 가기"<<endl;
}
void School::DoItByKey(int key)//키에 따라 기능 수행
{
switch(key)
{
case F2: StartLecture(); break; //강의 시작
case F3: GoToLibrary(); break; //도서관으로 가기
default: cout<<"잘못 선택하였습니다."<<endl;
}
}
void School::StartLecture()//강의 시작
{
cout<<"강의 시작"<<endl;
size_t max = GetCount();//학생 수 구하기
for(size_t index = 0; index<max; ++index)
{
IStudy *istudy = dynamic_cast<IStudy *>(GetAt(index));
if(istudy)
{
istudy->ListenLecture();
}
else
{
throw "장소에 있는 개체가 IStudy 형식으로 하향 캐스팅을 할 수 없습니다.";
}
}
}
void School::GoToLibrary()//도서관으로 가기
{
cout<<"도서관으로 가기"<<endl;
Man *man = SelectMan();
if(man==0)
{
cout<<"잘못 선택하였습니다."<<endl;
return;
}
IStudy *istudy = dynamic_cast<IStudy *>(man);
if(istudy)
{
istudy->Study();
SStudent *sstu = dynamic_cast<SStudent *>(istudy);
if(sstu)
{
sstu->Reading();
}
}
else
{
throw "IStudy 형식으로 하향 캐스팅을 하지 못하였습니다.";
}
}
void School::InStudent(Man *man)//유닛 이동
{
Place::InStudent(man);//기반 형식 Place의 InStudent를 호출(컬렉션에 보관)
if(man->GetSNum()==0)//처음 온 학생이면
{
last_snum++;
man->SetSNum(last_snum);//학번 부여
}
}
void School::View()//장소 정보 출력
{
cout<<"학교 "<<endl;
Place::View();
}
//Village.h
#pragma once
#include "Place.h"
#include "IRelax.h"
#include "MStudent.h"
class Village :
public Place
{
public:
Village(IComeBack &ic);
~Village(void);
virtual void View();//장소 정보 출력
private:
virtual void ViewMenu()const; //메뉴 출력
virtual void DoItByKey(int key);//키에 따라 기능 수행
void TurnOff();//소등
void GoToLivingRoom();//거실로 가기
};
//Village.cpp
#include "Village.h"
Village::Village(IComeBack &ic):Place(ic)
{
}
Village::~Village(void)
{
}
void Village::ViewMenu()const //메뉴 출력
{
Place::ViewMenu();
cout<<"F2: 소등"<<endl;
cout<<"F3: 거실로 가기"<<endl;
}
void Village::DoItByKey(int key)//키에 따라 기능 수행
{
switch(key)
{
case F2: TurnOff(); break; //강의 시작
case F3: GoToLivingRoom(); break; //도서관으로 가기
default: cout<<"잘못 선택하였습니다."<<endl;
}
}
void Village::TurnOff()//소등
{
cout<<"소등"<<endl;
size_t max = GetCount();//학생 수 구하기
for(size_t index = 0; index<max; ++index)
{
IRelax *irelax = dynamic_cast<IRelax *>(GetAt(index));
if(irelax)
{
irelax->Sleep();
}
else
{
throw "장소에 있는 개체가 IRelax 형식으로 하향 캐스팅을 할 수 없습니다.";
}
}
}
void Village::GoToLivingRoom()//거실로 가기
{
cout<<"거실로 가기"<<endl;
Man *man = SelectMan();
if(man==0)
{
cout<<"잘못 선택하였습니다."<<endl;
return;
}
IRelax *irelax = dynamic_cast<IRelax *>(man);
if(irelax)
{
irelax->Relax();
MStudent *mstu = dynamic_cast<MStudent *>(irelax);
if(mstu)
{
mstu->Travel();
}
}
else
{
throw "IRelax 형식으로 하향 캐스팅을 하지 못하였습니다.";
}
}
void Village::View()//장소 정보 출력
{
cout<<"주거지 "<<endl;
Place::View();
}
//EhNara.h
#pragma once
#include "SeqArray.h"
#include "StuFactory.h"
#include "IComeBack.h"
#include "Place.h"
#include "Student.h"
class EhNara:public IComeBack
{
static EhNara app;//단일체
enum PIndex//장소 인덱스
{
PI_SCHOOL, PI_DOWNTOWN, PI_VILLAGE, PI_MAX
};
Place *places[PI_MAX];
StuFactory *sf;
SeqArray<Student *> base;
public:
static void Start();//응용 시작 - 진입점에서 호출하는 정적 메서드
virtual void ComeBack(Man *man);//학생 복귀
private:
EhNara(void);
~EhNara(void);
void Initialize(); //초기화
void Run(); //사용자와 상호 작용
void Exit(); //해제화
int SelectMenu(); //메뉴 출력 및 선택
void MakeStudent(); //학생 생성
void MoveFocus(); //초점 이동
void MoveStudent(); //학생 이동
void ViewAll(); //전체 보기
Place *SelectPlace();//장소 선택
Student *SelectStudent();//이동할 학생 선택
void EraseStudent(Student *stu);//학생 제거
void ViewStudents();//전체 학생 정보 보기
void ViewPlaces();//전체 장소 정보 보기
};
//EhNara.cpp
#include "EhNara.h"
#include "School.h"
#include "Downtown.h"
#include "Village.h"
EhNara EhNara::app;//단일체
void EhNara::Start()//응용 시작 - 진입점에서 호출하는 정적 메서드
{
app.Initialize();
app.Run();
app.Exit();
}
EhNara::EhNara(void)
{
}
EhNara::~EhNara(void)
{
}
void EhNara::Initialize()
{
sf = new StuFactory();//학생 공장 생성
//장소 개체 생성
places[PI_SCHOOL] = new School(*this);
places[PI_DOWNTOWN] = new Downtown(*this);
places[PI_VILLAGE] = new Village(*this);
}
void EhNara::Run()
{
int key = 0;
while((key = SelectMenu())!=ESC)
{
switch(key)
{
case F1: MakeStudent(); break;
case F2: MoveFocus(); break;
case F3: MoveStudent(); break;
case F4: ViewAll(); break;
default: cout<<"잘못 선택하였습니다."<<endl; break;
}
cout<<"아무 키나 누르세요."<<endl;
ehglobal::getkey();
}
}
void EhNara::Exit() //해제화
{
for(int i = 0; i<PI_MAX; i++)//모든 장소 개체 해제
{
delete places[i];
}
delete sf;//학생 공장 개체 소멸
}
int EhNara::SelectMenu() //메뉴 출력 및 선택
{
ehglobal::clrscr();
cout<<"이에이치 나라 메뉴"<<endl;
cout<<"F1: 학생 생성 F2: 초점 이동 F3: 학생 이동 F4: 전체 보기 ESC: 프로그램 종료"<<endl;
return ehglobal::getkey();
}
void EhNara::MakeStudent() //학생 생성
{
cout<<"생성할 학생 유형을 선택하세요. [1]:학사학생 [2]:마법학생 [3]:운동학생"<<endl;
int stype;
cin>>stype;
if((stype<1)||(stype>3))//잘못 선택하였을 때
{
cout<<"잘못 선택하였습니다."<<endl;
return;
}
cout<<"학생 이름:";
string name;
cin>>name;
Student *stu = sf->MakeStudent(stype,name);//학생 생성 요청
base.PushBack(stu);//생성한 학생 보관
}
void EhNara::MoveFocus() //초점 이동
{
Place *place = SelectPlace();//장소 선택
if(place==0)
{
cout<<"잘못 선택하였습니다."<<endl;
return;
}
place->Run();//장소의 상호 작용
}
void EhNara::MoveStudent() //학생 이동
{
Place *place = SelectPlace();//이동할 장소 선택
if(place==0)//잘못 선택하였을 때
{
cout<<"잘못 선택하였습니다."<<endl;
return;
}
Student *stu = SelectStudent();//이동할 학생 선택
if(stu == 0)
{
cout<<"잘못 선택하였습니다."<<endl;
return;
}
EraseStudent(stu);//학생 제거
place->InStudent(stu);//선택한 장소로 학생 이동
}
void EhNara::ViewAll() //전체 보기
{
ViewStudents();//전체 학생 정보 보기
ViewPlaces();//전체 장소 정보 보기
}
void EhNara::ViewStudents()//전체 학생 정보 보기
{
size_t size = base.GetSize();//보관 개수를 얻어온다.
for(size_t i = 0; i<size; ++i)//i를 0~size-1까지 증가
{
base[i]->View();//학생 정보 출력
}
}
void EhNara::ViewPlaces()//전체 장소 정보 보기
{
for(int i = 0; i<PI_MAX; i++)
{
places[i]->View();//장소 정보 출력
}
}
Place *EhNara::SelectPlace()//장소 선택
{
cout<<"장소를 선택하세요."<<endl;
cout<<"1: 학교 2: 다운타운 3: 주거지"<<endl;
int pi=0;
cin>>pi;
if((pi<1)&&(pi>PI_MAX))//유효한 선택이 아닐 때
{
return 0;
}
return places[pi-1];
}
Student *EhNara::SelectStudent()//이동할 학생 선택
{
cout<<"선택할 학생의 주민번호:";
int pn=0;
cin>>pn;
size_t size = base.GetSize();//보관한 학생 수 구하기
for(size_t i=0;i<size;++i)
{
if(base[i]->GetPN() == pn)//학생 주민번호와 입력한 주민번호가 같을 때
{
return base[i];
}
}
return 0;
}
void EhNara::EraseStudent(Student *stu)//학생 제거
{
size_t size = base.GetSize();//보관한 학생 수 구하기
for(size_t i=0;i<size;++i)
{
if(base[i]==stu)//보관한 학생과 입력 인자로 받은 학생이 같을 때
{
base.RemoveAt(i);//해당 인덱스에 보관한 개체 지우기
return;
}
}
}
void EhNara::ComeBack(Man *man)//학생 복귀
{
Student *stu = dynamic_cast<Student *>(man);
if(stu == 0)
{
throw "Student 형식이 아닙니다.";
}
base.PushBack(stu);//순차 보관
}
//Program.cpp
#include "EhNara.h"
int main()
{
EhNara::Start();
return 0;
}
실행 결과
공부하다
본문
[디딤돌 C++] 68. 최종 실습 – 개발 공정 및 시나리오
[디딤돌 C++] 69. 최종 실습 – 요구 분석 및 정의
[디딤돌 C++] 70. 최종 실습 – 설계1(클래스 다이어그램)
[디딤돌 C++] 71. 최종 실습 – EHNARA 뼈대
[디딤돌 C++] 73. 최종 실습 – 확장 가능한 순차 배열
[디딤돌 C++] 74. 최종 실습 – 클래스 추가하기
[디딤돌 C++] 75. 최종 실습 – 초기화 및 해제화
'C++ > 디딤돌 C++' 카테고리의 다른 글
[C++ 소스] 실현(REALIZATION) 관계, IStudy 인터페이스와 Student 클래스 (0) | 2016.12.18 |
---|---|
[C++ 소스] 의존(DEPENDENCY) 관계, 공장과 상품 (0) | 2016.12.18 |
[C++ 소스] 연관(ASSOCIATION) 관계, 의사와 약사 (0) | 2016.12.18 |
[C++ 소스] 직접 연관(DIRECTED ASSOCIATION) 관계, 회사와 직원 (0) | 2016.12.18 |
[C++ 소스] 구성 관계(Composition Relation), 사람과 눈 (0) | 2016.12.18 |