본문 바로가기
프로그래밍/C++

C++ ] 클래스를 활용한 자판기 (2)

by eteo 2022. 6. 16.


VendingMachine.h

#define DRINKNUM 4
#define MAXSTOCK 4

struct _DRINK {
	const char* name;
	int price;
	int stock;
};

class VendingMachine
{
private:
	_DRINK drink[DRINKNUM];
	int MyMoney;
	int MinPrice;

public:
	VendingMachine(const char* name1, int price1, const char* name2, int price2, const char* name3, int price3, const char* name4, int price4);
	void showList();
	void chkMinPrice();
	int GetMoney() const;
	bool SetMoney(int money);
	int takeMoney();
	bool sale();

};

 

클래스 VendingMachine 은 멤버변수로 구조체배열인 drink와 MyMoney, MinPrice를 가진다.

 

생성자에서 음료수 명은 수정하지 않는다는 가정하에 const char * 로 리터럴 문자열을 받는다.

 

일단 getter, setter는 GetMoney, SetMoney 함수만 만들어 뒀는데 나중에 추가할 예정이다.

 

 

main.h

#ifndef __MAIN_H__
#define __MAIN_H__

#include "VendingMachine.h"

enum class Status {
	SELECTMACHINE,
	MONEYINPUT,
	SALE,
};

bool SelectVender(VendingMachine& vender1, VendingMachine& vender2, VendingMachine& selected);

#endif

 

자판기 두 대중 한대를 선택하게끔하는 함수 SelectVender와 자판기의 상태를 표현하는 enum class Status를 두었다.

 

VendingMachine.cpp

#include "VendingMachine.h"
#include <iostream>
#include <windows.h>

using namespace std;

vendingMachine::vendingMachine(const char* name1, int price1, const char* name2, int price2, const char* name3, int price3, const char* name4, int price4)
	: MyMoney(0), MinPrice(9999)
{
	drink[0].name = name1;
	drink[0].price = price1;
	drink[1].name = name2;
	drink[1].price = price2;
	drink[2].name = name3;
	drink[2].price = price3;
	drink[3].name = name4;
	drink[3].price = price4;

	for (int i = 0; i < DRINKNUM; i++) {
		drink[i].stock = MAXSTOCK;
	}
}

void vendingMachine::showList(void) {
	cout << drink[0].name << " " << drink[0].price << "," << drink[1].name << " " << drink[1].price << ","
		<< drink[2].name << " " << drink[2].price << "," << drink[3].name << " " << drink[3].price << endl;
}


void vendingMachine::chkMinPrice(void) {
	int min = drink[0].price;
	for (int i = 0; i < DRINKNUM; i++) {
		min = (drink[i].price < min) ? drink[i].price : min;
	}
	MinPrice= min;
}

int vendingMachine::GetMoney() const {
	return MyMoney;
}
bool vendingMachine::SetMoney(int money) {
	if (money < 0 || money > 10000) {
		cout << "잘못된 금액을 투입하셨습니다." << endl;
		Sleep(500);
		return false;
	}
	MyMoney = money;
	return true;
}

int vendingMachine::takeMoney(void) {
	int money;
	system("cls");
	cout << "음료수 자판기==================================" << endl;
	cout << "돈을 투입해주세요: ";
	cin >> money;
	return money;
}

