[카테고리:] <span>디딤돌 C++</span>

//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 &ic;
    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++를 마칠게요. 모두 행복한 엔지니어 생활하시길 바랄게요.

디딤돌 C++