C++.(P.4) 소맥 프로젝트(Soju & Beer) hot fixed

1. 개요

술자리를 가진 후 마신 소주-맥주의 종류, 병수에 따른 금액과 알코올 도수를 이용하여

  1. 음주운전 측정기 예상(혈중 알코올 농도)

  2. 금액 계산방법 결정(1/n, 1인 몰아주기)

의 기능을 할 수 있는 클래스 만들기.


2. Algorithm (pretty pseudo like)

  • 맥주, 소주, 소맥 세가지 클래스중 소주의 정보를 담은 소맥클래스를 맥주 클래스의 유도클래스로 설정한다.(소맥 is 맥주)
  • 맥주, 소맥 클래스를 entity class로 여기며, 적절한 변수설정 / 음주 테스트, 계산방법 결정 기능 함수 제작을 위한 멤버함수 생성.
  • 기능클래스(controller class)를 만들며 적절한 함수 생성.

3. Code

아직 다수의 객체를 다룸에 있어 어려움이 있다. 이에 하나의 파일 main.cpp에 몰아서 선언 및 정의를 진행하여 보았다.

  • 맥주 클래스(entity1)
#include<iostream>
#include<cstring>
#include<ctime>
#include<cstdlib>
using namespace std;

class Beer // Entity1
{
// 맥주명, 맥주 양(ml OR cc), 도수, 가격, 수량
private:
	char* bname;
	int bcc;
	double bfreq;
	int bcost;
	int bnum;

public:
	Beer(const char* Bname, const int bnum)
		: bnum(bnum)
	{
    // 해당 맥주명에 따라 나머지 변수 초기화(한몸)
		if (strcmp(Bname, "카스") == 0)
		{
			int len1 = strlen(Bname) + 1;
			bname = new char[len1];
			strcpy(bname, Bname);
			bcc = 350;
			bfreq = 0.05;
			bcost = 4000;
		}
		else if (strcmp(Bname, "클라우드") == 0)
		{
			int len2 = strlen(Bname) + 1;
			bname = new char[len2];
			strcpy(bname, Bname);
			bcc = 400;
			bfreq = 0.045;
			bcost = 5000;
		}
		else if(strcmp(Bname, "테라")==0)
		{
			int len3 = strlen(Bname) + 1;
			bname = new char[len3];
			strcpy(bname, Bname);
			bcc = 500;
			bfreq = 0.08;
			bcost = 6000;
		}
    else if(strcmp(Bname, "안마셔요")==0)
		{
			int len3 = strlen("없음") + 1;
			bname = new char[len3];
			strcpy(bname, "없음");
			bcc = 0;
			bfreq = 0;
			bcost = 0;
		}
	}
// destructor
	~Beer()
	{
		delete[]bname;
	}
	int Getbvolume()
	{
		return bcc * bnum;
	}
	double Getblevel() // 혈중알콜 측정함수 재료
	{
		return bfreq * Getbvolume();
	}
	int Getbspend() // 계산방법 결정함수 재료
	{
		return bcost * bnum;
	}

	void Showb() 
	{
		cout << "맥주명 : " << bname << endl;
	}

  char * Getbname() // 맥주-소주 조합 출력함수 재료
  {
    return bname;
  }

  int Getbnum()
  {
    return bnum;
  }


};
  • 소맥 클래스(entity2)
class Sojubeer : public Beer // Entity2 & 유도클래스
{
// 소주명, 양, 도수, 가격, 수량
private:
	char* sname;
	int scc;
	double sfreq;
	int scost;
	int snum;
  int nman;
public:
	Sojubeer(const char* Sname, const char* Bname, int snum, int bnum,int nman)
		:Beer(Bname, bnum), snum(snum), nman(nman)
	{
    // 마찬가지 상표가 정해지면 나머지값 자동 초기화
		if (strcmp(Sname, "참이슬") == 0)
		{
			int len1 = strlen(Sname) + 1;
			sname = new char[len1];
			strcpy(sname, Sname);
			scc = 350;
			sfreq = 0.17;
			scost = 4500;
		}
		if (strcmp(Sname, "처음처럼") == 0)
		{
			int len2 = strlen(Sname) + 1;
			sname = new char[len2];
			strcpy(sname, Sname);
			scc = 400;
			sfreq = 0.18;
			scost = 5000;
		}
		else if(strcmp(Sname,"진로")==0)
		{
			int len3 = strlen(Sname) + 1;
			sname = new char[len3];
			strcpy(sname, Sname);
			scc = 450;
			sfreq = 0.2;
			scost = 6000;
		}
    else if(strcmp(Sname,"안마셔요")==0)
		{
			int len3 = strlen("없음") + 1;
			sname = new char[len3];
			strcpy(sname, "없음");
			scc = 0;
			sfreq = 0;
			scost = 0;
		}
	}
// new - delete destructor
	~Sojubeer()
	{
		delete[]sname;
	}
// 이하 함수생성의 목적은 Beer class 멤버함수 생성 목적과 동일
	double Getsblevel()
	{
		return ((Getblevel()) + (scc * snum * sfreq))*0.798 / 70 / 100 / nman ;
	}
	int Getsbspend()
	{
		return Getbspend() + scost * snum;
	}

	void Showsb()
	{
		cout << "소주명 : " << sname << endl;
		Showb();
	}
  
  char * Getsname()
  {
    return sname;
  }

  int Getsnum()
  {
    return snum;
  }
    int Getnman()
  {
    return nman;
  }
};
  • 기능 클래스(Controller)
