[실습으로 다지는 C#] 학생 키우기 – 학생 구현 및 제어

안녕하세요. 언제나 휴일, 언휴예요.

이번 실습할 시나리오는 학생 개체 1명을 생성한 후에 메뉴를 통해 제어하는 프로그램입니다.

다음은 실습 시나리오입니다.

초기화(Init)
    학생 개체 생성(1명)
사용자와 상호작용(Run)
    F1: 공부하기
    F2: 강의받기
    F3: 잠자기
    F4: 휴식하기
    F5: 음료마시기
    F6: 노래하기
    F7: 학생 상태 출력

 다음은 정의할 학생 클래스 다이어그램입니다.

학생 클래스 다이어그램

학생 형식의 멤버 필드입니다.

pn: 주민번호(순차부여)
name: 이름(생성 시 전달)
iq: 아이큐(0~200, 초기 100)
hp: 체력(0~200, 초기 100)
stress: 스트레스(0~100, 초기 0)
scnt: 연속으로 공부한 횟수(0~5)
     "공부하다.", "강의받다"를 할 때는 1 증가, 기타 행동할 때는 0으로 리셋
lastpn: 가장 최근에 부여한 주민번호(정적 멤버)
각 멤버 필드 값 가져오기 블록 제공(속성)

학생 클래스의 메서드입니다. 메서드 이름 뒤의 값은 각 행동을 했을 때 변화하는 수치들입니다.

생성자(이름)
Study: 체력 -5, 아이큐 scnt, 스트레스 2 
ListenLecture: 체력 3, 아이큐 scnt, 스트레스 scnt
Sleep: 체력 10, 스트레스 -5
Relax : 체력 3, 스트레스 -25
Drink : 체력 5, 지력 -10 , 스트레스 2
Sing : 체력 10, 지력 scnt-5, 스트레스 5-scnt

 학생의 체력, 아이큐, 스트레스, 연속으로 공부한 횟수는 정해진 값이죠. 이러한 값들은 상수 멤버로 정의하세요. 여기에서는 별도의 정적 클래스를 정의하기로 할게요.

namespace 학생_키우기_Part1.학생_제어
{
    static class StuConst
    {
        internal const int MIN_IQ = 0;
        internal const int MAX_IQ = 200;
        internal const int DEF_IQ = 100;

        internal const int MIN_HP = 0;
        internal const int MAX_HP = 200;
        internal const int DEF_HP = 100;

        internal const int MIN_STRESS = 0;
        internal const int MAX_STRESS = 100;
        internal const int DEF_STRESS = 0;

        internal const int MAX_SCNT = 5;
    }
}

학생 클래스에서 pn은 변하지 않는 값이네요. 읽기 전용으로 표현합시다.

아이큐, 체력, 스트레스, 연속으로 공부한 횟수는 특정 범위 내에서 제어해야 합니다. 이를 위해 설정하는 부분에서의 로직이 필요하죠. 따라서 멤버 필드를 별도로 선언하고 대응하는 속성을 정의하세요. 물론 set 블록에서 약속한 범위 내에서 동작하게 구현하셔야 합니다.

가장 최근에 부여한 주민번호는 정적 멤버로 구현합니다.

여기까지 표현한다면 다음처럼 표현할 수 있을 거예요.

    class Student
    {
        readonly int pn;
        internal string Name
        {
            get;
            private set;
        }
        int iq;
        internal int IQ
        {
            get
            {
                return iq;
            }
            private set
            {
                if(value>StuConst.MAX_IQ)
                {
                    value = StuConst.MAX_IQ;
                }
                if(value<StuConst.MIN_IQ)
                {
                    value = StuConst.MIN_IQ;
                }
                iq = value;
            }
        }
        int hp;
        internal int HP
        {
            get
            {
                return hp;
            }
            private set
            {
                if(value > StuConst.MAX_HP)
                {
                    value = StuConst.MAX_HP;
                }
                if(value < StuConst.MIN_HP)
                {
                    value = StuConst.MIN_HP;
                }
                hp = value;
            }
        }
        int stress;
        internal int Stress
        {
            get
            {
                return stress;
            }
            private set
            {
                if(value > StuConst.MAX_STRESS)
                {
                    value = StuConst.MAX_STRESS;
                }
                if(value < StuConst.MIN_STRESS)
                {
                    value = StuConst.MIN_STRESS;
                }
                stress = value;
            }
        }
             
        int scnt;
        internal int SCnt
        {
            get
            {
                return scnt;
            }
            private set
            {
                if(value < StuConst.MAX_SCNT)
                {
                    scnt = value;
                }
            }
        }
        static int lastpn;
    }

이제 멤버 메서드에서는 속성을 통해 시나리오에 맞게 값을 변경하면 메서드 구현은 쉽게 할 수 있겠죠.

다음은 멤버 메서드까지 구현한 Student 클래스 소스 코드입니다.

using System;
namespace 학생_키우기_Part1.학생_제어
{
    class Student
    {
        readonly int pn;
        internal string Name
        {
            get;
            private set;
        }
        int iq;
        internal int IQ
        {
            get
            {
                return iq;
            }
            private set
            {
                if(value>StuConst.MAX_IQ)
                {
                    value = StuConst.MAX_IQ;
                }
                if(value<StuConst.MIN_IQ)
                {
                    value = StuConst.MIN_IQ;
                }
                iq = value;
            }
        }
        int hp;
        internal int HP
        {
            get
            {
                return hp;
            }
            private set
            {
                if(value > StuConst.MAX_HP)
                {
                    value = StuConst.MAX_HP;
                }
                if(value < StuConst.MIN_HP)
                {
                    value = StuConst.MIN_HP;
                }
                hp = value;
            }
        }
        int stress;
        internal int Stress
        {
            get
            {
                return stress;
            }
            private set
            {
                if(value > StuConst.MAX_STRESS)
                {
                    value = StuConst.MAX_STRESS;
                }
                if(value < StuConst.MIN_STRESS)
                {
                    value = StuConst.MIN_STRESS;
                }
                stress = value;
            }
        }
             
        int scnt;
        internal int SCnt
        {
            get
            {
                return scnt;
            }
            private set
            {
                if(value < StuConst.MAX_SCNT)
                {
                    scnt = value;
                }
            }
        }
        static int lastpn;
        internal Student(string name)
        {
            Name = name;
            lastpn++;
            pn = lastpn;
            IQ = StuConst.DEF_IQ;
            HP = StuConst.DEF_HP;
            Stress = StuConst.DEF_STRESS;
        }
        internal void Study()
        {
            HP -= 5;
            IQ += SCnt;
            Stress += 2;
            SCnt++;
        }
        internal void ListenLecture()
        {
            HP += 3;
            IQ += SCnt;
            Stress += SCnt;
            SCnt++;
        }
        internal void Sleep()
        {
            HP += 10;
            Stress -= 5;
            SCnt = 0;
        }
        internal void Relax()
        {
            HP += 3;
            Stress -= 25;
            SCnt = 0;
        }
        internal void Drink()
        {
            HP += 5;
            IQ -= 10;
            Stress += 2;
            SCnt = 0;
        }
        internal void Sing()
        {
            HP += 10;
            IQ += (SCnt - 5);
            Stress += (5 - SCnt);
            SCnt = 0;
        }
        public override string ToString()
        {
            return string.Format("{0}<{1}>", Name, pn);
        }
    }
}

사용자와 상호작용을 담당하는 Application 클래스를 작성하는 것은 이전 강의에서 다루었었죠. 다시 한 번 복습한다고 생각하시고 작성해 보세요.

using System;

namespace 학생_키우기_Part1.학생_제어
{
    class Application
    {
        #region 단일체
        internal static Application Singleton
        {
            get;
            private set;
        }
        static Application()
        {
            Singleton = new Application();
        }
        Application()
        {
        }
        #endregion 단일체


        Student student = null;
        internal void Init()
        {
            Console.WriteLine("학생 키우기 Part1 - 학생 제어");
            Console.WriteLine("생성할 학생 이름을 입력하세요.");
            Console.Write("이름:");
            string name = Console.ReadLine();
            student = new Student(name);
            Console.WriteLine("아무 키나 누르면 시작합니다.");
            Console.ReadKey(true);
        }

        internal void Run()
        {
            ConsoleKey key = ConsoleKey.NoName;
            while ((key = SelectMenu()) != ConsoleKey.Escape)//반복((키=메뉴 선택())!=종료키)
            {
                switch (key) //선택한 키에 따라
                {
                    case ConsoleKey.F1: Study(); break;
                    case ConsoleKey.F2: ListenLecture(); break;
                    case ConsoleKey.F3: Sleep(); break;
                    case ConsoleKey.F4: Relax(); break;
                    case ConsoleKey.F5: Drink(); break;
                    case ConsoleKey.F6: Sing(); break;
                    case ConsoleKey.F7: View(); break;
                    default: Console.WriteLine("잘못 선택하였습니다."); break;//다른 키: 잘못 선택한 것을 통보
                }
                Console.WriteLine("아무 키나 누르세요.");
                Console.ReadKey(true);//사용자가 결과 확인할 기회를 부여(아무 키나 누를 때까지 대기)
            }
        }

        private void View()
        {
            Console.WriteLine("===  {0}  ===", student);
            Console.WriteLine("IQ:{0} HP:{0} Stress:{2} SCNT:{3}", student.IQ, student.HP, student.Stress, student.SCnt);
        }

        private void Sing()
        {
            Console.WriteLine("{0} 노래하다.", student);
            student.Sing();
        }

        private void Drink()
        {
            Console.WriteLine("{0} 마시다.", student);
            student.Drink();
        }

        private void Relax()
        {
            Console.WriteLine("{0} 휴식하다.", student);
            student.Relax();
        }

        private void Sleep()
        {
            Console.WriteLine("{0} 잠자다.", student);
            student.Sleep();
        }

        private void ListenLecture()
        {
            Console.WriteLine("{0} 강의받다.", student);
            student.ListenLecture();
        }

        private void Study()
        {
            Console.WriteLine("{0} 공부하다.", student);
            student.Study();
        }

        private ConsoleKey SelectMenu()
        {
            Console.Clear();
            Console.WriteLine("학생 키우기 메뉴");
            Console.WriteLine("{0}:공부하기", ConsoleKey.F1);
            Console.WriteLine("{0}:강의받기", ConsoleKey.F2);
            Console.WriteLine("{0}:잠자기", ConsoleKey.F3);
            Console.WriteLine("{0}:휴식하기", ConsoleKey.F4);
            Console.WriteLine("{0}:마시기", ConsoleKey.F5);
            Console.WriteLine("{0}:노래하기", ConsoleKey.F6);
            Console.WriteLine("{0}:정보보기", ConsoleKey.F7);
            Console.WriteLine("종료를 원하시면 {0}를 누르세요.", ConsoleKey.Escape);
            return Console.ReadKey(true).Key;
        }
    }
}

//https://ehpub.co.kr
//학생 키우기 Part1. 학생 제어
namespace 학생_키우기_Part1.학생_제어
{
    class Program
    {
        static void Main(string[] args)
        {
            Application app = Application.Singleton;
            app.Init();
            app.Run();
        }
    }
}