C++/디딤돌 C++

[C++ 소스] 최종 프로그램 실습(학교, 도서관, 강의실, 학생 등)

언제나휴일 2016. 12. 21. 08:27
반응형

[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 &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++] 68. 최종 실습개발 공정 시나리오

[딤돌 C++] 69. 최종 실습요구 분석 정의

[디딤돌 C++] 70. 최종 실습설계1(클래스 다이어그램)

[디딤돌 C++] 71. 최종 실습 – EHNARA 뼈대

[디딤돌 C++] 72. 최종 실습프로토 타이핑

[디딤돌 C++] 73. 최종 실습확장 가능한 순차 배열

[디딤돌 C++] 74. 최종 실습클래스 추가하기

[디딤돌 C++] 75. 최종 실습초기화 해제화

[디딤돌 C++] 76. 최종 실습학생 생성

[디딤돌 C++] 77. 최종 실습학생 이동

[디딤돌 C++] 78. 최종 실습전체 보기

[디딤돌 C++] 79. 최종 실습학생 복귀

[디딤돌 C++] 80. 최종 실습강의 시작

[디딤돌 C++] 81. 최종 실습도서관 가기

[디딤돌 C++] 82. 최종 실습소등

[디딤돌 C++] 83. 최종 실습거실로 가기

[디딤돌 C++] 84. 최종 실습파티

[디딤돌 C++] 85. 최종 실습노래방 가기

[디딤돌 C++] 86. 최종 실습다이어그램




반응형