class Areyouok  // Controller
{
private:
	int Drunkenlevel;
	int Spend;

public:
// 상차림판
	void Showmenu()
	{
		cout << "---------술차림----------" << endl;
		cout << "         <소주>            " << endl;
		cout << "소주명    cc     도수    가격" << endl;
		cout << "참이슬    350    0.17    4500" << endl;
		cout << "처음처럼  400    0.18    5000" << endl;
		cout << "진로      450    0.20    6000" << endl;
		cout << "         <맥주>            " << endl;
		cout << "맥주명    cc     도수    가격" << endl;
		cout << "카스      350    0.05    4000" << endl;
		cout << "클라우드  400    0.045   5000" << endl;
		cout << "테라      500    0.08    6000" << endl << endl;
	}
    // 음주측정 예상기능 함수
	void breathalyzer(Sojubeer & sojuman)
	{
    int sratio=sojuman.Getsnum();
    int bratio=sojuman.Getbnum();
    int smaller;

    if(sratio < bratio)
    {
      smaller=sratio;
    }
    else
    {
      smaller=bratio;
    }
if(sratio !=0 && bratio !=0)
{
// 약분
    for(int i=2 ;  i <= smaller ; i++)
    {
      if(sratio % i ==0 && bratio % i ==0)
      {
        while(1)
        {
          if(sratio % i !=0 || bratio % i !=0)
          {
            break;
          }
            sratio /= i;
            bratio /= i;
        }
      }
    }
}

		cout << "소:맥 비율 : " << sratio << " : " << bratio << endl << endl;
    cout << "----알콜 기준----\n취소 : > 0.08%\n정지 : > 0.03%" << endl;  
		if (sojuman.Getsblevel() >= 0.0008)
		{
			cout << "당신의 혈중알코올농도 : " << sojuman.Getsblevel()*100 << "% / 면허 취소 수준\n대리운전을 부르세요 -> 이수근의 대리운전 : 1577-1577" << endl;
		}
		else if (sojuman.Getsblevel() >= 0.0003)
		{
			cout << "혈중알코올농도 " << sojuman.Getsblevel()*100 << "% / 면허 정지 수준\n대리운전을 부르세요 -> 이수근의 대리운전 : 1577-1577" << endl;
		}
		else
		{
			cout << "혈중알코올 농도 " << sojuman.Getsblevel()*100 << "%, 운전 가능!" << endl;
		}
	}
/* 계산방식 결정기능 함수, 랜덤성을 부과하였으나 가격이 높을수록 몰아주기 확률은 줄어들어
   부담없이 할 수 있는 게임 */
	void Pay(Sojubeer& sojuman)
	{
    cout << "----------------------------------------------------\n결제방식 : " ;
		if (sojuman.Getsbspend() >= 10000 * rand())
		{
			cout << "n분의 1 / "<< "인당 " << sojuman.Getsbspend() / sojuman.Getnman() << "원" << endl;
		}
		else
		{
			cout << "몰아주기" << sojuman.Getsbspend()  << "원" << endl;
		}
	}
// 소-맥 상호표시 & 히든 워드 "테슬라", "테진아" 삽입!!
	void Showmix(Sojubeer & sojuman)
	{
    cout << endl;
    if(strcmp(sojuman.Getsname(), "참이슬")==0 && strcmp(sojuman.Getbname(),"테라")==0)
    {
      cout << "Hidden name : 테슬라" << endl;
    }
    else if(strcmp(sojuman.Getsname(),"참이슬")==0 && strcmp(sojuman.Getbname(), "테라")==0)
    {
      cout << "테진아" << endl;
    }
    else
		sojuman.Showsb();
	}
};
  • main.function
const int NAME_LEN=20;

int main()
{
// 컴퓨터 시각 할당(0.~초?단위 추측)
	srand((unsigned)time(NULL));
	Areyouok result; // 기능함수 사용변수 생성
	result.Showmenu(); // 메뉴판
	char sname[NAME_LEN], bname[NAME_LEN];
	int snum, bnum, nman;
    // 주문
	cout << "<소주주문>" << endl;
	cout << "소주명 / 수량 : "; cin >> sname;
  if(strcmp(sname, "안마셔요")==0)
    {
      snum=0;
    }
    else
    {
      cin >> snum;
    }
	cout << "<맥주주문>" << endl;
	cout << "맥주명 / 수량 : "; cin >> bname;
    if(strcmp(bname, "안마셔요")==0)
    {
      bnum=0;
    }
    else
    {
      cin >> bnum;
    }
    /* 사실 알코올농도 계산과정에서 남녀, 개인을 구분하였어야 간결함을 위해 하지만 이번엔 성인남성 표준몸무게를 기준으로 하였음을 알림 */
  cout << "남자 몇명이서? : "; cin >> nman; 
	Sojubeer sojuman(sname,bname, snum, bnum, nman);
	result.Showmix(sojuman);
	result.breathalyzer(sojuman);
	result.Pay(sojuman);
  return 0;
}

4. 결과

  • 러프하게 계산한거지만 "소주 한병 = 8잔기준 / 1명 1잔만 마셔도 면허 취소?? 적은가격임에 높은확률로 몰아주기가 나온 모습"
  • "20명이서 소주1병 / 맥주2병 치 소맥만 마셔도 all 면허 정지수준. 20명중 돈을내게 될 운안좋은이는 누구?"

  • "평균적인 술자리 모습, 값이 나오니 확실히 n분의 1 확률이 높아진듯하다! 요즘 소맥은 잘 안마시지만 마신다면 난 테-진-아(?)로 마신다.."


5. 느낀점

맥주 클래스에 공통성을 담아냄에 있어 맛이 안나는 느낌이다(인위적이다) 이 모델이 상속의 필요성을 완전히 대변한다고 볼 수도 없다. 하지만 즐겼으면 된것이다. entity / controller 를 구분하여 구현한것에 의미를 두며.. 다음 프로젝트는 좀 더 적합한 주제로 돌아오겠다.

좋은 웹페이지 즐겨찾기