bool vendingMachine::sale() {

	// 잔액이 음료수 중 최저가보다 작은 경우 바로 반환
	if (MyMoney < MinPrice) {		
		cout << endl << "음료가 나옵니다." << endl;
		cout << "반환구에서 구입하신 음료와 거스름돈을 가져가세요." << endl;
		cout << "[ 거스름돈: " << MyMoney << "원 ]" << endl;
		system("pause");
		return 1;
	}
	
	system("cls");
	cout << "[ 현재금액: " << MyMoney << "원 ]" << endl;

	int select = 0;

	for (int i = 0; i < DRINKNUM; i++) {

		printf("%d. %-10s %15d\n", i + 1, drink[i].name, drink[i].price);

	}
	cout << "----------------------------------------------" << endl << endl;
	printf("구입할 음료수를 선택해주세요: _ (음료를 꺼내려면 -1을 선택해주세요)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
	cin >> select;

	// 사용자가 -1 선택한 경우 현재 잔액 반환
	if (select == -1) {
		cout << "반환구에서 구입하신 음료와 거스름돈을 가져가세요." << endl;
		cout << "[ 거스름돈: " << MyMoney << "원 ]" << endl << endl;
		system("pause");
		return 1;
	}

	if (select <= 0 || select > DRINKNUM) {
		cout << "잘못 입력하셨습니다." << endl;
		Sleep(500);
		return 0;
	}

	// 선택한 음료의 재고가 없거나 잔액이 부족한 경우가 아니라면 현재잔액에서 선택음료 가격 차감하고 재고 감소시킴
	if (MyMoney - drink[select - 1].price < 0) {
		cout << endl;
		cout << "잔액이 부족하여 해당제품은 구입할 수 없습니다. " << endl;
	}
	else if (drink[select - 1].stock <= 0) {
		cout << endl;
		cout << "재고가 부족하여 해당제품은 구입할 수 없습니다. " << endl;
	}
	else {
		MyMoney -= drink[select - 1].price;
		drink[select - 1].stock--;		
	}

	return 0;

}


생성자를 조금 정돈시켜서 다시 만들어보려고한다. 그리고 다음엔 거스름돈을 돌려주는 함수를 따로 뺄 생각중이다.

 

 

Main.cpp

#include <iostream>
#include "main.h"
#include "VendingMachine.h"
#include <windows.h>



using namespace std;

int main(void) {

	VendingMachine vender1("콜라",700,"사이다",800,"맥콜",900,"환타",1100);
	VendingMachine vender2("밀크티", 900, "우롱티", 600, "솔의눈", 1200, "우유", 800);

	VendingMachine& Selected = vender1;

	Status salestatus = Status::SELECTMACHINE; // enum class
	
	while (1) {
		if (salestatus == Status::SELECTMACHINE) {
			if (SelectVender(vender1, vender2, Selected)) {	// 자판기 1, 2 중 선택
				Selected.chkMinPrice();	// 최저가 확인
				salestatus = Status::MONEYINPUT;
			}		
		}
		else if (salestatus == Status::MONEYINPUT) {
			if (Selected.SetMoney(Selected.takeMoney())) {	// 돈 입력받음
				salestatus = Status::SALE;
			}
		}
		else if (salestatus == Status::SALE) {
			if (Selected.sale()) {							// 판매중
				salestatus = Status::SELECTMACHINE;
			}
		}
	}
	return 0;
}


bool SelectVender(VendingMachine& vender1, VendingMachine& vender2, VendingMachine& selected) {

	while (1) {
		int select;
		system("cls");
		cout << ">> 자판기를 선택해 주세요" << endl;
		cout << "자판기1 : ";
		vender1.showList();
		cout << "자판기2 : ";
		vender2.showList();
		cout << "[_]\b\b";
		cin >> select;
		if (select == 1) {
			selected = vender1;
			return true;
		}
		else if (select == 2) {
			selected = vender2;
			return true;
		}
		else {				
			cout << "다시 선택해 주세요." << endl;			
			Sleep(500);
			return false;
		}
	}
}

 

while문은 크게 SELECTMACHINE, MONEYINPUT, SALE 세가지 상태로 구분된다.

 

VendingMachine& Selected = vender1; 은 참조자는 선언과 동시에 초기화되어야 하기 때문에 임시로 vender1을 넣어준 것이고 아래 while문에서 어차피 사용자가 제대로 vender 선택을 했을 때만 다음 단계로 넘어가기 때문에 문제가 없다.

 

모든 재고가 0일경우 바로 반환하게끔 추가 예정.